From 8fd123992d746a3afa683b60790668757d0c9437 Mon Sep 17 00:00:00 2001 From: Paweł Kołodziejski Date: Tue, 6 Jan 2004 17:28:29 +0000 Subject: synced imuse digital with local tree svn-id: r12187 --- scumm/akos.cpp | 3 +- scumm/bundle.cpp | 972 ------------------------ scumm/bundle.h | 83 --- scumm/imuse_digi.cpp | 1450 ------------------------------------ scumm/imuse_digi.h | 149 ---- scumm/imuse_digi/.cvsignore | 1 + scumm/imuse_digi/dimuse.cpp | 576 ++++++++++++++ scumm/imuse_digi/dimuse.h | 154 ++++ scumm/imuse_digi/dimuse_bndmgr.cpp | 179 +++++ scumm/imuse_digi/dimuse_bndmgr.h | 72 ++ scumm/imuse_digi/dimuse_codecs.cpp | 698 +++++++++++++++++ scumm/imuse_digi/dimuse_sndmgr.cpp | 462 ++++++++++++ scumm/imuse_digi/dimuse_sndmgr.h | 126 ++++ scumm/imuse_digi/dimuse_tables.cpp | 583 +++++++++++++++ scumm/resource.cpp | 6 +- scumm/saveload.cpp | 4 +- scumm/script_v6.cpp | 5 +- scumm/script_v8.cpp | 23 +- scumm/scummvm.cpp | 2 +- scumm/smush/insane.cpp | 20 +- scumm/smush/smush_player.cpp | 2 +- scumm/sound.cpp | 11 +- scumm/string.cpp | 7 +- 23 files changed, 2878 insertions(+), 2710 deletions(-) delete mode 100644 scumm/bundle.cpp delete mode 100644 scumm/bundle.h delete mode 100644 scumm/imuse_digi.cpp delete mode 100644 scumm/imuse_digi.h create mode 100644 scumm/imuse_digi/.cvsignore create mode 100644 scumm/imuse_digi/dimuse.cpp create mode 100644 scumm/imuse_digi/dimuse.h create mode 100644 scumm/imuse_digi/dimuse_bndmgr.cpp create mode 100644 scumm/imuse_digi/dimuse_bndmgr.h create mode 100644 scumm/imuse_digi/dimuse_codecs.cpp create mode 100644 scumm/imuse_digi/dimuse_sndmgr.cpp create mode 100644 scumm/imuse_digi/dimuse_sndmgr.h create mode 100644 scumm/imuse_digi/dimuse_tables.cpp diff --git a/scumm/akos.cpp b/scumm/akos.cpp index c0b3570c4c..c47c1a9fd0 100644 --- a/scumm/akos.cpp +++ b/scumm/akos.cpp @@ -26,6 +26,7 @@ #include "scumm/akos.h" #include "scumm/bomp.h" #include "scumm/imuse.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/sound.h" namespace Scumm { @@ -1328,7 +1329,7 @@ void ScummEngine::akos_queCommand(byte cmd, Actor *a, int param_1, int param_2) case 3: if (param_1 != 0) { if (_features & GF_DIGI_IMUSE) - _sound->playSound(param_1); + _imuseDigital->startSfx(param_1); else _sound->addSoundToQueue(param_1); } diff --git a/scumm/bundle.cpp b/scumm/bundle.cpp deleted file mode 100644 index 921655458a..0000000000 --- a/scumm/bundle.cpp +++ /dev/null @@ -1,972 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2004 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - */ - -#include "stdafx.h" -#include "common/scummsys.h" -#include "scumm/scumm.h" -#include "scumm/bundle.h" - -namespace Scumm { - -#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 -}; - - -Bundle::Bundle() { - _compVoiceTable = NULL; - _compMusicTable = NULL; - - _bundleVoiceTable = NULL; - _bundleMusicTable = NULL; - - _numVoiceFiles = 0; - _numMusicFiles = 0; - - _lastSong = -1; - - initializeImcTables(); -} - -Bundle::~Bundle() { - free(_bundleVoiceTable); - free(_bundleMusicTable); - free(_compVoiceTable); - free(_compMusicTable); -} - -void Bundle::initializeImcTables() { - 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); - } -} - -bool Bundle::openVoiceFile(const char *filename, const char *directory) { - int32 tag, offset; - - if (_voiceFile.isOpen()) - return true; - - if (_voiceFile.open(filename, directory) == false) { - warning("Bundle: Can't open voice bundle file: %s", filename); - return false; - } - - tag = _voiceFile.readUint32BE(); - offset = _voiceFile.readUint32BE(); - _numVoiceFiles = _voiceFile.readUint32BE(); - - _bundleVoiceTable = (BundleAudioTable *) malloc(_numVoiceFiles * sizeof(BundleAudioTable)); - - _voiceFile.seek(offset, SEEK_SET); - - for (int32 i = 0; i < _numVoiceFiles; i++) { - char name[13], c; - int32 z = 0; - int32 z2; - - for (z2 = 0; z2 < 8; z2++) - if ((c = _voiceFile.readByte()) != 0) - name[z++] = c; - name[z++] = '.'; - for (z2 = 0; z2 < 4; z2++) - if ((c = _voiceFile.readByte()) != 0) - name[z++] = c; - name[z] = '\0'; - strcpy(_bundleVoiceTable[i].filename, name); - _bundleVoiceTable[i].offset = _voiceFile.readUint32BE(); - _bundleVoiceTable[i].size = _voiceFile.readUint32BE(); - } - - return true; -} - -void Bundle::closeVoiceFile() { - if (_voiceFile.isOpen()) { - _voiceFile.close(); - free(_bundleVoiceTable); - _bundleVoiceTable = NULL; - } -} - -bool Bundle::openMusicFile(const char *filename, const char *directory) { - int32 tag, offset; - - if (_musicFile.isOpen()) - return true; - - if (_musicFile.open(filename, directory) == false) { - warning("Bundle: Can't open music bundle file: %s", filename); - return false; - } - - tag = _musicFile.readUint32BE(); - offset = _musicFile.readUint32BE(); - _numMusicFiles = _musicFile.readUint32BE(); - - _bundleMusicTable = (BundleAudioTable *) malloc(_numMusicFiles * sizeof(BundleAudioTable)); - - _musicFile.seek(offset, SEEK_SET); - - for (int32 i = 0; i < _numMusicFiles; i++) { - char name[13], c; - int z = 0; - int z2; - - for (z2 = 0; z2 < 8; z2++) - if ((c = _musicFile.readByte()) != 0) - name[z++] = c; - name[z++] = '.'; - for (z2 = 0; z2 < 4; z2++) - if ((c = _musicFile.readByte()) != 0) - name[z++] = c; - name[z] = '\0'; - strcpy(_bundleMusicTable[i].filename, name); - _bundleMusicTable[i].offset = _musicFile.readUint32BE(); - _bundleMusicTable[i].size = _musicFile.readUint32BE(); - } - - return true; -} - -void Bundle::closeMusicFile() { - if (_musicFile.isOpen()) { - _musicFile.close(); - free(_bundleMusicTable); - _bundleMusicTable = NULL; - _lastSong = -1; - } -} - - -int32 Bundle::decompressVoiceSampleByIndex(int32 index, byte **comp_final) { - int32 i, tag, num, final_size, output_size; - byte *comp_input, *comp_output; - - if (_voiceFile.isOpen() == false) { - warning("Bundle: voice file is not open!"); - return 0; - } - - _voiceFile.seek(_bundleVoiceTable[index].offset, SEEK_SET); - tag = _voiceFile.readUint32BE(); - num = _voiceFile.readUint32BE(); - _voiceFile.readUint32BE(); - _voiceFile.readUint32BE(); - - if (tag != MKID_BE('COMP')) { - warning("Bundle: Compressed sound %d invalid (%s)", index, tag2str(tag)); - return 0; - } - - free(_compVoiceTable); - _compVoiceTable = (CompTable *)malloc(sizeof(CompTable) * num); - for (i = 0; i < num; i++) { - _compVoiceTable[i].offset = _voiceFile.readUint32BE(); - _compVoiceTable[i].size = _voiceFile.readUint32BE(); - _compVoiceTable[i].codec = _voiceFile.readUint32BE(); - _voiceFile.readUint32BE(); - } - - final_size = 0; - - comp_output = (byte *)malloc(0x2000); - - *comp_final = (byte *)malloc(0x2000 * num); - - for (i = 0; i < num; i++) { - // CMI hack: one more zero byte at the end of input buffer - comp_input = (byte *)malloc(_compVoiceTable[i].size + 1); - comp_input[_compVoiceTable[i].size] = 0; - - _voiceFile.seek(_bundleVoiceTable[index].offset + _compVoiceTable[i].offset, SEEK_SET); - _voiceFile.read(comp_input, _compVoiceTable[i].size); - - output_size = decompressCodec(_compVoiceTable[i].codec, comp_input, comp_output, _compVoiceTable[i].size); - assert(output_size <= 0x2000); - memcpy(*comp_final + final_size, comp_output, output_size); - final_size += output_size; - - free(comp_input); - } - free(comp_output); - - return final_size; -} - -int32 Bundle::decompressMusicSampleByIndex(int32 index, int32 number, byte *comp_final) { - int final_size; - byte *comp_input; - - if (_musicFile.isOpen() == false) { - warning("Bundle: music file is not open!"); - return 0; - } - - if (_lastSong != index) { - int i, tag, num; - _musicFile.seek(_bundleMusicTable[index].offset, SEEK_SET); - tag = _musicFile.readUint32BE(); - num = _musicFile.readUint32BE(); - _musicFile.readUint32BE(); - _musicFile.readUint32BE(); - - if (tag != MKID_BE('COMP')) { - warning("Bundle: Compressed sound %d invalid (%s)", index, tag2str(tag)); - return 0; - } - - free(_compMusicTable); - _compMusicTable = (CompTable *)malloc(sizeof(CompTable) * num); - - for (i = 0; i < num; i++) { - _compMusicTable[i].offset = _musicFile.readUint32BE(); - _compMusicTable[i].size = _musicFile.readUint32BE(); - _compMusicTable[i].codec = _musicFile.readUint32BE(); - _musicFile.readUint32BE(); - } - - _lastSong = index; - } - - // CMI hack: one more zero byte at the end of input buffer - comp_input = (byte *)malloc(_compMusicTable[number].size + 1); - comp_input[_compMusicTable[number].size] = 0; - - _musicFile.seek(_bundleMusicTable[index].offset + _compMusicTable[number].offset, SEEK_SET); - _musicFile.read(comp_input, _compMusicTable[number].size); - - final_size = decompressCodec(_compMusicTable[number].codec, comp_input, comp_final, _compMusicTable[number].size); - - free(comp_input); - - return final_size; -} - -int32 Bundle::decompressVoiceSampleByName(const char *name, byte **comp_final) { - int32 final_size = 0, i; - - if (_voiceFile.isOpen() == false) { - warning("Bundle: voice file is not open!"); - return 0; - } - - for (i = 0; i < _numVoiceFiles; i++) { - if (!scumm_stricmp(name, _bundleVoiceTable[i].filename)) { - final_size = decompressVoiceSampleByIndex(i, comp_final); - return final_size; - } - } - debug(2, "Failed finding voice %s", name); - return final_size; -} - -int32 Bundle::decompressMusicSampleByName(const char *name, int32 number, byte *comp_final) { - int32 final_size = 0, i; - - if (!name) { - warning("Bundle: decompressMusicSampleByName called with no name!"); - return 0; - } - - if (_musicFile.isOpen() == false) { - warning("Bundle: music file is not open!"); - return 0; - } - - for (i = 0; i < _numMusicFiles; i++) { - if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) { - final_size = decompressMusicSampleByIndex(i, number, comp_final); - return final_size; - } - } - warning("Couldn't find sample %s", name); - return final_size; -} - -int32 Bundle::getNumberOfMusicSamplesByIndex(int32 index) { - if (_musicFile.isOpen() == false) { - warning("Bundle: music file is not open!"); - return 0; - } - - _musicFile.seek(_bundleMusicTable[index].offset, SEEK_SET); - _musicFile.readUint32BE(); - return _musicFile.readUint32BE(); -} - -int32 Bundle::getNumberOfMusicSamplesByName(const char *name) { - int32 number = 0, i; - - if (_musicFile.isOpen() == false) { - warning("Bundle: music file is not open!"); - return 0; - } - - for (i = 0; i < _numMusicFiles; i++) { - if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) { - number = getNumberOfMusicSamplesByIndex(i); - return number; - } - } - warning("Couldn't find numsample %s", name); - return number; -} - -#define NextBit \ - do { \ - bit = mask & 1; \ - 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 Bundle::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: - warning("Bundle: Unknown codec %d!", (int)codec); - output_size = 0; - break; - } - - return output_size; -} - -} // End of namespace Scumm - -#ifdef __PALM_OS__ -#include "scumm_globals.h" - -_GINIT(Bundle) -_GSETPTR(Scumm::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM) -_GEND - -_GRELEASE(Bundle) -_GRELEASEPTR(GBVARS_IMCTABLE_INDEX, GBVARS_SCUMM) -_GEND - -#endif - - diff --git a/scumm/bundle.h b/scumm/bundle.h deleted file mode 100644 index 2c25c47653..0000000000 --- a/scumm/bundle.h +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2004 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - */ - -#ifndef BUNDLE_H -#define BUNDLE_H - -#include "common/scummsys.h" -#include "common/file.h" - -namespace Scumm { - -class Bundle { - -private: - - struct CompTable { - int32 offset; - int32 size; - int32 codec; - }; - - struct BundleAudioTable { - char filename[13]; - int32 size; - int32 offset; - }; - - CompTable *_compVoiceTable; - CompTable *_compMusicTable; - BundleAudioTable *_bundleVoiceTable; - BundleAudioTable *_bundleMusicTable; - int32 _numVoiceFiles; - int32 _numMusicFiles; - int32 _lastSong; - - byte _destImcTable[93]; - uint32 _destImcTable2[5697]; - - File _voiceFile; - File _musicFile; - - void initializeImcTables(); - - int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 size); - - int32 decompressVoiceSampleByIndex(int32 index, byte **comp_final); - int32 decompressMusicSampleByIndex(int32 index, int32 number, byte *comp_final); - int32 getNumberOfMusicSamplesByIndex(int32 index); - -public: - Bundle(); - ~Bundle(); - - bool openVoiceFile(const char *filename, const char *directory); - bool openMusicFile(const char *filename, const char *directory); - void closeVoiceFile(); - void closeMusicFile(); - - int32 decompressVoiceSampleByName(const char *name, byte **comp_final); - int32 decompressMusicSampleByName(const char *name, int32 number, byte *comp_final); - int32 getNumberOfMusicSamplesByName(const char *name); -}; - -} // End of namespace Scumm - -#endif diff --git a/scumm/imuse_digi.cpp b/scumm/imuse_digi.cpp deleted file mode 100644 index 6ca2fc1e15..0000000000 --- a/scumm/imuse_digi.cpp +++ /dev/null @@ -1,1450 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2001-2004 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - */ - -#include "stdafx.h" -#include "common/timer.h" -#include "scumm/actor.h" -#include "scumm/bundle.h" -#include "scumm/imuse_digi.h" -#include "scumm/scumm.h" -#include "scumm/sound.h" - -#include "sound/audiostream.h" -#include "sound/mixer.h" -#include "sound/voc.h" - -namespace Scumm { - -struct imuse_music_table { - int room; - int id; - int unk1; - int unk2; - int unk3; - int unk4; - char name[30]; - char title[30]; - char filename[13]; -}; - -struct imuse_music_map { - int room; - int table_index; - int unk1; - int unk2; - int unk3; - int unk4; -}; - -#ifdef __PALM_OS__ -// these games are currently not supported under PalmOS so we can save this space -// to prevent full data segement -static const imuse_music_map *_digStateMusicMap; -static const imuse_music_table *_digStateMusicTable; -static const imuse_music_table *_comiStateMusicTable; -static const imuse_music_table *_comiSeqMusicTable; -static const imuse_music_table *_digSeqMusicTable; -#else -static const imuse_music_map _digStateMusicMap[] = { - {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 } -}; - -static 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, "", "", ""} -}; - -static 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, "", "", "" } -}; - -static 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, "", "", ""} -}; - -static 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, "", "", ""} -}; - -#endif - -struct imuse_ft_music_table { - int index; - char audioname[15]; - int unk1; - int volume; - char name[30]; -}; - -#ifdef __PALM_OS__ -// these games are currently not supported under PalmOS so we can save this space -// to prevent full data segement -static const imuse_ft_music_table *_ftStateMusicTable; -static const imuse_ft_music_table *_ftSeqMusicTable; -#else -static const imuse_ft_music_table _ftStateMusicTable[] = { - {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, "" } -}; - -static 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, "" } -}; -#endif - -static uint32 decode12BitsSample(byte *src, byte **dst, uint32 size) { - uint32 loop_size = size / 3; - uint32 s_size = loop_size * 4; - byte *ptr = *dst = (byte *)malloc(s_size); - - uint32 tmp; - while (loop_size--) { - byte v1 = *src++; - byte v2 = *src++; - byte v3 = *src++; - tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000; - WRITE_BE_UINT16(ptr, tmp); ptr += 2; - tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; - WRITE_BE_UINT16(ptr, tmp); ptr += 2; - } - return s_size; -} - -IMuseDigital::Channel::Channel() - : idSound(-1), used(false), stream(0) { -} - -void IMuseDigital::timer_handler(void *refCon) { - IMuseDigital *imuseDigital = (IMuseDigital *)refCon; - imuseDigital->callback(); -} - -IMuseDigital::IMuseDigital(ScummEngine *scumm) - : _scumm(scumm) { - _pause = false; - - _nameBundleMusic = ""; - _musicBundleBufFinal = NULL; - _musicBundleBufOutput = NULL; - _musicDisk = 0; - - _bundle = new Bundle(); - - _scumm->_timer->installTimerProc(timer_handler, 1000000 / 25, this); -} - -IMuseDigital::~IMuseDigital() { - _scumm->_timer->removeTimerProc(timer_handler); - stopBundleMusic(); - - for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - _scumm->_mixer->stopHandle(_channel[l].handle); - delete _channel[l].stream; - _channel[l].stream = 0; - } - - delete _bundle; -} - -void IMuseDigital::callback() { - int l = 0; - - if (_pause || !_scumm) - return; - - for (l = 0; l < MAX_DIGITAL_CHANNELS;l ++) { - if (_channel[l].used) { - assert(_channel[l].stream); - - if (!_channel[l].handle.isActive() && _channel[l].started) { - debug(5, "IMuseDigital::callback(): stopped sound: %d", _channel[l].idSound); - delete _channel[l].stream; - _channel[l].stream = 0; - _channel[l].used = false; - continue; - } - - if (_channel[l].volFadeUsed) { - if (_channel[l].volFadeStep < 0) { - if (_channel[l].vol > _channel[l].volFadeDest) { - _channel[l].vol += _channel[l].volFadeStep; - if (_channel[l].vol < _channel[l].volFadeDest) { - _channel[l].vol = _channel[l].volFadeDest; - _channel[l].volFadeUsed = false; - } - if (_channel[l].vol == 0) { - _scumm->_mixer->stopHandle(_channel[l].handle); - } - } - } else if (_channel[l].volFadeStep > 0) { - if (_channel[l].vol < _channel[l].volFadeDest) { - _channel[l].vol += _channel[l].volFadeStep; - if (_channel[l].vol > _channel[l].volFadeDest) { - _channel[l].vol = _channel[l].volFadeDest; - _channel[l].volFadeUsed = false; - } - } - } - debug(5, "Fade: sound(%d), Vol(%d)", _channel[l].idSound, _channel[l].vol / 1000); - } - - if (_scumm->_mixer->isReady()) { - int pan = (_channel[l].pan != 64) ? 2 * _channel[l].pan - 127 : 0; - if (!_channel[l].started) { - _channel[l].started = true; - _scumm->_mixer->playInputStream(&_channel[l].handle, _channel[l].stream, true, _channel[l].vol / 1000, _channel[l].pan, -1, false); - } else { - _scumm->_mixer->setChannelVolume(_channel[l].handle, _channel[l].vol / 1000); - _scumm->_mixer->setChannelPan(_channel[l].handle, pan); - } - } - } - } -} - -void IMuseDigital::startSound(int sound, byte *voiceBundleData, AudioStream *input) { - debug(5, "IMuseDigital::startSound(%d)", sound); - int l, r; - - for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if (!_channel[l].used && !_channel[l].handle.isActive()) { - byte *ptr, *s_ptr; - if (sound != kTalkSoundID) { - s_ptr = ptr = _scumm->getResourceAddress(rtSound, sound); - if (ptr == NULL) { - warning("IMuseDigital::startSound(%d) NULL resource pointer", sound); - return; - } - } else if (voiceBundleData) { - s_ptr = ptr = voiceBundleData; - } else if (input) { - s_ptr = ptr = 0; - } else { - error("IMuseDigital::startSound() unknown condition"); - } - _channel[l].pan = 64; - _channel[l].vol = 127 * 1000; - _channel[l].volFadeDest = 0; - _channel[l].volFadeStep = 0; - _channel[l].volFadeDelay = 0; - _channel[l].volFadeUsed = false; - - _channel[l].numJumps = 0; - _channel[l].numRegions = 0; - _channel[l].numMarkers = 0; - - _channel[l].idSound = sound; - - if (input) { - // Do nothing here, we already have an audio stream - } else if (READ_UINT32(ptr) == MKID('Crea')) { - // Create an AudioStream - input = makeVOCStream(ptr); - } else if (READ_UINT32(ptr) == MKID('iMUS')) { - uint32 tag; - int32 size = 0; - - int freq, channels, bits; - int mixerFlags; - byte *data; - - ptr += 16; - freq = channels = bits = 0; - do { - tag = READ_BE_UINT32(ptr); ptr += 4; - switch(tag) { - case MKID_BE('FRMT'): - ptr += 12; - bits = READ_BE_UINT32(ptr); ptr += 4; - freq = READ_BE_UINT32(ptr); ptr += 4; - channels = READ_BE_UINT32(ptr); ptr += 4; - break; - case MKID_BE('TEXT'): - size = READ_BE_UINT32(ptr); ptr += 4; - if (_channel[l].numMarkers >= MAX_IMUSE_MARKERS) { - warning("IMuseDigital::startSound() Not enough space for Marker"); - ptr += size; - break; - } - strcpy(_channel[l].marker[_channel[l].numMarkers].name, (char *)ptr + 4); - _channel[l].numMarkers++; - ptr += size; - break; - case MKID_BE('REGN'): - size = READ_BE_UINT32(ptr); ptr += 4; - if (_channel[l].numRegions >= MAX_IMUSE_REGIONS) { - warning("IMuseDigital::startSound() Not enough space for Region"); - ptr += 8; - break; - } - _channel[l].region[_channel[l].numRegions].start = READ_BE_UINT32(ptr); ptr += 4; - _channel[l].region[_channel[l].numRegions].length = READ_BE_UINT32(ptr); ptr += 4; - _channel[l].numRegions++; - break; - case MKID_BE('STOP'): - ptr += 4; - _channel[l].offsetStop = READ_BE_UINT32(ptr); ptr += 4; - break; - case MKID_BE('JUMP'): - size = READ_BE_UINT32(ptr); ptr += 4; - if (_channel[l].numJumps >= MAX_IMUSE_JUMPS) { - warning("IMuseDigital::startSound() Not enough space for Jump"); - ptr += size; - break; - } - _channel[l].jump[_channel[l].numJumps].start = READ_BE_UINT32(ptr); ptr += 4; - _channel[l].jump[_channel[l].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4; - _channel[l].jump[_channel[l].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4; - _channel[l].jump[_channel[l].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4; - _channel[l].numJumps++; - break; - case MKID_BE('SYNC'): - size = READ_BE_UINT32(ptr); ptr += size + 4; - break; - case MKID_BE('DATA'): - size = READ_BE_UINT32(ptr); ptr += 4; - break; - default: - error("IMuseDigital::startSound(%d) Unknown sfx header '%s'", sound, tag2str(tag)); - } - } while (tag != MKID_BE('DATA')); - - if ((sound == kTalkSoundID) && voiceBundleData) { - if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) { - Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound"); - freq = (freq * a->talkFrequency) / 256; - _channel[l].pan = a->talkPan; - } - } - - uint32 header_size = ptr - s_ptr; - - _channel[l].offsetStop -= header_size; - if (bits == 12) { - _channel[l].offsetStop = (_channel[l].offsetStop / 3) * 4; - } - for (r = 0; r < _channel[l].numRegions; r++) { - _channel[l].region[r].start -= header_size; - if (bits == 12) { - _channel[l].region[r].start = (_channel[l].region[r].start / 3) * 4; - _channel[l].region[r].length = (_channel[l].region[r].length / 3) * 4; - } - } - if (_channel[l].numJumps > 0) { - for (r = 0; r < _channel[l].numJumps; r++) { - _channel[l].jump[r].start -= header_size; - _channel[l].jump[r].dest -= header_size; - if (bits == 12) { - _channel[l].jump[r].start = (_channel[l].jump[r].start / 3) * 4; - _channel[l].jump[r].dest = (_channel[l].jump[r].dest / 3) * 4; - } - } - } - - assert(channels == 1 || channels == 2); - - if (channels == 2) { - // FIXME / TODO: Is FLAG_REVERSE_STEREO really needed here? - // How do we know that it is needed? If we indeed have reasons - // to believe that it is needed, those should be documented in - // a comment here. And if the channels are reversed, then we - // might just swap them right here, instead of using the mixer - // flag - since we copy the data around anyway, swapping the - // channels should be little extra work (in fact, none for - // mono data, which includes the 12 bit compressed format). - - mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO; - } else { - mixerFlags = 0; - } - - if (bits == 12) { - mixerFlags |= SoundMixer::FLAG_16BITS; - size = decode12BitsSample(ptr, &data, size); - } else if (bits == 16) { - mixerFlags |= SoundMixer::FLAG_16BITS; - - // FIXME: For some weird reasons, sometimes we get an odd size, even though - // the data is supposed to be in 16 bit format... that makes no sense... - size &= ~1; - - data = (byte *)malloc(size); - memcpy(data, ptr, size); - } else if (bits == 8) { - mixerFlags |= SoundMixer::FLAG_UNSIGNED; - - data = (byte *)malloc(size); - memcpy(data, ptr, size); - } else - error("IMuseDigital::startSound(): Can't handle %d bit samples", bits); - - // Create an AudioStream - input = makeLinearInputStream(freq, mixerFlags | SoundMixer::FLAG_AUTOFREE, data, size, 0, 0); - } else { - error("IMuseDigital::startSound(): Unknown sound format"); - } - - // Set the audio stream for this new channel - _channel[l].stream = input; - - _channel[l].started = false; - _channel[l].used = true; - return; - } - } - warning("IMuseDigital::startSound(): All slots are full"); -} - -void IMuseDigital::stopSound(int sound) { - debug(5, "IMuseDigital::stopSound(%d)", sound); - for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if ((_channel[l].idSound == sound) && _channel[l].used) { - _scumm->_mixer->stopHandle(_channel[l].handle); - } - } -} - -void IMuseDigital::stopAllSounds() { - debug(5, "IMuseDigital::stopAllSounds"); - for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if (_channel[l].used) { - _scumm->_mixer->stopHandle(_channel[l].handle); - } - } -} - -void IMuseDigital::pause(bool p) { - for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if (_channel[l].used) { - _scumm->_mixer->pauseHandle(_channel[l].handle, p); - } - } - _pause = p; - pauseBundleMusic(p); -} - -void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) { - int cmd = a; - int sample = b; - int sub_cmd = c; - int chan = -1; - int l, r; - - if (!cmd) - return; - - switch (cmd) { - case 10: // ImuseStopAllSounds - debug(5, "ImuseStopAllSounds()"); - stopAllSounds(); - break; - case 12: // ImuseSetParam - switch (sub_cmd) { - case 0x500: // set priority - could be ignored - break; - case 0x600: // set volume - debug(5, "ImuseSetParam (0x600), sample(%d), volume(%d)", sample, d); - for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if ((_channel[l].idSound == sample) && _channel[l].used) { - _channel[l].vol = d * 1000; -// if (_channel[l].volFadeUsed) -// _channel[l].volFadeStep = (_channel[l].volFadeDest - _channel[l].vol) * 60 * 40 / (1000 * _channel[chan].volFadeDelay); - } - } - if (l == -1) { - debug(5, "ImuseSetParam (0x600), sample(%d) not exist in channels", sample); - return; - } - break; - case 0x700: // set pan - debug(5, "ImuseSetParam (0x700), sample(%d), pan(%d)", sample, d); - for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if ((_channel[l].idSound == sample) && _channel[l].used) { - _channel[l].pan = d; - } - } - if (l == -1) { - debug(5, "ImuseSetParam (0x700), sample(%d) not exist in channels", sample); - return; - } - break; - default: - warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd); - break; - } - break; - case 14: // ImuseFadeParam - switch (sub_cmd) { - case 0x600: // set new volume with fading - debug(5, "ImuseFadeParam - fade sample(%d), to volume(%d) with 60hz ticks(%d)", sample, d, e); - if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) { - stopSound(sample); - return; - } - for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if ((_channel[l].idSound == sample) && _channel[l].used) { - _channel[l].volFadeDelay = e; - _channel[l].volFadeDest = d * 1000; - _channel[l].volFadeStep = (_channel[l].volFadeDest - _channel[l].vol) * 60 * 40 / (1000 * e); - _channel[l].volFadeUsed = true; - debug(5, "ImuseFadeParam: vol %d, volDest %d, step %d", _channel[l].vol, d * 1000, _channel[l].volFadeStep); - } - } - if (chan == -1) { - debug(5, "ImuseFadeParam (0x600), sample %d not exist in channels", sample); - return; - } - break; - default: - warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd); - break; - } - break; - case 0x1000: // ImuseSetState - debug(5, "ImuseSetState (%d)", b); - if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) { - if (b == 1) - startSound(1); - else { - if (getSoundStatus(2) == 0) - startSound(2); - } - } else if (_scumm->_gameId == GID_DIG) { - if (b == 1000) { // STATE_NULL - stopBundleMusic(); - return; - } - for (l = 0; _digStateMusicMap[l].room != -1; l++) { - if (_digStateMusicMap[l].room == b) { - int music = _digStateMusicMap[l].table_index; - debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename); - if ((_digStateMusicTable[music].filename[0] != 0) && - (strcmp(_digStateMusicTable[_digStateMusicTable[music].unk3].filename, _nameBundleMusic) != 0) ) { - playBundleMusic(_digStateMusicTable[music].filename); - } - break; - } - } - } else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) { - if (b == 2) { - playBundleMusic("in1.imx"); - } else if (b == 4) { - playBundleMusic("in2.imx"); - } else if (b == 8) { - playBundleMusic("out1.imx"); - } else if (b == 9) { - playBundleMusic("out2.imx"); - } else if (b == 16) { - playBundleMusic("gun.imx"); - } else { - warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom); - } - } else if (_scumm->_gameId == GID_CMI) { - if (b == 1000) { // STATE_NULL - stopBundleMusic(); - return; - } - for (l = 0; _comiStateMusicTable[l].id != -1; l++) { - if ((_comiStateMusicTable[l].id == b)) { - debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename); - if (_comiStateMusicTable[l].filename[0] != 0) { - playBundleMusic(_comiStateMusicTable[l].filename); - } - break; - } - } - } else if (_scumm->_gameId == GID_FT) { - for (l = 0;; l++) { - if (_ftStateMusicTable[l].index == -1) { - return; - } - if (_ftStateMusicTable[l].index == b) { - debug(5, "Play imuse music: %s, %s", _ftStateMusicTable[l].name, _ftStateMusicTable[l].audioname); - if (_ftStateMusicTable[l].audioname[0] != 0) { - for (r = 0; r < _scumm->_numAudioNames; r++) { - if (strcmp(_ftStateMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) { - startSound(r); - parseScriptCmds(12, r, 1536, _ftStateMusicTable[l].volume, 0, 0, 0, 0); - } - } - } - } - } - } - break; - case 0x1001: // ImuseSetSequence - debug(5, "ImuseSetSequence (%d)", b); - if (_scumm->_gameId == GID_DIG) { - for (l = 0; _digSeqMusicTable[l].room != -1; l++) { - if (_digSeqMusicTable[l].room == b) { - debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename); - if (_digSeqMusicTable[l].filename[0] != 0) { - playBundleMusic(_digSeqMusicTable[l].filename); - } - break; - } - } - } else if (_scumm->_gameId == GID_CMI) { - for (l = 0; _comiSeqMusicTable[l].id != -1; l++) { - if (_comiSeqMusicTable[l].id == b) { - debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename); - if (_comiSeqMusicTable[l].filename[0] != 0) { - playBundleMusic(_comiSeqMusicTable[l].filename); - } - break; - } - } - } else if (_scumm->_gameId == GID_FT) { - for (l = 0; _ftSeqMusicTable[l].index != -1; l++) { - if (_ftSeqMusicTable[l].index == b) { - debug(5, "Play imuse music: %s, %s", _ftSeqMusicTable[l].name, _ftSeqMusicTable[l].audioname); - if (_ftSeqMusicTable[l].audioname[0] != 0) { - for (r = 0; r < _scumm->_numAudioNames; r++) { - if (strcmp(_ftSeqMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) { -// startSound(r); -// parseScriptCmds(12, r, 1536, _ftSeqMusicTable[l].volume, 0, 0, 0, 0); - } - } - } - } - } - } - break; - case 0x1002: // ImuseSetCuePoint - debug(5, "ImuseSetCuePoint (%d)", b); - break; - case 0x1003: // ImuseSetAttribute - debug(5, "ImuseSetAttribute (%d, %d)", b, c); - break; - case 0x2000: // ImuseSetMasterSFXVolume - debug(5, "ImuseSetMasterSFXVolume (%d)", b); - break; - case 0x2001: // ImuseSetMasterVoiceVolume - debug(5, "ImuseSetMasterVoiceVolume (%d)", b); - break; - case 0x2002: // ImuseSetMasterMusicVolume - debug(5, "ImuseSetMasterMusicVolume (%d)", b); - break; - default: - warning("IMuseDigital::doCommand DEFAULT command %d", cmd); - } -} - -int IMuseDigital::getSoundStatus(int sound) const { - debug(5, "IMuseDigital::getSoundStatus(%d)", sound); - for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) { - if ((_channel[l].idSound == sound) && _channel[l].used) { - return 1; - } - } - - return 0; -} - -void IMuseDigital::music_handler(void *refCon) { - ((IMuseDigital *)refCon)->bundleMusicHandler(); -} - -#define BUNDLE_MUSIC_ITER_PER_SEC 10 - -void IMuseDigital::playBundleMusic(const char *song) { - if (!_scumm->_mixer->isReady()) { - return; - } - - if (_nameBundleMusic[0] == 0) { - if (_scumm->_gameId == GID_CMI) { - _outputMixerSize = (22050 * 2 * 2); - - char bunfile[20]; - if (_scumm->_features & GF_DEMO) { - if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) { - _outputMixerSize = 0; - return; - } - } else { - - sprintf(bunfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); - if (_musicDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) - _bundle->closeMusicFile(); - - if (_bundle->openMusicFile(bunfile, _scumm->getGameDataPath()) == false) { - if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) { - _outputMixerSize = 0; - return; - } - } - - _musicDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); - } - } else { - _outputMixerSize = ((22050 * 2 * 2) / 4) * 3; - - if (_bundle->openMusicFile("digmusic.bun", _scumm->getGameDataPath()) == false) - return; - } - _musicBundleBufFinal = (byte *)malloc(_outputMixerSize); - _musicBundleBufOutput = (byte *)malloc(((_outputMixerSize / 0x2000) + 1) * _outputMixerSize); - _currentSampleBundleMusic = 0; - _offsetSampleBundleMusic = 0; - _offsetBufBundleMusic = 0; - _bundleMusicPosition = 0; - _bundleSongPosInMs = 0; - _pauseBundleMusic = false; - _musicBundleToBeChanged = false; - _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(song); - _nameBundleMusic = song; - _outputMixerSize /= BUNDLE_MUSIC_ITER_PER_SEC; - _scumm->_timer->installTimerProc(&music_handler, 1000000 / BUNDLE_MUSIC_ITER_PER_SEC, this); - } else if (strcmp(_nameBundleMusic, song) != 0) { - _newNameBundleMusic = song; - _musicBundleToBeChanged = true; - } -} - -void IMuseDigital::pauseBundleMusic(bool state) { - _pauseBundleMusic = state; -} - -void IMuseDigital::stopBundleMusic() { - // First stop the music timer - _scumm->_timer->removeTimerProc(&music_handler); - _nameBundleMusic = ""; - _scumm->_mixer->stopHandle(_bundleMusicTrack); - if (_musicBundleBufFinal) { - free(_musicBundleBufFinal); - _musicBundleBufFinal = NULL; - } - if (_musicBundleBufOutput) { - free(_musicBundleBufOutput); - _musicBundleBufOutput = NULL; - } -} - -void IMuseDigital::bundleMusicHandler() { - byte *ptr; - int32 l, num = _numberSamplesBundleMusic, length, k; - int32 rate = 22050; - int32 tag, size = -1, header_size = 0; - - if (_pauseBundleMusic) - return; - - if (_musicBundleToBeChanged) { - _nameBundleMusic = _newNameBundleMusic; - _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(_nameBundleMusic); - _currentSampleBundleMusic = 0; - _offsetSampleBundleMusic = 0; - _offsetBufBundleMusic = 0; - _musicBundleToBeChanged = false; - _bundleMusicPosition = 0; - _bundleSongPosInMs = 0; - } - - ptr = _musicBundleBufOutput; - - for (k = 0, l = _currentSampleBundleMusic; l < num && (_offsetSampleBundleMusic < _outputMixerSize + header_size); k++) { - length = _bundle->decompressMusicSampleByName(_nameBundleMusic, l, (_musicBundleBufOutput + ((k * 0x2000) + _offsetBufBundleMusic))); - _offsetSampleBundleMusic += length; - - if (l == 0) { - tag = READ_BE_UINT32(ptr); ptr += 4; - if (tag != MKID_BE('iMUS')) { - error("Decompressing bundle song failed (unknown tag '%s')", tag2str(tag)); - } - - ptr += 12; - while (tag != MKID_BE('DATA')) { - tag = READ_BE_UINT32(ptr); ptr += 4; - switch(tag) { - case MKID_BE('FRMT'): - ptr += 12; - _bundleMusicSampleBits = READ_BE_UINT32(ptr); ptr += 4; - rate = READ_BE_UINT32(ptr); ptr += 4; - _bundleSampleChannels = READ_BE_UINT32(ptr); ptr += 4; - break; - case MKID_BE('TEXT'): - case MKID_BE('REGN'): - case MKID_BE('STOP'): - case MKID_BE('JUMP'): - case MKID_BE('SYNC'): - size = READ_BE_UINT32(ptr); ptr += size + 4; - break; - case MKID_BE('DATA'): - size = READ_BE_UINT32(ptr); ptr += 4; - break; - - default: - error("Unknown sound header '%s'", tag2str(tag)); - } - } - if (size < 0) { - error("Decompressing sound failed (missing size field)"); - } - header_size = (ptr - _musicBundleBufOutput); - } - - l++; - _currentSampleBundleMusic = l; - - } - - if (_offsetSampleBundleMusic >= _outputMixerSize + header_size) { - memcpy(_musicBundleBufFinal, (_musicBundleBufOutput + header_size), _outputMixerSize); - _offsetBufBundleMusic = _offsetSampleBundleMusic - _outputMixerSize - header_size; - memcpy(_musicBundleBufOutput, (_musicBundleBufOutput + (_outputMixerSize + header_size)), _offsetBufBundleMusic); - _offsetSampleBundleMusic = _offsetBufBundleMusic; - } - - if (_currentSampleBundleMusic == num) { - _currentSampleBundleMusic = 0; - _offsetSampleBundleMusic = 0; - _offsetBufBundleMusic = 0; - _bundleMusicPosition = 0; - _bundleSongPosInMs = 0; - } - - ptr = _musicBundleBufFinal; - - byte *buffer = NULL; - uint32 final_size; - if (_bundleMusicSampleBits == 12) { - final_size = decode12BitsSample(ptr, &buffer, _outputMixerSize); - } else if (_bundleMusicSampleBits == 16) { - buffer = (byte *)malloc(_outputMixerSize); - final_size = _outputMixerSize; - memcpy(buffer, ptr, _outputMixerSize); - } else { - warning("IMuseDigital::bundleMusicHandler TODO: more newStream options..."); - return; - } - - // Compute the position in the song in milliseconds (in brief: _outputMixerSize - // gives the number of bytes used for one second, so if we compute the value of - // (_bundleMusicPosition / _outputMixerSize), that is an offset in seconds; - // multiplying that by 1000 gives milliseconds). - _bundleSongPosInMs = 1000 * _bundleMusicPosition / (_outputMixerSize * BUNDLE_MUSIC_ITER_PER_SEC); - _bundleMusicPosition += final_size; - if (!_bundleMusicTrack.isActive()) - _scumm->_mixer->newStream(&_bundleMusicTrack, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO, 300000); - _scumm->_mixer->appendStream(_bundleMusicTrack, buffer, final_size); - free(buffer); -} - -void IMuseDigital::playBundleSound(const char *sound) { - byte *ptr = 0; - bool result; - - if (!_scumm->_mixer->isReady()) - return; - - if (_scumm->_gameId == GID_CMI) { - if (_scumm->_features & GF_DEMO) { - result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath()); - } else { - char voxfile[20]; - sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); - if (_voiceDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) - _bundle->closeVoiceFile(); - - result = _bundle->openVoiceFile(voxfile, _scumm->getGameDataPath()); - - if (result == false) - result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath()); - _voiceDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); - } - } else if (_scumm->_gameId == GID_DIG) - result = _bundle->openVoiceFile("digvoice.bun", _scumm->getGameDataPath()); - else - error("Don't know which bundle file to load"); - - if (!result) - return; - - if (_scumm->_gameId == GID_CMI) { - char name[20]; - strcpy(name, sound); - if (!(_scumm->_features & GF_DEMO)) // CMI demo does not have .IMX for voice but does for music... - strcat(name, ".IMX"); - _bundle->decompressVoiceSampleByName(name, &ptr); - } else { - _bundle->decompressVoiceSampleByName(sound, &ptr); - } - - if (ptr) { - stopSound(kTalkSoundID); - startSound(kTalkSoundID, ptr, 0); - free(ptr); - } -} - -} // End of namespace Scumm - -#ifdef __PALM_OS__ -#include "scumm_globals.h" - -_GINIT(IMuseDigital) -_GSETPTR(Scumm::_digStateMusicMap, GBVARS_DIGSTATEMUSICMAP_INDEX, Scumm::imuse_music_map , GBVARS_SCUMM) -_GSETPTR(Scumm::_digStateMusicTable, GBVARS_DIGSTATEMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM) -_GSETPTR(Scumm::_comiStateMusicTable, GBVARS_COMISTATEMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM) -_GSETPTR(Scumm::_comiSeqMusicTable, GBVARS_COMISEQMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM) -_GSETPTR(Scumm::_digSeqMusicTable, GBVARS_DIGSEQMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM) -_GSETPTR(Scumm::_ftStateMusicTable, GBVARS_FTSTATEMUSICTABLE_INDEX, Scumm::imuse_ft_music_table , GBVARS_SCUMM) -_GSETPTR(Scumm::_ftSeqMusicTable, GBVARS_FTSEQMUSICTABLE_INDEX, Scumm::imuse_ft_music_table , GBVARS_SCUMM) -_GEND - -_GRELEASE(IMuseDigital) -_GRELEASEPTR(GBVARS_DIGSTATEMUSICMAP_INDEX , GBVARS_SCUMM) -_GRELEASEPTR(GBVARS_DIGSTATEMUSICTABLE_INDEX , GBVARS_SCUMM) -_GRELEASEPTR(GBVARS_COMISTATEMUSICTABLE_INDEX , GBVARS_SCUMM) -_GRELEASEPTR(GBVARS_COMISEQMUSICTABLE_INDEX , GBVARS_SCUMM) -_GRELEASEPTR(GBVARS_DIGSEQMUSICTABLE_INDEX , GBVARS_SCUMM) -_GRELEASEPTR(GBVARS_FTSTATEMUSICTABLE_INDEX , GBVARS_SCUMM) -_GRELEASEPTR(GBVARS_FTSEQMUSICTABLE_INDEX , GBVARS_SCUMM) -_GEND - -#endif diff --git a/scumm/imuse_digi.h b/scumm/imuse_digi.h deleted file mode 100644 index 047283530a..0000000000 --- a/scumm/imuse_digi.h +++ /dev/null @@ -1,149 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2001 Ludvig Strigeus - * Copyright (C) 2001-2004 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef IMUSE_DIGI_H -#define IMUSE_DIGI_H - -#include "common/scummsys.h" -#include "scumm/music.h" -#include "sound/mixer.h" - -class AudioStream; - -namespace Scumm { - -#define MAX_DIGITAL_CHANNELS 8 -#define MAX_IMUSE_JUMPS 50 -#define MAX_IMUSE_REGIONS 50 -#define MAX_IMUSE_MARKERS 50 - -class ScummEngine; -class Bundle; - -/** - * iMuse Digital Implementation for SCUMM v7 and higher. - */ -class IMuseDigital : public MusicEngine { -private: - - struct _region { - uint32 start; // begin of region - uint32 length; // lenght of region - }; - - struct _jump { - uint32 start; // jump start position - uint32 dest; // jump to dest position - uint32 hookId; // id of hook - uint32 fadeDelay; // fade delay in ms - }; - - struct _marker { - char name[256]; // name of marker - }; - - struct Channel { - int8 pan; // pan - int32 vol; // volume - int32 volFadeDest; // - int32 volFadeStep; // - int32 volFadeDelay; // - bool volFadeUsed; // - - _region region[MAX_IMUSE_REGIONS]; - _marker marker[MAX_IMUSE_MARKERS]; - _jump jump[MAX_IMUSE_JUMPS]; - int32 offsetStop; - int32 numJumps; - int32 numRegions; - int32 numMarkers; - - int idSound; - bool used; - bool started; - PlayingSoundHandle handle; - AudioStream *stream; - - Channel(); - }; - - Channel _channel[MAX_DIGITAL_CHANNELS]; - - ScummEngine *_scumm; - bool _pause; - - static void timer_handler(void *refConf); - void callback(); - - // - // Bundle music - // - const char *_nameBundleMusic; - const char *_newNameBundleMusic; - byte _musicDisk; - byte _voiceDisk; - int32 _currentSampleBundleMusic; - int32 _numberSamplesBundleMusic; - int32 _offsetSampleBundleMusic; - int32 _offsetBufBundleMusic; - byte *_musicBundleBufFinal; - byte *_musicBundleBufOutput; - bool _pauseBundleMusic; - PlayingSoundHandle _bundleMusicTrack; - bool _musicBundleToBeChanged; - int32 _bundleMusicSampleBits; - int32 _outputMixerSize; - int32 _bundleSampleChannels; - int32 _bundleMusicPosition; - - static void music_handler(void *refCon); - void bundleMusicHandler(); - - void playBundleMusic(const char *song); - -public: - int32 _bundleSongPosInMs; - Bundle *_bundle; // FIXME: should be protected but is used by ScummEngine::askForDisk - - void pauseBundleMusic(bool state); - void stopBundleMusic(); - void playBundleSound(const char *sound); - - void startSound(int sound, byte *voiceBundleData, AudioStream *input); - -public: - IMuseDigital(ScummEngine *scumm); - ~IMuseDigital(); - - void setMasterVolume(int vol) {} - - void startSound(int sound) { startSound(sound, 0, 0); } - void stopSound(int sound); - void stopAllSounds(); - void pause(bool pause); - void parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h); - int getSoundStatus(int sound) const; -}; - -} // End of namespace Scumm - -#endif diff --git a/scumm/imuse_digi/.cvsignore b/scumm/imuse_digi/.cvsignore new file mode 100644 index 0000000000..39a06683b7 --- /dev/null +++ b/scumm/imuse_digi/.cvsignore @@ -0,0 +1 @@ +.deps diff --git a/scumm/imuse_digi/dimuse.cpp b/scumm/imuse_digi/dimuse.cpp new file mode 100644 index 0000000000..0abcc59043 --- /dev/null +++ b/scumm/imuse_digi/dimuse.cpp @@ -0,0 +1,576 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#include "stdafx.h" +#include "common/timer.h" + +#include "scumm/actor.h" +#include "scumm/scumm.h" +#include "scumm/sound.h" +#include "scumm/imuse_digi/dimuse.h" +#include "scumm/imuse_digi/dimuse_bndmgr.h" + +#include "sound/audiostream.h" +#include "sound/mixer.h" + +namespace Scumm { + +IMuseDigital::Track::Track() + : idSound(-1), used(false), stream(NULL) { +} + +void IMuseDigital::timer_handler(void *refCon) { + IMuseDigital *imuseDigital = (IMuseDigital *)refCon; + imuseDigital->callback(); +} + +IMuseDigital::IMuseDigital(ScummEngine *scumm) + : _scumm(scumm) { + _pause = false; + _sound = new ImuseDigiSndMgr(_scumm); + _scumm->_timer->installTimerProc(timer_handler, 1000000 / 25, this); + _curMusicId = -1; +} + +IMuseDigital::~IMuseDigital() { + _scumm->_timer->removeTimerProc(timer_handler); + stopAllSounds(); + delete _sound; +} + +void IMuseDigital::callback() { + int l = 0; + + if (_pause || !_scumm) + return; + + for (l = 0; l < MAX_DIGITAL_TRACKS;l ++) { + if (_track[l].used) { + if (_track[l].stream2) { + if (!_track[l].handle.isActive() && _track[l].started) { + debug(5, "IMuseDigital::callback(): stoped sound: %d", _track[l].idSound); + delete _track[l].stream2; + _track[l].stream2 = NULL; + _track[l].used = false; + continue; + } + } else if (_track[l].stream) { + if (_track[l].toBeRemoved) { + debug(5, "IMuseDigital::callback(): stoped sound: %d", _track[l].idSound); + if (_track[l].stream) + _track[l].stream->finish(); + _track[l].stream = NULL; + _sound->closeSound(_track[l].soundHandle); + _track[l].used = false; + continue; + } + } + + if (_track[l].volFadeUsed) { + if (_track[l].volFadeStep < 0) { + if (_track[l].vol > _track[l].volFadeDest) { + _track[l].vol += _track[l].volFadeStep; + if (_track[l].vol < _track[l].volFadeDest) { + _track[l].vol = _track[l].volFadeDest; + _track[l].volFadeUsed = false; + } + if (_track[l].vol == 0) { + _track[l].toBeRemoved = true; + } + } + } else if (_track[l].volFadeStep > 0) { + if (_track[l].vol < _track[l].volFadeDest) { + _track[l].vol += _track[l].volFadeStep; + if (_track[l].vol > _track[l].volFadeDest) { + _track[l].vol = _track[l].volFadeDest; + _track[l].volFadeUsed = false; + } + } + } + debug(5, "Fade: sound(%d), Vol(%d)", _track[l].idSound, _track[l].vol / 1000); + } + + int pan = (_track[l].pan != 64) ? 2 * _track[l].pan - 127 : 0; + + if (_scumm->_mixer->isReady()) { + if (_track[l].stream2) { + if (!_track[l].started) { + _track[l].started = true; + _scumm->_mixer->playInputStream(&_track[l].handle, _track[l].stream2, true, _track[l].vol / 1000, _track[l].pan, -1, false); + } else { + _scumm->_mixer->setChannelVolume(_track[l].handle, _track[l].vol / 1000); + _scumm->_mixer->setChannelPan(_track[l].handle, pan); + } + continue; + } + } + + if (_track[l].stream) { + int32 mixer_size = _track[l].pullSize; + byte *data = NULL; + int32 result = 0; + + if (_track[l].stream->endOfData()) + mixer_size *= 2; + + do { + if (_sound->getBits(_track[l].soundHandle) == 12) { + byte *ptr = NULL; + mixer_size += _track[l].mod; + int length = (((mixer_size * 3) / 4) / 3) * 3; + _track[l].mod = ((mixer_size * 3) / 4) - length; + mixer_size = length; + + int32 offset = (_track[l].regionOffset * 3) / 4; + result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &ptr, offset, mixer_size); + int32 result2 = BundleCodecs::decode12BitsSample(ptr, &data, result); + result = (result * 4) / 3; + if (result != result2) { + debug(5, "result: %d, result2: %d", result, result2); + result &= ~1; + } + mixer_size = (mixer_size * 4) / 3; + free(ptr); + } else if (_sound->getBits(_track[l].soundHandle) == 16) { + result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size); + if (_sound->getChannels(_track[l].soundHandle) == 2) { + if (result & 3) + result &= ~2; + } + if (_sound->getChannels(_track[l].soundHandle) == 1) { + if (result & 1) + result &= ~1; + } + } else if (_sound->getBits(_track[l].soundHandle) == 8) { + result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size); + if (_sound->getChannels(_track[l].soundHandle) == 2) { + if (result & 1) + result &= ~1; + } + } + + if (_scumm->_mixer->isReady()) { + _scumm->_mixer->setChannelVolume(_track[l].handle, _track[l].vol / 1000); + _scumm->_mixer->setChannelPan(_track[l].handle, pan); + _track[l].stream->append(data, result); + _track[l].regionOffset += result; + _track[l].trackOffset += result; + free(data); + } + + if (_sound->isEndOfRegion(_track[l].soundHandle, _track[l].curRegion)) { + switchToNextRegion(l); + if (_track[l].toBeRemoved) + break; + } + mixer_size -= result; + assert(mixer_size >= 0); + } while (mixer_size != 0); + } + } + } +} + +void IMuseDigital::switchToNextRegion(int track) { + // TODO - finish + int num_regions = _sound->getNumRegions(_track[track].soundHandle); + if (++_track[track].curRegion == num_regions) { + _track[track].toBeRemoved = true; + return; + } + _track[track].regionOffset = 0; +} + +void IMuseDigital::startSound(int soundId, char *soundName, int soundType, int soundGroup, AudioStream *input) { + debug(5, "IMuseDigital::startSound(%d)", soundId); + int l; + + for (l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if (!_track[l].used && !_track[l].handle.isActive()) { + _track[l].pan = 64; + _track[l].vol = 127 * 1000; + _track[l].volFadeDest = 0; + _track[l].volFadeStep = 0; + _track[l].volFadeDelay = 0; + _track[l].volFadeUsed = false; + _track[l].idSound = soundId; + _track[l].started = false; + _track[l].soundGroup = soundGroup; + _track[l].curHookId = 0; + _track[l].curRegion = 0; + _track[l].regionOffset = 0; + _track[l].trackOffset = 0; + _track[l].mod = 0; + _track[l].toBeRemoved = false; + + int bits = 0, freq = 0, channels = 0, mixerFlags = 0; + + if (input) { + // Do nothing here, we already have an audio stream + } else { + if (soundName == NULL) + _track[l].soundHandle = _sound->openSound(soundId, NULL, soundType, soundGroup); + else + _track[l].soundHandle = _sound->openSound(0, soundName, soundType, soundGroup); + + if (_track[l].soundHandle == NULL) + return; + + bits = _sound->getBits(_track[l].soundHandle); + channels = _sound->getChannels(_track[l].soundHandle); + freq = _sound->getFreq(_track[l].soundHandle); + + if (channels == 2) { + mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO; + _track[l].pullSize = freq * 2; + } else { + _track[l].pullSize = freq; + } + + if (bits == 12) { + mixerFlags |= SoundMixer::FLAG_16BITS; + _track[l].pullSize *= 2; + } else if (bits == 16) { + mixerFlags |= SoundMixer::FLAG_16BITS; + _track[l].pullSize *= 2; + } else if (bits == 8) { + mixerFlags |= SoundMixer::FLAG_UNSIGNED; + } else + error("IMuseDigital::startSound(): Can't handle %d bit samples", bits); + + _track[l].pullSize /= 25; // We want a "frame rate" of 25 audio blocks per second + if (soundGroup == IMUSE_MUSIC) + _curMusicId = soundId; + } + + if (input) { + _track[l].stream2 = input; + _track[l].stream = NULL; + } else { + _track[l].stream2 = NULL; + _track[l].stream = makeAppendableAudioStream(freq, mixerFlags, 100000); + _scumm->_mixer->playInputStream(&_track[l].handle, _track[l].stream, true, _track[l].vol / 1000, _track[l].pan, -1, false); + } + + _track[l].used = true; + return; + } + } + warning("IMuseDigital::startSound(): All slots are full"); +} + +void IMuseDigital::stopMusic() { + debug(5, "IMuseDigital::stopMusic()"); + for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if ((_track[l].idSound == _curMusicId) && _track[l].used) { + if (_track[l].stream) { + _track[l].toBeRemoved = true; + } + } + } + _curMusicId = -1; +} + +void IMuseDigital::stopSound(int soundId) { + debug(5, "IMuseDigital::stopSound(%d)", soundId); + for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if ((_track[l].idSound == soundId) && _track[l].used) { + if (_track[l].stream) { + _track[l].toBeRemoved = true; + } + else if (_track[l].stream2) + _scumm->_mixer->stopHandle(_track[l].handle); + } + } +} + +void IMuseDigital::stopAllSounds() { + debug(5, "IMuseDigital::stopAllSounds"); + for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if (_track[l].used) { + if (_track[l].stream) { + _track[l].toBeRemoved = true; + } else if (_track[l].stream2) + _scumm->_mixer->stopHandle(_track[l].handle); + } + } +} + +void IMuseDigital::pause(bool p) { + for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if (_track[l].used) { + _scumm->_mixer->pauseHandle(_track[l].handle, p); + } + } + _pause = p; +} + +void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) { + int cmd = a; + int sample = b; + int sub_cmd = c; + int chan = -1; + int l, r; + + if (!cmd) + return; + + switch (cmd) { + case 10: // ImuseStopAllSounds + debug(5, "ImuseStopAllSounds()"); + stopAllSounds(); + break; + case 12: // ImuseSetParam + switch (sub_cmd) { + case 0x500: // set priority - could be ignored + break; + case 0x600: // set volume + debug(5, "ImuseSetParam (0x600), sample(%d), volume(%d)", sample, d); + for (l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if ((_track[l].idSound == sample) && _track[l].used) { + _track[l].vol = d * 1000; +// if (_track[l].volFadeUsed) +// _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * _track[chan].volFadeDelay); + } + } + if (l == -1) { + debug(5, "ImuseSetParam (0x600), sample(%d) not exist in channels", sample); + return; + } + break; + case 0x700: // set pan + debug(5, "ImuseSetParam (0x700), sample(%d), pan(%d)", sample, d); + for (l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if ((_track[l].idSound == sample) && _track[l].used) { + _track[l].pan = d; + } + } + if (l == -1) { + debug(5, "ImuseSetParam (0x700), sample(%d) not exist in channels", sample); + return; + } + break; + default: + warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd); + break; + } + break; + case 14: // ImuseFadeParam + switch (sub_cmd) { + case 0x600: // set new volume with fading + debug(5, "ImuseFadeParam - fade sample(%d), to volume(%d) with 60hz ticks(%d)", sample, d, e); + if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) { + stopSound(sample); + return; + } + for (l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if ((_track[l].idSound == sample) && _track[l].used) { + _track[l].volFadeDelay = e; + _track[l].volFadeDest = d * 1000; + _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * e); + _track[l].volFadeUsed = true; + debug(5, "ImuseFadeParam: vol %d, volDest %d, step %d", _track[l].vol, d * 1000, _track[l].volFadeStep); + } + } + if (chan == -1) { + debug(5, "ImuseFadeParam (0x600), sample %d not exist in channels", sample); + return; + } + break; + default: + warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd); + break; + } + break; + case 0x1000: // ImuseSetState + debug(5, "ImuseSetState (%d)", b); + if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) { + if (b == 1) + startMusic(1); + else { + if (getSoundStatus(2) == 0) + startMusic(2); + } + } else if (_scumm->_gameId == GID_DIG) { + if (b == 1000) { // STATE_NULL + stopMusic(); + return; + } + for (l = 0; _digStateMusicMap[l].room != -1; l++) { + if (_digStateMusicMap[l].room == b) { + int music = _digStateMusicMap[l].table_index; + debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename); + if (_digStateMusicTable[music].filename[0] != 0) { + startMusic((char *)_digStateMusicTable[music].filename, _digStateMusicTable[music].id); + } + break; + } + } + } else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) { + if (b == 2) { + startMusic("in1.imx", 2002); + } else if (b == 4) { + startMusic("in2.imx", 2004); + } else if (b == 8) { + startMusic("out1.imx", 2008); + } else if (b == 9) { + startMusic("out2.imx", 2009); + } else if (b == 16) { + startMusic("gun.imx", 2016); + } else { + warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom); + } + } else if (_scumm->_gameId == GID_CMI) { + if (b == 1000) { // STATE_NULL + stopMusic(); + return; + } + for (l = 0; _comiStateMusicTable[l].id != -1; l++) { + if ((_comiStateMusicTable[l].id == b)) { + debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename); + if (_comiStateMusicTable[l].filename[0] != 0) { + startMusic((char *)_comiStateMusicTable[l].filename, b); + } + break; + } + } + } else if (_scumm->_gameId == GID_FT) { + for (l = 0;; l++) { + if (_ftStateMusicTable[l].index == -1) { + return; + } + if (_ftStateMusicTable[l].index == b) { + debug(5, "Play imuse music: %s, %s", _ftStateMusicTable[l].name, _ftStateMusicTable[l].audioname); + if (_ftStateMusicTable[l].audioname[0] != 0) { + for (r = 0; r < _scumm->_numAudioNames; r++) { + if (strcmp(_ftStateMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) { + startMusic(r); + parseScriptCmds(12, r, 0x600, _ftStateMusicTable[l].volume, 0, 0, 0, 0); + } + } + } + } + } + } + break; + case 0x1001: // ImuseSetSequence + debug(5, "ImuseSetSequence (%d)", b); + if (_scumm->_gameId == GID_DIG) { + for (l = 0; _digSeqMusicTable[l].room != -1; l++) { + if (_digSeqMusicTable[l].room == b) { + debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename); + if (_digSeqMusicTable[l].filename[0] != 0) { + startMusic((char *)_digSeqMusicTable[l].filename, b); + } + break; + } + } + } else if (_scumm->_gameId == GID_CMI) { + for (l = 0; _comiSeqMusicTable[l].id != -1; l++) { + if (_comiSeqMusicTable[l].id == b) { + debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename); + if (_comiSeqMusicTable[l].filename[0] != 0) { + startMusic((char *)_comiSeqMusicTable[l].filename, b); + } + break; + } + } + } else if (_scumm->_gameId == GID_FT) { + for (l = 0; _ftSeqMusicTable[l].index != -1; l++) { + if (_ftSeqMusicTable[l].index == b) { + debug(5, "Play imuse music: %s, %s", _ftSeqMusicTable[l].name, _ftSeqMusicTable[l].audioname); + if (_ftSeqMusicTable[l].audioname[0] != 0) { + for (r = 0; r < _scumm->_numAudioNames; r++) { + if (strcmp(_ftSeqMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) { + startMusic(r); + parseScriptCmds(12, r, 0x600, _ftSeqMusicTable[l].volume, 0, 0, 0, 0); + } + } + } + } + } + } + break; + case 0x1002: // ImuseSetCuePoint + debug(5, "ImuseSetCuePoint (%d)", b); + // TODO + break; + case 0x1003: // ImuseSetAttribute + debug(5, "ImuseSetAttribute (%d, %d)", b, c); + // TODO + break; + case 0x2000: // ImuseSetMasterSFXVolume + debug(5, "ImuseSetMasterSFXVolume (%d)", b); + // TODO + break; + case 0x2001: // ImuseSetMasterVoiceVolume + debug(5, "ImuseSetMasterVoiceVolume (%d)", b); + // TODO + break; + case 0x2002: // ImuseSetMasterMusicVolume + debug(5, "ImuseSetMasterMusicVolume (%d)", b); + // TODO + break; + default: + warning("IMuseDigital::doCommand DEFAULT command %d", cmd); + } +} + +int IMuseDigital::getSoundStatus(int sound) const { + debug(5, "IMuseDigital::getSoundStatus(%d)", sound); + for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { + if ((_track[l].idSound == sound) && _track[l].used) { + return 1; + } + } + + return 0; +} + +void IMuseDigital::closeBundleFiles() { + // TODO +} + +int32 IMuseDigital::getCurMusicPosInMs() { + // TODO + return 0; +} + +int32 IMuseDigital::getCurVoiceLipSyncWidth() { + // TODO + return _scumm->_rnd.getRandomNumber(255); +} + +int32 IMuseDigital::getCurVoiceLipSyncHeight() { + // TODO + return _scumm->_rnd.getRandomNumber(255); +} + +int32 IMuseDigital::getCurMusicLipSyncWidth() { + // TODO + return _scumm->_rnd.getRandomNumber(255); +} + +int32 IMuseDigital::getCurMusicLipSyncHeight() { + // TODO + return _scumm->_rnd.getRandomNumber(255); +} + +} // End of namespace Scumm diff --git a/scumm/imuse_digi/dimuse.h b/scumm/imuse_digi/dimuse.h new file mode 100644 index 0000000000..cb2ba02d1b --- /dev/null +++ b/scumm/imuse_digi/dimuse.h @@ -0,0 +1,154 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#ifndef IMUSE_DIGI_H +#define IMUSE_DIGI_H + +#include "common/scummsys.h" + +#include "scumm/imuse_digi/dimuse.h" +#include "scumm/imuse_digi/dimuse_bndmgr.h" +#include "scumm/imuse_digi/dimuse_sndmgr.h" +#include "scumm/music.h" + +#include "sound/mixer.h" +#include "sound/audiostream.h" + +namespace Scumm { + +#define MAX_DIGITAL_TRACKS 16 + +class IMuseDigital : public MusicEngine { +private: + + struct Track { + int8 pan; // pan + int32 vol; // volume + int32 volFadeDest; // + int32 volFadeStep; // + int32 volFadeDelay; // + bool volFadeUsed; // + + int idSound; + bool used; + bool toBeRemoved; + bool started; + int32 regionOffset; + int32 trackOffset; + int curRegion; + int curHookId; + int soundGroup; + void *soundHandle; + int32 pullSize; + int mod; + PlayingSoundHandle handle; + AppendableAudioStream *stream; + AudioStream *stream2; + + Track(); + }; + + Track _track[MAX_DIGITAL_TRACKS]; + + ScummEngine *_scumm; + ImuseDigiSndMgr *_sound; + bool _pause; + int _curMusicId; + + static void timer_handler(void *refConf); + void callback(); + void switchToNextRegion(int track); + void startSound(int soundId, char *soundName, int soundType, int soundGroup, AudioStream *input); + +public: + IMuseDigital(ScummEngine *scumm); + ~IMuseDigital(); + + void startVoice(int soundId, AudioStream *input) + { debug(0, "startVoiceStream(%d)", soundId); startSound(soundId, NULL, 0, IMUSE_VOICE, input); } + void startVoice(int soundId) + { debug(0, "startVoiceBundle(%d)", soundId); startSound(soundId, NULL, IMUSE_BUNDLE, IMUSE_VOICE, NULL); } + void startVoice(int soundId, char *soundName) + { debug(0, "startVoiceBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOICE, NULL); } + void startMusic(int soundId) + { debug(0, "startMusicResource(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_MUSIC, NULL); } + void startMusic(char *soundName, int soundId) + { debug(0, "startMusicBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_MUSIC, NULL); } + void startSfx(int soundId) + { debug(0, "startSfx(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_SFX, NULL); } + void startSound(int soundId) + { error("MusicEngine::startSound() Should be never called"); } + + void setMasterVolume(int vol) {} + void stopMusic(); + void stopSound(int soundId); + void stopAllSounds(); + void pause(bool pause); + void parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h); + int getSoundStatus(int sound) const; + int32 getCurMusicPosInMs(); + int32 getCurVoiceLipSyncWidth(); + int32 getCurVoiceLipSyncHeight(); + int32 getCurMusicLipSyncWidth(); + int32 getCurMusicLipSyncHeight(); + + void closeBundleFiles(); +}; + +struct imuse_music_table { + int room; + int id; + int unk1; + int unk2; + int unk3; + int unk4; + char name[30]; + char title[30]; + char filename[13]; +}; + +struct imuse_music_map { + int room; + int table_index; + int unk1; + int unk2; + int unk3; + int unk4; +}; + +struct imuse_ft_music_table { + int index; + char audioname[15]; + int unk1; + int volume; + char name[30]; +}; + +extern imuse_music_map _digStateMusicMap[]; +extern const imuse_music_table _digStateMusicTable[]; +extern const imuse_music_table _digSeqMusicTable[]; +extern const imuse_music_table _comiStateMusicTable[]; +extern const imuse_music_table _comiSeqMusicTable[]; +extern const imuse_ft_music_table _ftStateMusicTable[]; +extern const imuse_ft_music_table _ftSeqMusicTable[]; + +} // End of namespace Scumm + +#endif diff --git a/scumm/imuse_digi/dimuse_bndmgr.cpp b/scumm/imuse_digi/dimuse_bndmgr.cpp new file mode 100644 index 0000000000..915ea73785 --- /dev/null +++ b/scumm/imuse_digi/dimuse_bndmgr.cpp @@ -0,0 +1,179 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#include "stdafx.h" +#include "common/scummsys.h" +#include "scumm/scumm.h" +#include "scumm/imuse_digi/dimuse_bndmgr.h" + +namespace Scumm { + +BundleMgr::BundleMgr() { + _compTable = NULL; + _bundleTable = NULL; + _numFiles = 0; + _curSample = -1; +} + +BundleMgr::~BundleMgr() { + free(_bundleTable); + free(_compTable); +} + +bool BundleMgr::openFile(const char *filename, const char *directory) { + int32 tag, offset; + + if (_file.isOpen()) + return true; + + if (_file.open(filename, directory) == false) { + warning("BundleMgr::openFile() Can't open bundle file: %s", filename); + return false; + } + + tag = _file.readUint32BE(); + offset = _file.readUint32BE(); + _numFiles = _file.readUint32BE(); + + _bundleTable = (AudioTable *) malloc(_numFiles * sizeof(AudioTable)); + + _file.seek(offset, SEEK_SET); + + for (int32 i = 0; i < _numFiles; i++) { + char name[13], c; + int32 z = 0; + int32 z2; + + for (z2 = 0; z2 < 8; z2++) + if ((c = _file.readByte()) != 0) + name[z++] = c; + name[z++] = '.'; + for (z2 = 0; z2 < 4; z2++) + if ((c = _file.readByte()) != 0) + name[z++] = c; + name[z] = '\0'; + strcpy(_bundleTable[i].filename, name); + _bundleTable[i].offset = _file.readUint32BE(); + _bundleTable[i].size = _file.readUint32BE(); + } + + return true; +} + +void BundleMgr::closeFile() { + if (_file.isOpen()) { + _file.close(); + free(_bundleTable); + _bundleTable = NULL; + } +} + +int32 BundleMgr::decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size) { + return decompressSampleByIndex(_curSample, offset, size, comp_final, header_size); +} + +int32 BundleMgr::decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size) { + int32 i, tag, num, final_size, output_size; + byte *comp_input, *comp_output; + + if (index != -1) + _curSample = index; + + if (_file.isOpen() == false) { + warning("BundleMgr::decompressSampleByIndex() File is not open!"); + return 0; + } + + _file.seek(_bundleTable[index].offset, SEEK_SET); + tag = _file.readUint32BE(); + num = _file.readUint32BE(); + _file.readUint32BE(); + _file.readUint32BE(); + + if (tag != MKID_BE('COMP')) { + warning("BundleMgr::decompressSampleByIndex() Compressed sound %d invalid (%s)", index, tag2str(tag)); + return 0; + } + + free(_compTable); + _compTable = (CompTable *)malloc(sizeof(CompTable) * num); + for (i = 0; i < num; i++) { + _compTable[i].offset = _file.readUint32BE(); + _compTable[i].size = _file.readUint32BE(); + _compTable[i].codec = _file.readUint32BE(); + _file.readUint32BE(); + } + + int first_block = (offset + header_size) / 0x2000; + int last_block = (offset + size + header_size - 1) / 0x2000; + + comp_output = (byte *)malloc(0x2000); + *comp_final = (byte *)malloc(0x2000 * (1 + last_block - first_block)); + final_size = 0; + + int skip = offset - (first_block * 0x2000) + header_size; + + for (i = first_block; i <= last_block; i++) { + assert(size); + // CMI hack: one more zero byte at the end of input buffer + comp_input = (byte *)malloc(_compTable[i].size + 1); + comp_input[_compTable[i].size] = 0; + + _file.seek(_bundleTable[index].offset + _compTable[i].offset, SEEK_SET); + _file.read(comp_input, _compTable[i].size); + + output_size = BundleCodecs::decompressCodec(_compTable[i].codec, comp_input, comp_output, _compTable[i].size); + assert(output_size <= 0x2000); + if ((header_size != 0) && (skip > header_size)) + output_size -= skip; + if (output_size > size) + output_size = size; + memcpy(*comp_final + final_size, comp_output + skip, output_size); + final_size += output_size; + size -= output_size; + if (skip > 0) + skip = 0; + + free(comp_input); + } + free(comp_output); + + return final_size; +} + +int32 BundleMgr::decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final) { + int32 final_size = 0, i; + + if (_file.isOpen() == false) { + warning("BundleMgr::decompressSampleByName() File is not open!"); + return 0; + } + + for (i = 0; i < _numFiles; i++) { + if (!scumm_stricmp(name, _bundleTable[i].filename)) { + final_size = decompressSampleByIndex(i, offset, size, comp_final, 0); + return final_size; + } + } + debug(2, "BundleMgr::decompressSampleByName() Failed finding voice %s", name); + return final_size; +} + +} // End of namespace Scumm diff --git a/scumm/imuse_digi/dimuse_bndmgr.h b/scumm/imuse_digi/dimuse_bndmgr.h new file mode 100644 index 0000000000..11560f1ee5 --- /dev/null +++ b/scumm/imuse_digi/dimuse_bndmgr.h @@ -0,0 +1,72 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#ifndef BUNDLE_MGR_H +#define BUNDLE_MGR_H + +#include "common/scummsys.h" +#include "common/file.h" + +namespace Scumm { + +class BundleMgr { + +private: + + struct CompTable { + int32 offset; + int32 size; + int32 codec; + }; + + struct AudioTable { + char filename[13]; + int32 size; + int32 offset; + }; + + CompTable *_compTable; + AudioTable *_bundleTable; + int32 _numFiles; + int32 _curSample; + File _file; + +public: + BundleMgr(); + ~BundleMgr(); + + bool openFile(const char *filename, const char *directory); + void closeFile(); + int32 decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final); + int32 decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size); + int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size); +}; + +namespace BundleCodecs { + +uint32 decode12BitsSample(byte *src, byte **dst, uint32 size); +void initializeImcTables(); +int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size); + +} // End of namespace BundleCodecs + +} // End of namespace Scumm + +#endif diff --git a/scumm/imuse_digi/dimuse_codecs.cpp b/scumm/imuse_digi/dimuse_codecs.cpp new file mode 100644 index 0000000000..5d3e1f78f2 --- /dev/null +++ b/scumm/imuse_digi/dimuse_codecs.cpp @@ -0,0 +1,698 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#include "stdafx.h" +#include "common/scummsys.h" +#include "common/util.h" + +namespace Scumm { + +namespace BundleCodecs { + +uint32 decode12BitsSample(byte *src, byte **dst, uint32 size) { + uint32 loop_size = size / 3; + uint32 s_size = loop_size * 4; + byte *ptr = *dst = (byte *)malloc(s_size); + + uint32 tmp; + while (loop_size--) { + byte v1 = *src++; + byte v2 = *src++; + byte v3 = *src++; + tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000; + WRITE_BE_UINT16(ptr, tmp); ptr += 2; + tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; + WRITE_BE_UINT16(ptr, tmp); ptr += 2; + } + return s_size; +} + +static byte _destImcTable[93]; +static uint32 _destImcTable2[5697]; + +#ifdef __PALM_OS__ +static const int16 *imcTable; +#else +static const int16 imcTable[] = { + 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011, + 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D, + 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, + 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133, + 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C, + 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812, + 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, + 0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, + 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF +}; +#endif + +static const byte imxOtherTable[6][128] = { + { + 0xFF, 0x04, 0xFF, 0x04 + }, + + { + 0xFF, 0xFF, 0x02, 0x08, 0xFF, 0xFF, 0x02, 0x08 + }, + + { + 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x04, 0x06, + 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x04, 0x06 + }, + + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x01, 0x02, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x20, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x01, 0x02, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x20 + }, + + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x20, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x20 + }, + + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 + } +}; + +static const byte imxShortTable[] = { + 0, 0, 1, 3, 7, 15, 31, 63 +}; + +void initializeImcTables() { + int32 destTablePos = 0; + int32 imcTable1Pos = 0; + do { + byte put = 1; + int32 tableValue = ((imcTable[imcTable1Pos] * 4) / 7) / 2; + if (tableValue != 0) { + do { + tableValue /= 2; + put++; + } while (tableValue != 0); + } + if (put < 3) { + put = 3; + } + if (put > 8) { + put = 8; + } + put--; + _destImcTable[destTablePos] = put; + destTablePos++; + } while (++imcTable1Pos <= 88); + _destImcTable[89] = 0; + + for (int n = 0; n < 64; n++) { + imcTable1Pos = 0; + destTablePos = n; + do { + int32 count = 32; + int32 put = 0; + int32 tableValue = imcTable[imcTable1Pos]; + do { + if ((count & n) != 0) { + put += tableValue; + } + count /= 2; + tableValue /= 2; + } while (count != 0); + _destImcTable2[destTablePos] = put; + destTablePos += 64; + } while (++imcTable1Pos <= 88); + } +} +#define NextBit \ + do { \ + bit = mask & 1; \ + mask >>= 1; \ + if (!--bitsleft) { \ + mask = READ_LE_UINT16(srcptr); \ + srcptr += 2; \ + bitsleft = 16; \ + } \ + } while (0) + +static int32 compDecode(byte *src, byte *dst) { + byte *result, *srcptr = src, *dstptr = dst; + int data, size, bit, bitsleft = 16, mask = READ_LE_UINT16(srcptr); + srcptr += 2; + + while (1) { + NextBit; + if (bit) { + *dstptr++ = *srcptr++; + } else { + NextBit; + if (!bit) { + NextBit; + size = bit << 1; + NextBit; + size = (size | bit) + 3; + data = *srcptr++ | 0xffffff00; + } else { + data = *srcptr++; + size = *srcptr++; + + data |= 0xfffff000 + ((size & 0xf0) << 4); + size = (size & 0x0f) + 3; + + if (size == 3) + if (((*srcptr++) + 1) == 1) + return dstptr - dst; + } + result = dstptr + data; + while (size--) + *dstptr++ = *result++; + } + } +} +#undef NextBit + +int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size) { + int32 output_size, channels; + int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z; + byte *src, *t_table, *p, *ptr; + byte t_tmp1, t_tmp2; + + switch (codec) { + case 0: + memcpy(comp_output, comp_input, input_size); + output_size = input_size; + break; + + case 1: + output_size = compDecode(comp_input, comp_output); + break; + + case 2: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + break; + + case 3: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + break; + + case 4: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + + t_table = (byte *)malloc(output_size); + memset(t_table, 0, output_size); + + src = comp_output; + length = (output_size * 8) / 12; + k = 0; + if (length > 0) { + c = -12; + s = 0; + j = 0; + do { + ptr = src + length + k / 2; + if (k & 1) { + r = c / 8; + t_table[r + 2] = ((src[j] & 0x0f) << 4) | (ptr[1] >> 4); + t_table[r + 1] = (src[j] & 0xf0) | (t_table[r + 1]); + } else { + r = s / 8; + t_table[r + 0] = ((src[j] & 0x0f) << 4) | (ptr[0] & 0x0f); + t_table[r + 1] = src[j] >> 4; + } + s += 12; + c += 12; + k++; + j++; + } while (k < length); + } + offset1 = ((length - 1) * 3) / 2; + t_table[offset1 + 1] = (t_table[offset1 + 1]) | (src[length - 1] & 0xf0); + memcpy(src, t_table, output_size); + free(t_table); + break; + + case 5: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + + t_table = (byte *)malloc(output_size); + memset(t_table, 0, output_size); + + src = comp_output; + length = (output_size * 8) / 12; + k = 1; + c = 0; + s = 12; + t_table[0] = src[length] / 16; + t = length + k; + j = 1; + if (t > k) { + do { + ptr = src + length + k / 2; + if (k & 1) { + r = c / 8; + t_table[r + 0] = (src[j - 1] & 0xf0) | t_table[r]; + t_table[r + 1] = ((src[j - 1] & 0x0f) << 4) | (ptr[0] & 0x0f); + } else { + r = s / 8; + t_table[r + 0] = src[j - 1] >> 4; + t_table[r - 1] = ((src[j - 1] & 0x0f) << 4) | (ptr[0] >> 4); + } + s += 12; + c += 12; + k++; + j++; + } while (k < t); + } + memcpy(src, t_table, output_size); + free(t_table); + break; + + case 6: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + + t_table = (byte *)malloc(output_size); + memset(t_table, 0, output_size); + + src = comp_output; + length = (output_size * 8) / 12; + k = 0; + c = 0; + j = 0; + s = -12; + t_table[0] = src[output_size - 1]; + t_table[output_size - 1] = src[length - 1]; + t = length - 1; + if (t > 0) { + do { + ptr = src + length + k / 2; + if (k & 1) { + r = s / 8; + t_table[r + 2] = (src[j] & 0xf0) | *(t_table + r + 2); + t_table[r + 3] = ((src[j] & 0x0f) << 4) | (ptr[0] >> 4); + } else { + r = c / 8; + t_table[r + 2] = src[j] >> 4; + t_table[r + 1] = ((src[j] & 0x0f) << 4) | (ptr[0] & 0x0f); + } + s += 12; + c += 12; + k++; + j++; + } while (k < t); + } + memcpy(src, t_table, output_size); + free(t_table); + break; + + case 10: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + + t_table = (byte *)malloc(output_size); + memcpy(t_table, p, output_size); + + offset1 = output_size / 3; + offset2 = offset1 * 2; + offset3 = offset2; + src = comp_output; + do { + if (offset1 == 0) + break; + offset1--; + offset2 -= 2; + offset3--; + t_table[offset2 + 0] = src[offset1]; + t_table[offset2 + 1] = src[offset3]; + } while (1); + + src = comp_output; + length = (output_size * 8) / 12; + k = 0; + if (length > 0) { + c = -12; + s = 0; + do { + j = length + k / 2; + if (k & 1) { + r = c / 8; + t_tmp1 = t_table[k]; + t_tmp2 = t_table[j + 1]; + src[r + 2] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 >> 4); + src[r + 1] = (src[r + 1]) | (t_tmp1 & 0xf0); + } else { + r = s / 8; + t_tmp1 = t_table[k]; + t_tmp2 = t_table[j]; + src[r + 0] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f); + src[r + 1] = t_tmp1 >> 4; + } + s += 12; + c += 12; + k++; + } while (k < length); + } + offset1 = ((length - 1) * 3) / 2; + src[offset1 + 1] = (t_table[length] & 0xf0) | src[offset1 + 1]; + free(t_table); + break; + + case 11: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + + t_table = (byte *)malloc(output_size); + memcpy(t_table, p, output_size); + + offset1 = output_size / 3; + offset2 = offset1 * 2; + offset3 = offset2; + src = comp_output; + do { + if (offset1 == 0) + break; + offset1--; + offset2 -= 2; + offset3--; + t_table[offset2 + 0] = src[offset1]; + t_table[offset2 + 1] = src[offset3]; + } while (1); + + src = comp_output; + length = (output_size * 8) / 12; + k = 1; + c = 0; + s = 12; + t_tmp1 = t_table[length] / 16; + src[0] = t_tmp1; + t = length + k; + if (t > k) { + do { + j = length + k / 2; + if (k & 1) { + r = c / 8; + t_tmp1 = t_table[k - 1]; + t_tmp2 = t_table[j]; + src[r + 0] = (src[r]) | (t_tmp1 & 0xf0); + src[r + 1] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f); + } else { + r = s / 8; + t_tmp1 = t_table[k - 1]; + t_tmp2 = t_table[j]; + src[r + 0] = t_tmp1 >> 4; + src[r - 1] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 >> 4); + } + s += 12; + c += 12; + k++; + } while (k < t); + } + free(t_table); + break; + + case 12: + output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; + + t_table = (byte *)malloc(output_size); + memcpy(t_table, p, output_size); + + offset1 = output_size / 3; + offset2 = offset1 * 2; + offset3 = offset2; + src = comp_output; + do { + if (offset1 == 0) + break; + offset1--; + offset2 -= 2; + offset3--; + t_table[offset2 + 0] = src[offset1]; + t_table[offset2 + 1] = src[offset3]; + } while (1); + + src = comp_output; + length = (output_size * 8) / 12; + k = 0; + c = 0; + s = -12; + src[0] = t_table[output_size - 1]; + src[output_size - 1] = t_table[length - 1]; + t = length - 1; + if (t > 0) { + do { + j = length + k / 2; + if (k & 1) { + r = s / 8; + t_tmp1 = t_table[k]; + t_tmp2 = t_table[j]; + src[r + 2] = (src[r + 2]) | (t_tmp1 & 0xf0); + src[r + 3] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 >> 4); + } else { + r = c / 8; + t_tmp1 = t_table[k]; + t_tmp2 = t_table[j]; + src[r + 2] = t_tmp1 >> 4; + src[r + 1] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f); + } + s += 12; + c += 12; + k++; + } while (k < t); + } + free(t_table); + break; + + case 13: + case 15: + if (codec == 13) { + channels = 1; + } else { + channels = 2; + } + + { + const int MAX_CHANNELS = 2; + int32 left, startPos, origLeft, curTableEntry, destPos, esiReg; + int16 firstWord; + byte sByte[MAX_CHANNELS] = {0, 0}; + int32 sDWord1[MAX_CHANNELS] = {0, 0}; + int32 sDWord2[MAX_CHANNELS] = {0, 0}; + int32 tableEntrySum, imcTableEntry, curTablePos, outputWord, adder; + byte decompTable, otherTablePos, bitMask; + byte *readPos, *dst; + uint16 readWord; + + assert(0 <= channels && channels <= MAX_CHANNELS); + + src = comp_input; + dst = comp_output; + if (channels == 2) { + output_size = left = 0x2000; + } else { + left = 0x1000; + output_size = 0x2000; + } + firstWord = READ_BE_UINT16(src); + src += 2; + if (firstWord != 0) { + memcpy(dst, src, firstWord); + dst += firstWord; + src += firstWord; + startPos = 0; + if (channels == 2) { + left = 0x2000 - firstWord; + output_size = left; + } else { + left = 0x1000 - firstWord / 2; + output_size = left * 2; + } + } else { + startPos = 1; + for (int i = 0; i < channels; i++) { + sByte[i] = *(src++); + sDWord1[i] = READ_BE_UINT32(src); + src += 4; + sDWord2[i] = READ_BE_UINT32(src); + src += 4; + } + } + + origLeft = left >> (channels - 1); + tableEntrySum = 0; + for (int l = 0; l < channels; l++) { + if (startPos != 0) { + curTablePos = sByte[l]; + imcTableEntry = sDWord1[l]; + outputWord = sDWord2[l]; + } else { + curTablePos = 0; + imcTableEntry = 7; + outputWord = 0; + } + + left = origLeft; + destPos = l * 2; + + if (channels == 2) { + if (l == 0) + left++; + left /= 2; + } + + while (left--) { + curTableEntry = _destImcTable[curTablePos]; + decompTable = (byte)(curTableEntry - 2); + bitMask = 2 << decompTable; + readPos = src + tableEntrySum / 8; + + // FIXME - it seems the decoder often reads exactly one byte too + // far - that is, it reads 2 bytes at once, and the second byte + // is just outside the buffer. However, it seems of these two bytes, + // only the upper one is actually used, so this should be fine. + // Still, I put this error message into place. If somebody one day + // encounters a situation where the second byte would be used, too, + // then this would indicate there is a bug in the decoder... + if (readPos + 1 >= comp_input + input_size) { + // OK an overflow... if it is more than one byte or if we + // need more than 8 bit of data -> error + if (readPos + 1 > comp_input + input_size || + curTableEntry + (tableEntrySum & 7) > 8) { + error("decompressCodec: input buffer overflow: %d bytes over (we need %d bits of data)", + (int)((readPos + 1) - (comp_input + input_size)) + 1, + curTableEntry + (tableEntrySum & 7) + ); + } + } + readWord = (uint16)(READ_BE_UINT16(readPos) << (tableEntrySum & 7)); + otherTablePos = (byte)(readWord >> (16 - curTableEntry)); + tableEntrySum += curTableEntry; + esiReg = ((imxShortTable[curTableEntry] & otherTablePos) + << (7 - curTableEntry)) + (curTablePos * 64); + imcTableEntry >>= (curTableEntry - 1); + adder = imcTableEntry + _destImcTable2[esiReg]; + if ((otherTablePos & bitMask) != 0) { + adder = -adder; + } + outputWord += adder; + + // Clip outputWord to 16 bit signed, and write it into the destination stream + if (outputWord > 0x7fff) + outputWord = 0x7fff; + if (outputWord < -0x8000) + outputWord = -0x8000; + dst[destPos] = ((int16)outputWord) >> 8; + dst[destPos + 1] = (byte)(outputWord); + + // Adjust the curTablePos / imcTableEntry + assert(decompTable < 6); + curTablePos += (signed char)imxOtherTable[decompTable][otherTablePos]; + if (curTablePos > 88) + curTablePos = 88; + if (curTablePos < 0) + curTablePos = 0; + imcTableEntry = imcTable[curTablePos]; + + destPos += channels * 2; + } + } + } + break; + + default: + error("BundleCodecs::decompressCodec() Unknown codec %d!", (int)codec); + output_size = 0; + break; + } + + return output_size; +} + +} // End of namespace BundleCodecs + +} // End of namespace Scumm + +#ifdef __PALM_OS__ +#include "scumm_globals.h" + +_GINIT(BundleCodecs) +_GSETPTR(Scumm::BundleCodecs::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM) +_GEND + +_GRELEASE(BundleCodecs) +_GRELEASEPTR(GBVARS_IMCTABLE_INDEX, GBVARS_SCUMM) +_GEND + +#endif diff --git a/scumm/imuse_digi/dimuse_sndmgr.cpp b/scumm/imuse_digi/dimuse_sndmgr.cpp new file mode 100644 index 0000000000..51a3e5eb09 --- /dev/null +++ b/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -0,0 +1,462 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#include "stdafx.h" +#include "common/scummsys.h" +#include "common/util.h" +#include "sound/voc.h" +#include "scumm/scumm.h" +#include "scumm/imuse_digi/dimuse_sndmgr.h" +#include "scumm/imuse_digi/dimuse_bndmgr.h" + +namespace Scumm { + +ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) { + memset(&_sounds, 0, sizeof(_sounds)); + _scumm = scumm; + _mutex = g_system->create_mutex(); + _disk = 0; + _accessFree = true; + BundleCodecs::initializeImcTables(); +} + +ImuseDigiSndMgr::~ImuseDigiSndMgr() { + for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { + closeSound(&_sounds[l]); + } +} + +void ImuseDigiSndMgr::waitForFreeAccess() { + Common::StackLock lock(_mutex); + while (!_accessFree) { + } +} + +void ImuseDigiSndMgr::lock() { + Common::StackLock lock(_mutex); + waitForFreeAccess(); + _accessFree = false; +} + +void ImuseDigiSndMgr::unlock() { + Common::StackLock lock(_mutex); + _accessFree = true; +} + +void ImuseDigiSndMgr::prepareSound(byte *ptr, int slot) { + Common::StackLock lock(_mutex); + if (READ_UINT32(ptr) == MKID('Crea')) { + int size, rate, loops; + _sounds[slot].resPtr = readVOCFromMemory(ptr, size, rate, loops); + _sounds[slot].freeResPtr = true; + _sounds[slot].bits = 8; + _sounds[slot].freq = rate; + _sounds[slot].channels = 1; + _sounds[slot].region[0].length = size; + _sounds[slot].numRegions++; + _sounds[slot].numJumps++; + } else if (READ_UINT32(ptr) == MKID('iMUS')) { + uint32 tag; + int32 size = 0; + byte *s_ptr = ptr; + + ptr += 16; + do { + tag = READ_BE_UINT32(ptr); ptr += 4; + switch(tag) { + case MKID_BE('FRMT'): + ptr += 12; + _sounds[slot].bits = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].freq = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].channels = READ_BE_UINT32(ptr); ptr += 4; + break; + case MKID_BE('TEXT'): + size = READ_BE_UINT32(ptr); ptr += 4; + if (_sounds[slot].numMarkers >= MAX_IMUSE_MARKERS) { + warning("ImuseDigiSndMgr::prepareSound() Not enough space for Marker"); + ptr += size; + break; + } + strcpy(_sounds[slot].marker[_sounds[slot].numMarkers].name, (char *)ptr + 4); + _sounds[slot].numMarkers++; + ptr += size; + break; + case MKID_BE('REGN'): + size = READ_BE_UINT32(ptr); ptr += 4; + if (_sounds[slot].numRegions >= MAX_IMUSE_REGIONS) { + warning("ImuseDigiSndMgr::prepareSound() Not enough space for Region"); + ptr += 8; + break; + } + _sounds[slot].region[_sounds[slot].numRegions].offset = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].region[_sounds[slot].numRegions].length = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].numRegions++; + break; + case MKID_BE('STOP'): + ptr += 4; + _sounds[slot].offsetStop = READ_BE_UINT32(ptr); ptr += 4; + break; + case MKID_BE('JUMP'): + size = READ_BE_UINT32(ptr); ptr += 4; + if (_sounds[slot].numJumps >= MAX_IMUSE_JUMPS) { + warning("ImuseDigiSndMgr::prepareSound() Not enough space for Jump"); + ptr += size; + break; + } + _sounds[slot].jump[_sounds[slot].numJumps].offset = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].jump[_sounds[slot].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].jump[_sounds[slot].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].jump[_sounds[slot].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4; + _sounds[slot].numJumps++; + break; + case MKID_BE('SYNC'): + size = READ_BE_UINT32(ptr); ptr += size + 4; + break; + case MKID_BE('DATA'): + size = READ_BE_UINT32(ptr); ptr += 4; + break; + default: + error("ImuseDigiSndMgr::prepareSound() Unknown sfx header '%s'", tag2str(tag)); + } + } while (tag != MKID_BE('DATA')); + _sounds[slot].offsetData = ptr - s_ptr; + } else { + error("ImuseDigiSndMgr::prepareSound(): Unknown sound format"); + } +} + +int ImuseDigiSndMgr::allocSlot() { + Common::StackLock lock(_mutex); + for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { + if (!_sounds[l].inUse) { + _sounds[l].inUse = true; + return l; + } + } + + return -1; +} + +bool ImuseDigiSndMgr::openMusicBundle(int slot) { + Common::StackLock lock(_mutex); + bool result = false; + + _sounds[slot]._bundle = new BundleMgr(); + if (_scumm->_gameId == GID_CMI) { + if (_scumm->_features & GF_DEMO) { + result = _sounds[slot]._bundle->openFile("music.bun", _scumm->getGameDataPath()); + } else { + char musicfile[20]; + sprintf(musicfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); + if (_disk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) + _sounds[slot]._bundle->closeFile(); + + result = _sounds[slot]._bundle->openFile(musicfile, _scumm->getGameDataPath()); + + if (result == false) + result = _sounds[slot]._bundle->openFile("music.bun", _scumm->getGameDataPath()); + _disk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); + } + } else if (_scumm->_gameId == GID_DIG) + result = _sounds[slot]._bundle->openFile("digmusic.bun", _scumm->getGameDataPath()); + else + error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load"); + + return result; +} + +bool ImuseDigiSndMgr::openVoiceBundle(int slot) { + Common::StackLock lock(_mutex); + bool result = false; + + _sounds[slot]._bundle = new BundleMgr(); + if (_scumm->_gameId == GID_CMI) { + if (_scumm->_features & GF_DEMO) { + result = _sounds[slot]._bundle->openFile("voice.bun", _scumm->getGameDataPath()); + } else { + char voxfile[20]; + sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); + if (_disk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) + _sounds[slot]._bundle->closeFile(); + + result = _sounds[slot]._bundle->openFile(voxfile, _scumm->getGameDataPath()); + + if (result == false) + result = _sounds[slot]._bundle->openFile("voice.bun", _scumm->getGameDataPath()); + _disk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); + } + } else if (_scumm->_gameId == GID_DIG) + result = _sounds[slot]._bundle->openFile("digvoice.bun", _scumm->getGameDataPath()); + else + error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load"); + + return result; +} + +void *ImuseDigiSndMgr::openSound(int32 soundId, char *soundName, int soundType, int soundGroup) { + assert(soundId >= 0); + assert(soundType); + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + + int slot = allocSlot(); + if (slot == -1) { + error("ImuseDigiSndMgr::openSound() can't alloc free sound slot"); + } + + bool result = false; + byte *ptr = NULL; + + if (soundName == NULL) { + if ((soundType == IMUSE_RESOURCE)) { + ptr = _scumm->getResourceAddress(rtSound, soundId); + if (ptr == NULL) { + closeSound(&_sounds[slot]); + unlock(); + return NULL; + } + _sounds[slot].resPtr = ptr; + result = true; + } else if (soundType == IMUSE_BUNDLE) { + if (soundGroup == IMUSE_VOICE) + result = openVoiceBundle(slot); + else if (soundGroup == IMUSE_MUSIC) + result = openMusicBundle(slot); + else + error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId); + _sounds[slot]._bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0); + } else { + error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId); + } + } else if (soundName != NULL) { + if (soundType == IMUSE_BUNDLE) { + if (soundGroup == IMUSE_VOICE) + result = openVoiceBundle(slot); + else if (soundGroup == IMUSE_MUSIC) + result = openMusicBundle(slot); + else + error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId); + _sounds[slot]._bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr); + } else { + error("ImuseDigiSndMgr::openSound() Don't know how load sound: %s", soundName); + } + } + + if (result) { + if (ptr == NULL) { + closeSound(&_sounds[slot]); + unlock(); + return NULL; + } + prepareSound(ptr, slot); + void *soundHandle = &_sounds[slot]; + unlock(); + return soundHandle; + } + + unlock(); + return NULL; +} + +void ImuseDigiSndMgr::closeSound(void *soundHandle) { + assert(soundHandle && checkForProperHandle(soundHandle)); + Common::StackLock lock(_mutex); + + for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { + if (&_sounds[l] == soundHandle) { + if (_sounds[l].freeResPtr) + free(_sounds[l].resPtr); + if (_sounds[l]._bundle) + delete _sounds[l]._bundle; + memset(&_sounds[l], 0, sizeof(soundStruct)); + } + } +} + +bool ImuseDigiSndMgr::checkForProperHandle(void *soundHandle) { + Common::StackLock lock(_mutex); + for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { + if (soundHandle == &_sounds[l]) + return true; + } + return false; +} + +int ImuseDigiSndMgr::getFreq(void *soundHandle) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + int result = ((soundStruct *)soundHandle)->freq; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getBits(void *soundHandle) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + int result = ((soundStruct *)soundHandle)->bits; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getChannels(void *soundHandle) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + int result = ((soundStruct *)soundHandle)->channels; + unlock(); + return result; +} + +bool ImuseDigiSndMgr::isEndOfRegion(void *soundHandle, int region) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(region >= 0 && region < ((soundStruct *)soundHandle)->numRegions); + bool result = ((soundStruct *)soundHandle)->endFlag; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getNumRegions(void *soundHandle) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + int result = ((soundStruct *)soundHandle)->numRegions; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getNumJumps(void *soundHandle) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + int result = ((soundStruct *)soundHandle)->numJumps; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getNumMarkers(void *soundHandle) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + int result = ((soundStruct *)soundHandle)->numMarkers; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getJumpIdByRegion(void *soundHandle, int number) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(number >= 0 && number < ((soundStruct *)soundHandle)->numRegions); + for (int l = 0; l < ((soundStruct *)soundHandle)->numJumps; l++) { + if (((soundStruct *)soundHandle)->jump[number].offset == ((soundStruct *)soundHandle)->region[l].offset) + unlock(); + return l; + } + + unlock(); + return -1; +} + +int ImuseDigiSndMgr::getJumpDestRegionId(void *soundHandle, int number) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps); + for (int l = 0; l < ((soundStruct *)soundHandle)->numRegions; l++) { + if (((soundStruct *)soundHandle)->jump[number].dest == ((soundStruct *)soundHandle)->region[l].offset) { + unlock(); + return l; + } + } + + unlock(); + return -1; +} + +int ImuseDigiSndMgr::getJumpHookId(void *soundHandle, int number) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps); + int result = ((soundStruct *)soundHandle)->jump[number].hookId; + unlock(); + return result; +} + +int ImuseDigiSndMgr::getJumpFade(void *soundHandle, int number) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps); + unlock(); + return ((soundStruct *)soundHandle)->jump[number].fadeDelay; +} + +char *ImuseDigiSndMgr::getMarker(void *soundHandle, int number) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(number >= 0 && number < ((soundStruct *)soundHandle)->numMarkers); + char *result = (char *)(((soundStruct *)soundHandle)->marker[number].name); + unlock(); + return result; +} + +int32 ImuseDigiSndMgr::getDataFromRegion(void *soundHandle, int region, byte **buf, int32 offset, int32 size) { + Common::StackLock lock(_mutex); + ImuseDigiSndMgr::lock(); + assert(soundHandle && checkForProperHandle(soundHandle)); + assert(buf && offset >= 0 && size >= 0); + assert(region >= 0 && region < ((soundStruct *)soundHandle)->numRegions); + + int32 region_offset = ((soundStruct *)soundHandle)->region[region].offset; + int32 region_length = ((soundStruct *)soundHandle)->region[region].length; + int32 offset_data = ((soundStruct *)soundHandle)->offsetData; + int32 start = region_offset - offset_data; + + if (offset + size + offset_data > region_length) { + size = region_length - offset; + ((soundStruct *)soundHandle)->endFlag = true; + } else { + ((soundStruct *)soundHandle)->endFlag = false; + } + + int header_size = ((soundStruct *)soundHandle)->offsetData; + + if (((soundStruct *)soundHandle)->_bundle) { +// *buf = (byte *)malloc(size); +// memset(*buf, 0, size); + size = ((soundStruct *)soundHandle)->_bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size); + } else if (((soundStruct *)soundHandle)->resPtr) { + byte *ptr = ((soundStruct *)soundHandle)->resPtr; + *buf = (byte *)malloc(size); +// warning("%d, %d, %d", start + header_size + offset, region_offset + region_length, size); + memcpy(*buf, ptr + start + offset + header_size, size); + } + + unlock(); + return size; +} + +} // End of namespace Scumm diff --git a/scumm/imuse_digi/dimuse_sndmgr.h b/scumm/imuse_digi/dimuse_sndmgr.h new file mode 100644 index 0000000000..9ac8cf7f32 --- /dev/null +++ b/scumm/imuse_digi/dimuse_sndmgr.h @@ -0,0 +1,126 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#ifndef IMUSE_DIGI_SNDMGR_H +#define IMUSE_DIGI_SNDMGR_H + +#include "stdafx.h" +#include "common/scummsys.h" +#include "common/system.h" + +namespace Scumm { + +class ScummEngine; +class BundleMgr; + +class ImuseDigiSndMgr { +public: + +#define MAX_IMUSE_SOUNDS 20 +#define MAX_IMUSE_JUMPS 50 +#define MAX_IMUSE_REGIONS 50 +#define MAX_IMUSE_MARKERS 50 + +#define IMUSE_RESOURCE 1 +#define IMUSE_BUNDLE 2 +#define IMUSE_VOICE 1 +#define IMUSE_SFX 2 +#define IMUSE_MUSIC 3 + +private: + struct _region { + int32 offset; // offset of region + int32 length; // lenght of region + }; + + struct _jump { + int32 offset; // jump offset position + int32 dest; // jump to dest position + int hookId; // id of hook + int fadeDelay; // fade delay in ms + }; + + struct _marker { + char name[256]; // name of marker + }; + + struct soundStruct { + int freq; // frequency + int channels; // stereo or mono + int bits; // 8, 12, 16 + int numJumps; // number of Jumps + int numRegions; // number of Regions + int numMarkers; // number of Markers + int32 offsetStop; // end offset in source data + bool endFlag; + bool inUse; + byte *allData; + int32 offsetData; + byte *resPtr; + bool freeResPtr; + BundleMgr *_bundle; + _region region[MAX_IMUSE_REGIONS]; + _marker marker[MAX_IMUSE_MARKERS]; + _jump jump[MAX_IMUSE_JUMPS]; + } _sounds[MAX_IMUSE_SOUNDS]; + + bool checkForProperHandle(void *soundHandle); + int allocSlot(); + void prepareSound(byte *ptr, int slot); + + ScummEngine *_scumm; + OSystem::MutexRef _mutex; + byte _disk; + bool _accessFree; + + void waitForFreeAccess(); + void lock(); + void unlock(); + + bool openMusicBundle(int slot); + bool openVoiceBundle(int slot); + +public: + + ImuseDigiSndMgr(ScummEngine *scumm); + ~ImuseDigiSndMgr(); + + void *openSound(int32 soundId, char *soundName, int soundType, int soundGroup); + void closeSound(void *soundHandle); + + int getFreq(void *soundHandle); + int getBits(void *soundHandle); + int getChannels(void *soundHandle); + bool isEndOfRegion(void *soundHandle, int region); + int getNumRegions(void *soundHandle); + int getNumJumps(void *soundHandle); + int getNumMarkers(void *soundHandle); + int getJumpIdByRegion(void *soundHandle, int number); + int getJumpDestRegionId(void *soundHandle, int number); + int getJumpHookId(void *soundHandle, int number); + int getJumpFade(void *soundHandle, int number); + char *getMarker(void *soundHandle, int number); + + int32 getDataFromRegion(void *soundHandle, int region, byte **buf, int32 offset, int32 size); +}; + +} // End of namespace Scumm + +#endif diff --git a/scumm/imuse_digi/dimuse_tables.cpp b/scumm/imuse_digi/dimuse_tables.cpp new file mode 100644 index 0000000000..d9f5fa9301 --- /dev/null +++ b/scumm/imuse_digi/dimuse_tables.cpp @@ -0,0 +1,583 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#include "stdafx.h" +#include "scumm/imuse_digi/dimuse.h" + +namespace Scumm { + +imuse_music_map _digStateMusicMap[] = { + {0, 0, 0, 0, 0, 0 }, + {1, 0, 0, 0, 0, 0 }, + {2, 2, 0, 0, 0, 0 }, + {4, 3, 0, 0, 0, 0 }, + {5, 3, 0, 0, 0, 0 }, + {6, 3, 0, 0, 0, 0 }, + {7, 3, 0, 0, 0, 0 }, + {8, 4, 0, 0, 0, 0 }, + {9, 5, 0, 0, 0, 0 }, + {10, 4, 0, 0, 0, 0 }, + {12, 5, 0, 0, 0, 0 }, + {14, 5, 0, 0, 0, 0 }, + {15, 6, 29, 7, 0, 0 }, + {16, 8, 0, 0, 0, 0 }, + {17, 1, 0, 0, 0, 0 }, + {18, 9, 0, 0, 0, 0 }, + {19, 9, 0, 0, 0, 0 }, + {20, 6, 0, 0, 0, 0 }, + {21, 6, 0, 0, 0, 0 }, + {22, 44, 0, 0, 0, 0 }, + {23, 10, 7, 0, 0, 0 }, + {24, 26, 0, 0, 0, 0 }, + {25, 17, 0, 0, 0, 0 }, + {26, 17, 0, 0, 0, 0 }, + {27, 18, 0, 0, 0, 0 }, + {28, 1, 0, 0, 0, 0 }, + {29, 20, 0, 0, 0, 0 }, + {30, 22, 0, 0, 0, 0 }, + {31, 23, 0, 0, 0, 0 }, + {32, 22, 0, 0, 0, 0 }, + {33, 26, 0, 0, 0, 0 }, + {34, 24, 0, 0, 0, 0 }, + {35, 1, 0, 0, 0, 0 }, + {36, 1, 0, 0, 0, 0 }, + {37, 42, 0, 0, 0, 0 }, + {38, 43, 0, 0, 0, 0 }, + {39, 44, 0, 0, 0, 0 }, + {40, 1, 0, 0, 0, 0 }, + {41, 43, 0, 0, 0, 0 }, + {42, 44, 0, 0, 0, 0 }, + {43, 43, 0, 0, 0, 0 }, + {44, 45, 117,45, 114,46}, + {47, 1, 0, 0, 0, 0 }, + {48, 43, 0, 0, 0, 0 }, + {49, 44, 0, 0, 0, 0 }, + {51, 1, 0, 0, 0, 0 }, + {53, 28, 0, 0, 0, 0 }, + {54, 28, 0, 0, 0, 0 }, + {55, 29, 0, 0, 0, 0 }, + {56, 29, 0, 0, 0, 0 }, + {57, 29, 0, 0, 0, 0 }, + {58, 31, 0, 0, 0, 0 }, + {59, 1, 0, 0, 0, 0 }, + {60, 37, 0, 0, 0, 0 }, + {61, 39, 0, 0, 0, 0 }, + {62, 38, 0, 0, 0, 0 }, + {63, 39, 0, 0, 0, 0 }, + {64, 39, 0, 0, 0, 0 }, + {65, 40, 0, 0, 0, 0 }, + {67, 40, 0, 0, 0, 0 }, + {68, 39, 0, 0, 0, 0 }, + {69, 1, 0, 0, 0, 0 }, + {70, 49, 0, 0, 0, 0 }, + {73, 50, 0, 0, 0, 0 }, + {75, 51, 0, 0, 0, 0 }, + {76, 1, 0, 0, 0, 0 }, + {77, 52, 7, 0, 0, 0 }, + {78, 63, 0, 0, 0, 0 }, + {79, 1, 0, 0, 0, 0 }, + {82, 21, 0, 0, 0, 0 }, + {85, 1, 0, 0, 0, 0 }, + {86, 0, 0, 0, 0, 0 }, + {89, 33, 6, 35, 5, 34}, + {90, 16, 0, 0, 0, 0 }, + {91, 57, 0, 0, 0, 0 }, + {88, 32, 0, 0, 0, 0 }, + {92, 25, 0, 0, 0, 0 }, + {93, 0, 0, 0, 0, 0 }, + {95, 19, 0, 0, 0, 0 }, + {80, 41, 0, 0, 0, 0 }, + {81, 48, 0, 0, 0, 0 }, + {83, 27, 0, 0, 0, 0 }, + {94, 36, 0, 0, 0, 0 }, + {40, 1, 0, 0, 0, 0 }, + {96, 13, 0, 0, 0, 0 }, + {97, 14, 0, 0, 0, 0 }, + {98, 11, 0, 0, 0, 0 }, + {99, 15, 0, 0, 0, 0 }, + {100, 17, 0, 0, 0, 0 }, + {101, 38, 0, 0, 0, 0 }, + {103, 0, 0, 0, 0, 0 }, + {104, 0, 0, 0, 0, 0 }, + {11, 44, 0, 0, 0, 0 }, + {3, 47, 0, 0, 0, 0 }, + {105, 30, 128,29, 0, 0 }, + {106, 0, 0, 0, 0, 0 }, + {107, 1, 0, 0, 0, 0 }, + {108, 1, 0, 0, 0, 0 }, + {47, 1, 0, 0, 0, 0 }, + {50, 1, 0, 0, 0, 0 }, + {52, 0, 0, 0, 0, 0 }, + {71, 1, 0, 0, 0, 0 }, + {13, 1, 0, 0, 0, 0 }, + {72, 1, 0, 0, 0, 0 }, + {46, 33, 6, 35, 5, 34}, + {74, 1, 0, 0, 0, 0 }, + {84, 1, 0, 0, 0, 0 }, + {66, 1, 0, 0, 0, 0 }, + {102, 1, 0, 0, 0, 0 }, + {109, 1, 0, 0, 0, 0 }, + {110, 2, 0, 0, 0, 0 }, + {45, 1, 0, 0, 0, 0 }, + {87, 1, 0, 0, 0, 0 }, + {111, 1, 0, 0, 0, 0 }, + {-1, 1, 0, 0, 0, 0 } +}; + +const imuse_music_table _digStateMusicTable[] = { + {0, 1000, 0, 0, 0, 0, "STATE_NULL", "", ""}, + {1, 1001, 0, 0, 0, 0, "stateNoChange", "", ""}, + {2, 1100, 0, 3, 2, 0, "stateAstShip", "Asteroid (amb-ship)", "ASTERO~1.IMU"}, + {3, 1120, 0, 3, 2, 0, "stateAstClose", "Asteroid (amb-close)", "ASTERO~2.IMU"}, + {4, 1140, 0, 3, 0, 0, "stateAstInside", "Asteroid (inside)", "ASTERO~3.IMU"}, + {5, 1150, 0, 3, 0, 0, "stateAstCore", "Asteroid (core)", "ASTERO~4.IMU"}, + {6, 1200, 0, 3, 0, 0, "stateCanyonClose", "Canyon (close)", "CANYON~1.IMU"}, + {7, 1205, 0, 3, 0, 0, "stateCanyonClose_m", "Canyon (close-m)", "CANYON~2.IMU"}, + {8, 1210, 0, 3, 0, 0, "stateCanyonOver", "Canyon (over)", "CANYON~3.IMU"}, + {9, 1220, 0, 3, 0, 0, "stateCanyonWreck", "Canyon (wreck)", "CANYON~4.IMU"}, + {10, 1300, 0, 3,10, 0, "stateNexusCanyon", "Nexus (plan)", "NEXUS(~1.IMU"}, + {11, 1310, 0, 3,10, 0, "stateNexusPlan", "Nexus (plan)", "NEXUS(~1.IMU"}, + {12, 1320, 0, 3,10, 0, "stateNexusRamp", "Nexus (ramp)", "NEXUS(~2.IMU"}, + {13, 1330, 0, 3,10, 0, "stateNexusMuseum", "Nexus (museum)", "NEXUS(~3.IMU"}, + {14, 1340, 0, 3,10, 0, "stateNexusMap", "Nexus (map)", "NEXUS(~4.IMU"}, + {15, 1350, 0, 3,10, 0, "stateNexusTomb", "Nexus (tomb)", "NE3706~5.IMU"}, + {16, 1360, 0, 3,10, 0, "stateNexusCath", "Nexus (cath)", "NE3305~5.IMU"}, + {17, 1370, 0, 3, 0, 0, "stateNexusAirlock", "Nexus (airlock)", "NE2D3A~5.IMU"}, + {18, 1380, 0, 3, 0, 0, "stateNexusPowerOff", "Nexus (power)", "NE8522~5.IMU"}, + {19, 1400, 0, 3, 0, 0, "stateMuseumTramNear", "Tram (mu-near)", "TRAM(M~1.IMU"}, + {20, 1410, 0, 3, 0, 0, "stateMuseumTramFar", "Tram (mu-far)", "TRAM(M~2.IMU"}, + {21, 1420, 0, 3, 0, 0, "stateMuseumLockup", "Museum (lockup)", "MUSEUM~1.IMU"}, + {22, 1433, 0, 3,22, 0, "stateMuseumPool", "Museum (amb-pool)", "MUSEUM~2.IMU"}, + {23, 1436, 0, 3,22, 0, "stateMuseumSpire", "Museum (amb-spire)", "MUSEUM~3.IMU"}, + {24, 1440, 0, 3,22, 0, "stateMuseumMuseum", "Museum (amb-mu)", "MUSEUM~4.IMU"}, + {25, 1450, 0, 3, 0, 0, "stateMuseumLibrary", "Museum (library)", "MUB575~5.IMU"}, + {26, 1460, 0, 3, 0, 0, "stateMuseumCavern", "Museum (cavern)", "MUF9BE~5.IMU"}, + {27, 1500, 0, 3, 0, 0, "stateTombTramNear", "Tram (tomb-near)", "TRAM(T~1.IMU"}, + {28, 1510, 0, 3,28, 0, "stateTombBase", "Tomb (amb-base)", "TOMB(A~1.IMU"}, + {29, 1520, 0, 3,28, 0, "stateTombSpire", "Tomb (amb-spire)", "TOMB(A~2.IMU"}, + {30, 1530, 0, 3,28, 0, "stateTombCave", "Tomb (amb-cave)", "TOMB(A~3.IMU"}, + {31, 1540, 0, 3,31, 0, "stateTombCrypt", "Tomb (crypt)", "TOMB(C~1.IMU"}, + {32, 1550, 0, 3,31, 0, "stateTombGuards", "Tomb (crypt-guards)", "TOMB(C~2.IMU"}, + {33, 1560, 0, 3, 0, 0, "stateTombInner", "Tomb (inner)", "TOMB(I~1.IMU"}, + {34, 1570, 0, 3, 0, 0, "stateTombCreator1", "Tomb (creator 1)", "TOMB(C~3.IMU"}, + {35, 1580, 0, 3, 0, 0, "stateTombCreator2", "Tomb (creator 2)", "TOMB(C~4.IMU"}, + {36, 1600, 0, 3, 0, 0, "statePlanTramNear", "Tram (plan-near)", "TRAM(P~1.IMU"}, + {37, 1610, 0, 3, 0, 0, "statePlanTramFar", "Tram (plan-far)", "TRAM(P~2.IMU"}, + {38, 1620, 0, 3,38, 0, "statePlanBase", "Plan (amb-base)", "PLAN(A~1.IMU"}, + {39, 1630, 0, 3,38, 0, "statePlanSpire", "Plan (amb-spire)", "PLAN(A~2.IMU"}, + {40, 1650, 0, 3, 0, 0, "statePlanDome", "Plan (dome)", "PLAN(D~1.IMU"}, + {41, 1700, 0, 3, 0, 0, "stateMapTramNear", "Tram (map-near)", "TRAM(M~3.IMU"}, + {42, 1710, 0, 3, 0, 0, "stateMapTramFar", "Tram (map-far)", "TRAM(M~4.IMU"}, + {43, 1720, 0, 3,43, 0, "stateMapCanyon", "Map (amb-canyon)", "MAP(AM~1.IMU"}, + {44, 1730, 0, 3,43, 0, "stateMapExposed", "Map (amb-exposed)", "MAP(AM~2.IMU"}, + {45, 1750, 0, 3,43, 0, "stateMapNestEmpty", "Map (amb-nest)", "MAP(AM~4.IMU"}, + {46, 1760, 0, 3, 0, 0, "stateMapNestMonster", "Map (monster)", "MAP(MO~1.IMU"}, + {47, 1770, 0, 3, 0, 0, "stateMapKlein", "Map (klein)", "MAP(KL~1.IMU"}, + {48, 1800, 0, 3, 0, 0, "stateCathTramNear", "Tram (cath-near)", "TRAM(C~1.IMU"}, + {49, 1810, 0, 3, 0, 0, "stateCathTramFar", "Tram (cath-far)", "TRAM(C~2.IMU"}, + {50, 1820, 0, 3,50, 0, "stateCathLab", "Cath (amb-inside)", "CATH(A~1.IMU"}, + {51, 1830, 0, 3,50, 0, "stateCathOutside", "Cath (amb-outside)", "CATH(A~2.IMU"}, + {52, 1900, 0, 3,52, 0, "stateWorldMuseum", "World (museum)", "WORLD(~1.IMU"}, + {53, 1901, 0, 3,52, 0, "stateWorldPlan", "World (plan)", "WORLD(~2.IMU"}, + {54, 1902, 0, 3,52, 0, "stateWorldTomb", "World (tomb)", "WORLD(~3.IMU"}, + {55, 1903, 0, 3,52, 0, "stateWorldMap", "World (map)", "WORLD(~4.IMU"}, + {56, 1904, 0, 3,52, 0, "stateWorldCath", "World (cath)", "WO3227~5.IMU"}, + {57, 1910, 0, 3, 0, 0, "stateEye1", "Eye 1", "EYE1~1.IMU"}, + {58, 1911, 0, 3, 0, 0, "stateEye2", "Eye 2", "EYE2~1.IMU"}, + {59, 1912, 0, 3, 0, 0, "stateEye3", "Eye 3", "EYE3~1.IMU"}, + {60, 1913, 0, 3, 0, 0, "stateEye4", "Eye 4", "EYE4~1.IMU"}, + {61, 1914, 0, 3, 0, 0, "stateEye5", "Eye 5", "EYE5~1.IMU"}, + {62, 1915, 0, 3, 0, 0, "stateEye6", "Eye 6", "EYE6~1.IMU"}, + {63, 1916, 0, 3, 0, 0, "stateEye7", "Eye 7", "EYE7~1.IMU"}, + {-1, -1, 0, 0, 0, 0, "", "", ""} +}; + +const imuse_music_table _digSeqMusicTable[] = { + {0, 2000, 0, 0, 0, 0, "SEQ_NULL", "", "" }, + {0, 2005, 0, 0, 0, 0, "seqLogo", "", "" }, + {0, 2010, 0, 0, 0, 0, "seqIntro", "", "" }, + {0, 2020, 0, 6, 0, 0, "seqExplosion1b", "", "" }, + {0, 2030, 0, 3, 0, 0, "seqAstTunnel1a", "Seq (ast tunnel 1a)", "SEQ(AS~1.IMU"}, + {0, 2031, 0, 6, 0, 0, "seqAstTunnel2b", "", "" }, + {0, 2032, 0, 4, 0, 0, "seqAstTunnel3a", "Seq (ast tunnel 3a)", "SEQ(AS~2.IMU"}, + {0, 2040, 0, 5, 0, 0, "seqToPlanet1b", "", "" }, + {0, 2045, 0, 4, 0, 0, "seqArgBegin", "Seq (arg begin)", "SEQ(AR~1.IMU"}, + {0, 2046, 0, 4, 0, 0, "seqArgEnd", "Seq (arg end)", "SEQ(AR~2.IMU"}, + {0, 2050, 0, 4, 0, 0, "seqWreckGhost", "Seq (ghost-wreck)", "SEQ(GH~1.IMU"}, + {0, 2060, 0, 4, 0, 0, "seqCanyonGhost", "Seq (ghost-canyon)", "SEQ(GH~2.IMU"}, + {0, 2070, 0, 0, 0, 0, "seqBrinkFall", "", "" }, + {0, 2080, 0, 4, 0, 0, "seqPanUpCanyon", "Seq (pan up canyon)", "SEQ(PA~1.IMU"}, + {0, 2091, 0, 6, 0, 0, "seqAirlockTunnel1b", "", "" }, + {0, 2100, 0, 6, 0, 0, "seqTramToMu", "", "" }, + {0, 2101, 0, 6, 0, 0, "seqTramFromMu", "", "" }, + {0, 2102, 0, 6, 0, 0, "seqTramToTomb", "", "" }, + {0, 2103, 0, 6, 0, 0, "seqTramFromTomb", "", "" }, + {0, 2104, 0, 6, 0, 0, "seqTramToPlan", "", "" }, + {0, 2105, 0, 6, 0, 0, "seqTramFromPlan", "", "" }, + {0, 2106, 0, 6, 0, 0, "seqTramToMap", "", "" }, + {0, 2107, 0, 6, 0, 0, "seqTramFromMap", "", "" }, + {0, 2108, 0, 6, 0, 0, "seqTramToCath", "", "" }, + {0, 2109, 0, 6, 0, 0, "seqTramFromCath", "", "" }, + {0, 2110, 0, 0, 0, 0, "seqMuseumGhost", "", "" }, + {0, 2120, 0, 0, 0, 0, "seqSerpentAppears", "", "" }, + {0, 2130, 0, 0, 0, 0, "seqSerpentEats", "", "" }, + {0, 2140, 0, 6, 0, 0, "seqBrinkRes1b", "", "" }, + {0, 2141, 0, 4, 0, 0, "seqBrinkRes2a", "Seq (brink's madness)", "SEQ(BR~1.IMU"}, + {0, 2150, 0, 3, 0, 0, "seqLockupEntry", "Seq (brink's madness)", "SEQ(BR~1.IMU"}, + {0, 2160, 0, 0, 0, 0, "seqSerpentExplodes", "", "" }, + {0, 2170, 0, 4, 0, 0, "seqSwimUnderwater", "Seq (descent)", "SEQ(DE~1.IMU"}, + {0, 2175, 0, 4, 0, 0, "seqWavesPlunge", "Seq (plunge)", "SEQ(PL~1.IMU"}, + {0, 2180, 0, 0, 0, 0, "seqCryptOpens", "", "" }, + {0, 2190, 0, 0, 0, 0, "seqGuardsFight", "", "" }, + {0, 2200, 0, 3, 0, 0, "seqCreatorRes1.1a", "Seq (creator res 1.1a)", "SEQ(CR~1.IMU"}, + {0, 2201, 0, 6, 0, 0, "seqCreatorRes1.2b", "", "" }, + {0, 2210, 0, 6, 0, 0, "seqMaggieCapture1b", "", "" }, + {0, 2220, 0, 3, 0, 0, "seqStealCrystals", "Seq (brink's madness)", "SEQ(BR~1.IMU"}, + {0, 2230, 0, 0, 0, 0, "seqGetByMonster", "", "" }, + {0, 2240, 0, 6, 0, 0, "seqKillMonster1b", "", "" }, + {0, 2250, 0, 3, 0, 0, "seqCreatorRes2.1a", "Seq (creator res 2.1a)", "SEQ(CR~2.IMU"}, + {0, 2251, 0, 6, 0, 0, "seqCreatorRes2.2b", "", "" }, + {0, 2252, 0, 4, 0, 0, "seqCreatorRes2.3a", "Seq (creator res 2.3a)", "SEQ(CR~3.IMU"}, + {0, 2260, 0, 0, 0, 0, "seqMaggieInsists", "", "" }, + {0, 2270, 0, 0, 0, 0, "seqBrinkHelpCall", "", "" }, + {0, 2280, 0, 3, 0, 0, "seqBrinkCrevice1a", "Seq (brink crevice 1a)", "SEQ(BR~2.IMU"}, + {0, 2281, 0, 3, 0, 0, "seqBrinkCrevice2a", "Seq (brink crevice 2a)", "SEQ(BR~3.IMU"}, + {0, 2290, 0, 6, 0, 0, "seqCathAccess1b", "", "" }, + {0, 2291, 0, 4, 0, 0, "seqCathAccess2a", "Seq (cath access 2a)", "SEQ(CA~1.IMU"}, + {0, 2300, 0, 3, 0, 0, "seqBrinkAtGenerator", "Seq (brink's madness)", "SEQ(BR~1.IMU"}, + {0, 2320, 0, 6, 0, 0, "seqFightBrink1b", "", "" }, + {0, 2340, 0, 6, 0, 0, "seqMaggieDies1b", "", "" }, + {0, 2346, 0, 6, 0, 0, "seqMaggieRes1b", "", "" }, + {0, 2347, 0, 4, 0, 0, "seqMaggieRes2a", "Seq (maggie res 2a)", "SEQ(MA~1.IMU"}, + {0, 2350, 0, 0, 0, 0, "seqCreatureFalls", "", "" }, + {0, 2360, 0, 5, 0, 0, "seqFinale1b", "", "" }, + {0, 2370, 0, 3, 0, 0, "seqFinale2a", "Seq (finale 2a)", "SEQ(FI~1.IMU"}, + {0, 2380, 0, 6, 0, 0, "seqFinale3b1", "", "" }, + {0, 2390, 0, 6, 0, 0, "seqFinale3b2", "", "" }, + {0, 2400, 0, 3, 0, 0, "seqFinale4a", "Seq (finale 4a)", "SEQ(FI~2.IMU"}, + {0, 2410, 0, 3, 0, 0, "seqFinale5a", "Seq (finale 5a)", "SEQ(FI~3.IMU"}, + {0, 2420, 0, 3, 0, 0, "seqFinale6a", "Seq (finale 6a)", "SEQ(FI~4.IMU"}, + {0, 2430, 0, 3, 0, 0, "seqFinale7a", "Seq (finale 7a)", "SE3D2B~5.IMU"}, + {0, 2440, 0, 6, 0, 0, "seqFinale8b", "", "" }, + {0, 2450, 0, 4, 0, 0, "seqFinale9a", "Seq (finale 9a)", "SE313B~5.IMU"}, + {-1, -1, 0, 0, 0, 0, "", "", "" } +}; + +const imuse_music_table _comiStateMusicTable[] = { + {0, 1000, 0, 0, 0, 0, "STATE_NULL", "", ""}, + {0, 1001, 0, 0, 0, 0, "stateNoChange", "", ""}, + {0, 1098, 0, 3, 0, 0, "stateCredits1", "1098-Credits1", "1098-C~1.IMX"}, + {0, 1099, 0, 3, 0, 0, "stateMenu", "1099-Menu", "1099-M~1.IMX"}, + {0, 1100, 0, 3, 0, 0, "stateHold1", "1100-Hold1", "1100-H~1.IMX"}, + {0, 1101, 0, 3, 1, 0, "stateWaterline1", "1101-Waterline1", "1101-W~1.IMX"}, + {0, 1102, 0, 3, 0, 0, "stateHold2", "1102-Hold2", "1102-H~1.IMX"}, + {0, 1103, 0, 3, 0, 0, "stateWaterline2", "1103-Waterline2", "1103-W~1.IMX"}, + {0, 1104, 0, 3, 0, 0, "stateCannon", "1104-Cannon", "1104-C~1.IMX"}, + {0, 1105, 0, 3, 0, 0, "stateTreasure", "1105-Treasure", "1105-T~1.IMX"}, + {0, 1200, 0, 3, 1, 0, "stateFortBase", "1200-Fort Base", "1200-F~1.IMX"}, + {0, 1201, 0, 3, 1, 0, "statePreFort", "1201-Pre-Fort", "1201-P~1.IMX"}, + {0, 1202, 0, 3, 0, 0, "statePreVooOut", "1202-PreVoo Out", "1202-P~1.IMX"}, + {0, 1203, 0, 3, 0, 0, "statePreVooIn", "1203-PreVoo In", "1203-P~1.IMX"}, + {0, 1204, 0, 3, 0, 0, "statePreVooLad", "1204-PreVoo Lady", "1204-P~1.IMX"}, + {0, 1205, 0, 3, 0, 0, "stateVoodooOut", "1205-Voodoo Out", "1205-V~1.IMX"}, + {0, 1210, 0, 3, 0, 0, "stateVoodooIn", "1210-Voodoo In", "1210-V~1.IMX"}, + {0, 1212, 0,12, 1, 0, "stateVoodooInAlt", "1210-Voodoo In", "1210-V~1.IMX"}, + {0, 1215, 0, 3, 0, 0, "stateVoodooLady", "1215-Voodoo Lady", "1215-V~1.IMX"}, + {0, 1219, 0, 3, 0, 0, "statePrePlundermap", "1219-Pre-Map", "1219-P~1.IMX"}, + {0, 1220, 0, 3, 0, 0, "statePlundermap", "1220-Plunder Map", "1220-P~1.IMX"}, + {0, 1222, 0, 3, 0, 0, "statePreCabana", "1222-Pre-Cabana", "1222-P~1.IMX"}, + {0, 1223, 0, 3, 0, 0, "stateCabana", "1223-Cabana", "1223-C~1.IMX"}, + {0, 1224, 0, 3, 0, 0, "statePostCabana", "1224-Post-Cabana", "1224-P~1.IMX"}, + {0, 1225, 0, 3, 0, 0, "stateBeachClub", "1225-Beach Club", "1225-B~1.IMX"}, + {0, 1230, 0, 3, 0, 0, "stateCliff", "1230-Cliff", "1230-C~1.IMX"}, + {0, 1232, 0, 3, 0,800, "stateBelly", "1232-Belly", "1232-B~1.IMX"}, + {0, 1235, 0, 3, 0, 0, "stateQuicksand", "1235-Quicksand", "1235-Q~1.IMX"}, + {0, 1240, 0, 3, 0,800, "stateDangerBeach", "1240-Danger Beach", "1240-D~1.IMX"}, + {0, 1241, 0,12, 2,800, "stateDangerBeachAlt","1240-Danger Beach", "1240-D~1.IMX"}, + {0, 1245, 0, 3, 0, 0, "stateRowBoat", "1245-Row Boat", "1245-R~1.IMX"}, + {0, 1247, 0, 3, 0,800, "stateAlongside", "1247-Alongside", "1247-A~1.IMX"}, + {0, 1248, 0,12, 1,800, "stateAlongsideAlt", "1247-Alongside", "1247-A~1.IMX"}, + {0, 1250, 0, 3, 0,500, "stateChimpBoat", "1250-Chimp Boat", "1250-C~1.IMX"}, + {0, 1255, 0, 3, 0,800, "stateMrFossey", "1255-Mr Fossey", "1255-M~1.IMX"}, + {0, 1259, 0, 3, 0, 0, "statePreTown", "1259-Pre-Town", "1259-P~1.IMX"}, + {0, 1260, 0, 3, 0, 0, "stateTown", "1260-Town", "1260-T~1.IMX"}, + {0, 1264, 0, 3, 0, 0, "statePreMeadow", "1264-Pre-Meadow", "1264-P~1.IMX"}, + {0, 1265, 0, 3, 0, 0, "stateMeadow", "1265-Meadow", "1265-M~1.IMX"}, + {0, 1266, 0, 3, 0, 0, "stateMeadowAmb", "1266-Meadow Amb", "1266-M~1.IMX"}, + {0, 1270, 0, 3, 0, 0, "stateWardrobePre", "1270-Wardrobe-Pre", "1270-W~1.IMX"}, + {0, 1272, 0, 3, 0, 0, "statePreShow", "1272-Pre-Show", "1272-P~1.IMX"}, + {0, 1274, 0, 3, 0, 0, "stateWardrobeShow", "1274-Wardrobe-Show", "1274-W~1.IMX"}, + {0, 1276, 0, 3, 0, 0, "stateShow", "1276-Show", "1276-S~1.IMX"}, + {0, 1277, 0, 3, 0, 0, "stateWardrobeJug", "1277-Wardrobe-Jug", "1277-W~1.IMX"}, + {0, 1278, 0, 3, 0, 0, "stateJuggling", "1278-Juggling", "1278-J~1.IMX"}, + {0, 1279, 0, 3, 0, 0, "statePostShow", "1279-Post-Show", "1279-P~1.IMX"}, + {0, 1280, 0, 3, 0, 0, "stateChickenShop", "1280-Chicken Shop", "1280-C~1.IMX"}, + {0, 1285, 0, 3, 0, 0, "stateBarberShop", "1285-Barber Shop", "1285-B~1.IMX"}, + {0, 1286, 0, 3, 0, 0, "stateVanHelgen", "1286-Van Helgen", "1286-V~1.IMX"}, + {0, 1287, 0, 3, 0, 0, "stateBill", "1287-Bill", "1287-B~1.IMX"}, + {0, 1288, 0, 3, 0, 0, "stateHaggis", "1288-Haggis", "1288-H~1.IMX"}, + {0, 1289, 0, 3, 0, 0, "stateRottingham", "1289-Rottingham", "1289-R~1.IMX"}, + {0, 1305, 0, 3, 0, 0, "stateDeck", "1305-Deck", "1305-D~1.IMX"}, + {0, 1310, 0, 3, 0, 0, "stateCombatMap", "1310-Combat Map", "1310-C~1.IMX"}, + {0, 1320, 0, 3, 0, 0, "stateShipCombat", "1320-Ship Combat", "1320-S~1.IMX"}, + {0, 1325, 0, 3, 0, 0, "stateSwordfight", "1325-Swordfight", "1325-S~1.IMX"}, + {0, 1327, 0, 3, 0, 0, "stateSwordRott", "1327-Sword Rott", "1327-S~1.IMX"}, + {0, 1330, 0, 3, 0, 0, "stateTownEdge", "1330-Town Edge", "1330-T~1.IMX"}, + {0, 1335, 0, 3, 0, 0, "stateSwordLose", "1335-Sword Lose", "1335-S~1.IMX"}, + {0, 1340, 0, 3, 0, 0, "stateSwordWin", "1340-Sword Win", "1340-S~1.IMX"}, + {0, 1345, 0, 3, 0, 0, "stateGetMap", "1345-Get Map", "1345-G~1.IMX"}, + {0, 1400, 0, 3, 0, 0, "stateWreckBeach", "1400-Wreck Beach", "1400-W~1.IMX"}, + {0, 1405, 0, 3, 0, 0, "stateBloodMap", "1405-Blood Map", "1405-B~1.IMX"}, + {0, 1410, 0, 3, 0, 0, "stateClearing", "1410-Clearing", "1410-C~1.IMX"}, + {0, 1415, 0, 3, 0, 0, "stateLighthouse", "1415-Lighthouse", "1415-L~1.IMX"}, + {0, 1420, 0, 3, 0, 0, "stateVillage", "1420-Village", "1420-V~1.IMX"}, + {0, 1423, 0, 3, 0, 0, "stateVolcano", "1423-Volcano", "1423-V~1.IMX"}, + {0, 1425, 0, 3, 0, 0, "stateAltar", "1425-Altar", "1425-A~1.IMX"}, + {0, 1430, 0, 3, 0, 0, "stateHotelOut", "1430-Hotel Out", "1430-H~1.IMX"}, + {0, 1435, 0, 3, 0, 0, "stateHotelBar", "1435-Hotel Bar", "1435-H~1.IMX"}, + {0, 1440, 0, 3, 0, 0, "stateHotelIn", "1440-Hotel In", "1440-H~1.IMX"}, + {0, 1445, 0, 3, 0, 0, "stateTarotLady", "1445-Tarot Lady", "1445-T~1.IMX"}, + {0, 1447, 0, 3, 0, 0, "stateGoodsoup", "1447-Goodsoup", "1447-G~1.IMX"}, + {0, 1448, 0, 3, 0, 0, "stateGuestRoom", "1448-Guest Room", "1448-G~1.IMX"}, + {0, 1450, 0, 3, 0, 0, "stateWindmill", "1450-Windmill", "1450-W~1.IMX"}, + {0, 1455, 0, 3, 0, 0, "stateCemetary", "1455-Cemetary", "1455-C~1.IMX"}, + {0, 1460, 0, 3, 0, 0, "stateCrypt", "1460-Crypt", "1460-C~1.IMX"}, + {0, 1463, 0, 3, 0, 0, "stateGraveDigger", "1463-Gravedigger", "1463-G~1.IMX"}, + {0, 1465, 0, 3, 0, 0, "stateMonkey1", "1465-Monkey1", "1465-M~1.IMX"}, + {0, 1475, 0, 3, 0, 0, "stateStanDark", "1475-Stan Dark", "1475-S~1.IMX"}, + {0, 1477, 0, 3, 0, 0, "stateStanLight", "1477-Stan", "1477-S~1.IMX"}, + {0, 1480, 0, 3, 0, 0, "stateEggBeach", "1480-Egg Beach", "1480-E~1.IMX"}, + {0, 1485, 0, 3, 0, 0, "stateSkullIsland", "1485-Skull Island", "1485-S~1.IMX"}, + {0, 1490, 0, 3, 0, 0, "stateSmugglersCave", "1490-Smugglers", "1490-S~1.IMX"}, + {0, 1500, 0, 3, 0, 0, "stateLeChuckTalk", "1500-Le Talk", "1500-L~1.IMX"}, + {0, 1505, 0, 3, 0, 0, "stateCarnival", "1505-Carnival", "1505-C~1.IMX"}, + {0, 1511, 0, 3, 0, 0, "stateHang", "1511-Hang", "1511-H~1.IMX"}, + {0, 1512, 0, 3, 0, 0, "stateRum", "1512-Rum", "1512-RUM.IMX"}, + {0, 1513, 0, 3, 0, 0, "stateTorture", "1513-Torture", "1513-T~1.IMX"}, + {0, 1514, 0, 3, 0, 0, "stateSnow", "1514-Snow", "1514-S~1.IMX"}, + {0, 1515, 0, 3, 0, 0, "stateCredits", "1515-Credits (end)", "1515-C~1.IMX"}, + {0, 1520, 0, 3, 0, 0, "stateCarnAmb", "1520-Carn Amb", "1520-C~1.IMX"}, + {-1, -1, 0, 0, 0, 0, "", "", ""} +}; + +const imuse_music_table _comiSeqMusicTable[] = { + {0, 2000, 0, 0, 0, 0, "SEQ_NULL", "", ""}, + {0, 2100, 0, 0, 0, 0, "seqINTRO", "", ""}, + {0, 2105, 0, 3, 0, 0, "seqInterlude1", "2105-Interlude1", "2105-I~1.IMX"}, + {0, 2110, 0, 8, 1, 0, "seqLastBoat", "", ""}, + {0, 2115, 0, 0, 0, 0, "seqSINK_SHIP", "", ""}, + {0, 2120, 0, 0, 0, 0, "seqCURSED_RING", "", ""}, + {0, 2200, 0, 3, 0, 0, "seqInterlude2", "2200-Interlude2", "2200-I~1.IMX"}, + {0, 2210, 0, 3, 0, 0, "seqKidnapped", "2210-Kidnapped", "2210-K~1.IMX"}, + {0, 2220, 0, 8, 1, 0, "seqSnakeVomits", "", ""}, + {0, 2222, 0, 8, 1, 0, "seqPopBalloon", "", ""}, + {0, 2225, 0, 3, 0, 0, "seqDropBalls", "2225-Drop Balls", "2225-D~1.IMX"}, + {0, 2232, 0, 4, 0, 0, "seqArriveBarber", "2232-Arrive Barber", "2232-A~1.IMX"}, + {0, 2233, 0, 3, 0, 0, "seqAtonal", "2233-Atonal", "2233-A~1.IMX"}, + {0, 2235, 0, 3, 0, 0, "seqShaveHead1", "2235-Shave Head", "2235-S~1.IMX"}, + {0, 2236, 0, 2, 2, 0, "seqShaveHead2", "2235-Shave Head", "2235-S~1.IMX"}, + {0, 2245, 0, 3, 0, 0, "seqCaberLose", "2245-Caber Lose", "2245-C~1.IMX"}, + {0, 2250, 0, 3, 0, 0, "seqCaberWin", "2250-Caber Win", "2250-C~1.IMX"}, + {0, 2255, 0, 3, 0, 0, "seqDuel1", "2255-Duel", "2255-D~1.IMX"}, + {0, 2256, 0, 2, 2, 0, "seqDuel2", "2255-Duel", "2255-D~1.IMX"}, + {0, 2257, 0, 2, 3, 0, "seqDuel3", "2255-Duel", "2255-D~1.IMX"}, + {0, 2260, 0, 3, 0, 0, "seqBlowUpTree1", "2260-Blow Up Tree", "2260-B~1.IMX"}, + {0, 2261, 0, 2, 2, 0, "seqBlowUpTree2", "2260-Blow Up Tree", "2260-B~1.IMX"}, + {0, 2275, 0, 3, 0, 0, "seqMonkeys", "2275-Monkeys", "2275-M~1.IMX"}, + {0, 2277, 0, 9, 1, 0, "seqAttack", "", ""}, + {0, 2285, 0, 3, 0, 0, "seqSharks", "2285-Sharks", "2285-S~1.IMX"}, + {0, 2287, 0, 3, 0, 0, "seqTowelWalk", "2287-Towel Walk", "2287-T~1.IMX"}, + {0, 2293, 0, 0, 0, 0, "seqNICE_BOOTS", "", ""}, + {0, 2295, 0, 0, 0, 0, "seqBIG_BONED", "", ""}, + {0, 2300, 0, 3, 0, 0, "seqToBlood", "2300-To Blood", "2300-T~1.IMX"}, + {0, 2301, 0, 3, 0, 0, "seqInterlude3", "2301-Interlude3", "2301-I~1.IMX"}, + {0, 2302, 0, 3, 0, 0, "seqRott1", "2302-Rott Attack", "2302-R~1.IMX"}, + {0, 2304, 0, 2, 2, 0, "seqRott2", "2302-Rott Attack", "2302-R~1.IMX"}, + {0, 2305, 0, 2,21, 0, "seqRott2b", "2302-Rott Attack", "2302-R~1.IMX"}, + {0, 2306, 0, 2, 3, 0, "seqRott3", "2302-Rott Attack", "2302-R~1.IMX"}, + {0, 2308, 0, 2, 4, 0, "seqRott4", "2302-Rott Attack", "2302-R~1.IMX"}, + {0, 2309, 0, 2, 5, 0, "seqRott5", "2302-Rott Attack", "2302-R~1.IMX"}, + {0, 2311, 0, 3, 0, 0, "seqVerse1", "2311-Song", "2311-S~1.IMX"}, + {0, 2312, 0, 2, 2, 0, "seqVerse2", "2311-Song", "2311-S~1.IMX"}, + {0, 2313, 0, 2, 3, 0, "seqVerse3", "2311-Song", "2311-S~1.IMX"}, + {0, 2314, 0, 2, 4, 0, "seqVerse4", "2311-Song", "2311-S~1.IMX"}, + {0, 2315, 0, 2, 5, 0, "seqVerse5", "2311-Song", "2311-S~1.IMX"}, + {0, 2316, 0, 2, 6, 0, "seqVerse6", "2311-Song", "2311-S~1.IMX"}, + {0, 2317, 0, 2, 7, 0, "seqVerse7", "2311-Song", "2311-S~1.IMX"}, + {0, 2318, 0, 2, 8, 0, "seqVerse8", "2311-Song", "2311-S~1.IMX"}, + {0, 2319, 0, 2, 9, 0, "seqSongEnd", "2311-Song", "2311-S~1.IMX"}, + {0, 2336, 0, 2, 0, 0, "seqRiposteLose", "2336-Riposte Lose", "2336-R~1.IMX"}, + {0, 2337, 0, 2, 0, 0, "seqRiposteWin", "2337-Riposte Win", "2337-R~1.IMX"}, + {0, 2338, 0, 2, 0, 0, "seqInsultLose", "2338-Insult Lose", "2338-I~1.IMX"}, + {0, 2339, 0, 2, 0, 0, "seqInsultWin", "2339-Insult Win", "2339-I~1.IMX"}, + {0, 2340, 0, 3, 0, 0, "seqSwordLose", "1335-Sword Lose", "1335-S~1.IMX"}, + {0, 2345, 0, 3, 0, 0, "seqSwordWin", "1340-Sword Win", "1340-S~1.IMX"}, + {0, 2347, 0, 3, 0, 0, "seqGetMap", "1345-Get Map", "1345-G~1.IMX"}, + {0, 2400, 0, 3, 0, 0, "seqInterlude4", "2400-Interlude4", "2400-I~1.IMX"}, + {0, 2405, 0, 0, 0, 0, "seqSHIPWRECK", "", ""}, + {0, 2408, 0, 3, 0, 0, "seqFakeCredits", "2408-Fake Credits", "2408-F~1.IMX"}, + {0, 2410, 0, 3, 0, 0, "seqPassOut", "2410-Pass Out", "2410-P~1.IMX"}, + {0, 2414, 0, 3, 0, 0, "seqGhostTalk", "2414-Ghost Talk", "2414-G~1.IMX"}, + {0, 2415, 0, 2, 1, 0, "seqGhostWedding", "2414-Ghost Talk", "2414-G~1.IMX"}, + {0, 2420, 0, 3, 0, 0, "seqEruption", "2420-Eruption", "2420-E~1.IMX"}, + {0, 2425, 0, 3, 0, 0, "seqSacrifice", "2425-Sacrifice", "2425-S~1.IMX"}, + {0, 2426, 0, 2, 1, 0, "seqSacrificeEnd", "2425-Sacrifice", "2425-S~1.IMX"}, + {0, 2430, 0, 3, 0, 0, "seqScareDigger", "2430-Scare Digger", "2430-S~1.IMX"}, + {0, 2445, 0, 3, 0, 0, "seqSkullArrive", "2445-Skull Arrive", "2445-S~1.IMX"}, + {0, 2450, 0, 3, 0, 0, "seqFloat", "2450-Cliff Fall", "2450-C~1.IMX"}, + {0, 2451, 0, 2, 1, 0, "seqFall", "2450-Cliff Fall", "2450-C~1.IMX"}, + {0, 2452, 0, 2, 2, 0, "seqUmbrella", "2450-Cliff Fall", "2450-C~1.IMX"}, + {0, 2460, 0, 3, 0, 0, "seqFight", "2460-Fight", "2460-F~1.IMX"}, + {0, 2465, 0, 0, 0, 0, "seqLAVE_RIDE", "", ""}, + {0, 2470, 0, 0, 0, 0, "seqMORE_SLAW", "", ""}, + {0, 2475, 0, 0, 0, 0, "seqLIFT_CURSE", "", ""}, + {0, 2500, 0, 3, 0, 0, "seqInterlude5", "2500-Interlude5", "2500-I~1.IMX"}, + {0, 2502, 0, 3, 0, 0, "seqExitSkycar", "2502-Exit Skycar", "2502-E~1.IMX"}, + {0, 2504, 0, 3, 0, 0, "seqGrow1", "2504-Grow", "2504-G~1.IMX"}, + {0, 2505, 0, 2, 1, 0, "seqGrow2", "2504-Grow", "2504-G~1.IMX"}, + {0, 2508, 0, 3, 0, 0, "seqInterlude6", "2508-Interlude6", "2508-I~1.IMX"}, + {0, 2515, 0, 0, 0, 0, "seqFINALE", "", ""}, + {0, 2520, 0, 3, 0, 0, "seqOut", "2520-Out", "2520-OUT.IMX"}, + {0, 2530, 0, 3, 0, 0, "seqZap1a", "2530-Zap1", "2530-Z~1.IMX"}, + {0, 2531, 0, 2, 1, 0, "seqZap1b", "2530-Zap1", "2530-Z~1.IMX"}, + {0, 2532, 0, 2, 2, 0, "seqZap1c", "2530-Zap1", "2530-Z~1.IMX"}, + {0, 2540, 0, 3, 0, 0, "seqZap2a", "2540-Zap2", "2540-Z~1.IMX"}, + {0, 2541, 0, 2, 1, 0, "seqZap2b", "2540-Zap2", "2540-Z~1.IMX"}, + {0, 2542, 0, 2, 2, 0, "seqZap2c", "2540-Zap2", "2540-Z~1.IMX"}, + {0, 2550, 0, 3, 0, 0, "seqZap3a", "2550-Zap3", "2550-Z~1.IMX"}, + {0, 2551, 0, 2, 1, 0, "seqZap3b", "2550-Zap3", "2550-Z~1.IMX"}, + {0, 2552, 0, 2, 2, 0, "seqZap3c", "2550-Zap3", "2550-Z~1.IMX"}, + {0, 2560, 0, 3, 0, 0, "seqZap4a", "2560-Zap4", "2560-Z~1.IMX"}, + {0, 2561, 0, 2, 1, 0, "seqZap4b", "2560-Zap4", "2560-Z~1.IMX"}, + {0, 2562, 0, 2, 2, 0, "seqZap4c", "2560-Zap4", "2560-Z~1.IMX"}, + {-1, -1, 0, 0, 0, 0, "", "", ""} +}; + +const imuse_ft_music_table _ftStateMusicTable[] = { + {0, "", 0, 0, "STATE_NULL" }, + {1, "", 4, 127, "stateKstandOutside" }, + {2, "kinside", 2, 127, "stateKstandInside" }, + {3, "moshop", 3, 64, "stateMoesInside" }, + {4, "melcut", 2, 127, "stateMoesOutside" }, + {5, "mellover", 2, 127, "stateMellonAbove" }, + {6, "radloop", 3, 28, "stateTrailerOutside" }, + {7, "radloop", 3, 58, "stateTrailerInside" }, + {8, "radloop", 3, 127, "stateTodShop" }, + {9, "junkgate", 2, 127, "stateJunkGate" }, + {10, "junkover", 3, 127, "stateJunkAbove" }, + {11, "gastower", 2, 127, "stateGasTower" }, + {12, "", 4, 0, "stateTowerAlarm" }, + {13, "melcut", 2, 127, "stateCopsOnGround" }, + {14, "melcut", 2, 127, "stateCopsAround" }, + {15, "melcut", 2, 127, "stateMoesRuins" }, + {16, "melcut", 2, 127, "stateKstandNight" }, + {17, "trukblu2", 2, 127, "stateTruckerTalk" }, + {18, "stretch", 2, 127, "stateMumblyPeg" }, + {19, "kstand", 2, 100, "stateRanchOutside" }, + {20, "kinside", 2, 127, "stateRanchInside" }, + {21, "desert", 2, 127, "stateWreckedTruck" }, + {22, "opening", 2, 100, "stateGorgeVista" }, + {23, "caveopen", 2, 127, "stateCaveOpen" }, + {24, "cavecut1", 2, 127, "stateCaveOuter" }, + {25, "cavecut1", 1, 127, "stateCaveMiddle" }, + {26, "cave", 2, 127, "stateCaveInner" }, + {27, "corville", 2, 127, "stateCorvilleFront" }, + {28, "mines", 2, 127, "stateMineField" }, + {29, "bunyman3", 2, 127, "stateBunnyStore" }, + {30, "stretch", 2, 127, "stateStretchBen" }, + {31, "saveme", 2, 127, "stateBenPleas" }, + {32, "", 4, 0, "stateBenConvinces" }, + {33, "derby", 3, 127, "stateDemoDerby" }, + {34, "fire", 3, 127, "stateLightMyFire" }, + {35, "derby", 3, 127, "stateDerbyChase" }, + {36, "carparts", 2, 127, "stateVultureCarParts"}, + {37, "cavecut1", 2, 127, "stateVulturesInside" }, + {38, "mines", 2, 127, "stateFactoryRear" }, + {39, "croffice", 2, 127, "stateCorleyOffice" }, + {40, "melcut", 2, 127, "stateCorleyHall" }, + {41, "", 4, 0, "stateProjRoom" }, + {42, "", 4, 0, "stateMMRoom" }, + {43, "bumper", 2, 127, "stateBenOnBumper" }, + {44, "benump", 2, 127, "stateBenOnBack" }, + {45, "plane", 2, 127, "stateInCargoPlane" }, + {46, "saveme", 2, 127, "statePlaneControls" }, + {47, "", 4, 0, "stateCliffHanger1" }, + {48, "", 4, 0, "stateCliffHanger2" }, + {-1, "", 0, 0, "" } +}; + +const imuse_ft_music_table _ftSeqMusicTable[] = { + {0, "", 2, 127, "SEQ_NULL" }, + {1, "opening", 2, 127, "seqLogo" }, + {2, "barbeat", 2, 127, "seqOpenFlick" }, + {3, "barwarn", 2, 127, "seqBartender" }, + {4, "benwakes", 2, 127, "seqBenWakes" }, + {5, "barwarn", 2, 127, "seqPhotoScram" }, + {6, "swatben", 2, 127, "seqClimbChain" }, + {7, "dogattak", 2, 127, "seqDogChase" }, + {8, "", 0, 0, "seqDogSquish" }, + {9, "", 0, 0, "seqDogHoist" }, + {10, "cops2", 2, 127, "seqCopsArrive" }, + {11, "cops2", 2, 127, "seqCopsLand" }, + {12, "cops2", 2, 127, "seqCopsLeave" }, + {13, "", 0, 0, "seqCopterFlyby" }, + {14, "bunymrch", 2, 127, "seqCopterCrash" }, + {15, "", 0, 0, "seqMoGetsParts" }, + {16, "", 0, 0, "seqMoFixesBike" }, + {17, "", 0, 0, "seqFirstGoodbye" }, + {18, "trucker", 2, 127, "seqCopRoadblock" }, + {19, "cops2", 2, 127, "seqDivertCops" }, + {20, "barwarn", 2, 127, "seqMurder" }, + {21, "corldie", 2, 127, "seqCorleyDies" }, + {22, "barwarn", 2, 127, "seqTooLateAtMoes" }, + {23, "picture", 2, 127, "seqPicture" }, + {24, "ripintro", 2, 127, "seqNewsReel" }, + {25, "trucker", 2, 127, "seqCopsInspect" }, + {26, "ripdead", 2, 127, "seqHijack" }, + {27, "nesranch", 2, 127, "seqNestolusAtRanch" }, + {28, "scolding", 2, 127, "seqRipLimo" }, + {29, "desert", 2, 127, "seqGorgeTurn" }, + {30, "cavecut1", 2, 127, "seqStealRamp" }, + {31, "vaceamb", 2, 80, "seqCavefishTalk" }, + {32, "castle", 2, 127, "seqArriveCorville" }, + {33, "bunymrch", 2, 105, "seqSingleBunny" }, + {34, "valkyrs", 2, 127, "seqBunnyArmy" }, + {35, "melcut", 2, 127, "seqArriveAtMines" }, + {36, "veltures", 2, 127, "seqArriveAtVultures" }, + {37, "sorry", 2, 127, "seqMakePlan" }, + {38, "makeplan", 2, 127, "seqShowPlan" }, + {39, "castle", 2, 127, "seqDerbyStart" }, + {40, "fire", 3, 127, "seqLightBales" }, + {41, "saveme", 3, 127, "seqNestolusBBQ" }, + {42, "cops2", 2, 127, "seqCallSecurity" }, + {43, "sorry", 2, 127, "seqFilmFail" }, + {44, "sorry", 2, 127, "seqFilmBurn" }, + {45, "caveamb", 2, 127, "seqRipSpeech" }, + {46, "expose", 2, 127, "seqExposeRip" }, + {47, "ripscram", 2, 127, "seqRipEscape" }, + {48, "", 0, 0, "seqRareMoment" }, + {49, "valkyrs", 2, 127, "seqFanBunnies" }, + {50, "ripdead", 2, 127, "seqRipDead" }, + {51, "funeral", 2, 127, "seqFuneral" }, + {52, "bornbad", 2, 127, "seqCredits" }, + {-1, "", 0, 0, "" } +}; + +} // End of namespace Scumm diff --git a/scumm/resource.cpp b/scumm/resource.cpp index c715bbec24..1c178807ff 100644 --- a/scumm/resource.cpp +++ b/scumm/resource.cpp @@ -23,10 +23,9 @@ #include "stdafx.h" #include "common/map.h" #include "common/str.h" -#include "scumm/bundle.h" #include "scumm/dialogs.h" #include "scumm/imuse.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/object.h" #include "scumm/resource.h" #include "scumm/scumm.h" @@ -228,8 +227,7 @@ void ScummEngine::askForDisk(const char *filename, int disknum) { if (_version == 8) { char result; - _imuseDigital->_bundle->closeVoiceFile(); - _imuseDigital->_bundle->closeMusicFile(); + _imuseDigital->closeBundleFiles(); #ifdef MACOSX sprintf(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nHit OK to retry, Cancel to exit", filename, disknum); diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index aa66eac9a4..50162a441c 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -26,7 +26,7 @@ #include "scumm/actor.h" #include "scumm/charset.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/imuse.h" #include "scumm/object.h" #include "scumm/resource.h" @@ -125,8 +125,6 @@ bool ScummEngine::loadState(int slot, bool compat, SaveFileManager *mgr) { memcpy(_saveLoadName, hdr.name, sizeof(hdr.name)); _sound->stopAllSounds(); - if (_imuseDigital) - _imuseDigital->stopBundleMusic(); _sound->stopCD(); _sound->pauseSounds(true); diff --git a/scumm/script_v6.cpp b/scumm/script_v6.cpp index df33772509..e9139c881f 100644 --- a/scumm/script_v6.cpp +++ b/scumm/script_v6.cpp @@ -28,6 +28,7 @@ #include "scumm/actor.h" #include "scumm/charset.h" #include "scumm/imuse.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/intern.h" #include "scumm/object.h" #include "scumm/resource.h" @@ -936,7 +937,7 @@ void ScummEngine_v6::o6_startSound() { pop(); // offset which seems to always be zero if (_features & GF_DIGI_IMUSE) - _sound->playSound(pop()); + _imuseDigital->startSfx(pop()); else _sound->addSoundToQueue(pop()); } @@ -947,7 +948,7 @@ void ScummEngine_v6::o6_stopSound() { void ScummEngine_v6::o6_startMusic() { if (_features & GF_DIGI_IMUSE) - _sound->playSound(pop()); + error("o6_startMusic() It shouldn't be called here for imuse digital"); else _sound->addSoundToQueue(pop()); } diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp index 7ae55bac74..61fec48cbb 100644 --- a/scumm/script_v8.cpp +++ b/scumm/script_v8.cpp @@ -24,7 +24,7 @@ #include "scumm/actor.h" #include "scumm/akos.h" #include "scumm/charset.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/intern.h" #include "scumm/object.h" #include "scumm/resource.h" @@ -1444,14 +1444,9 @@ void ScummEngine_v8::o8_kernelGetFunctions() { break; } case 0xDA: // lipSyncWidth + push(_imuseDigital->getCurVoiceLipSyncWidth()); case 0xDB: // lipSyncHeight - { - // TODO - get lip sync data for the currently active voice - // HACK - return random values for now, to make things look half decent - int val = _rnd.getRandomNumber(255); -// warning("o8_kernelGetFunctions: lipSync(case 0x%x, len %d, val %d)", args[0], len, val); - push(val); - } + push(_imuseDigital->getCurVoiceLipSyncHeight()); break; case 0xDC: // actorTalkAnimation { @@ -1482,18 +1477,12 @@ void ScummEngine_v8::o8_kernelGetFunctions() { } break; case 0xE1: // imGetMusicPosition - warning("o8_kernelGetFunctions: imGetMusicPosition(stub)"); - // FIXME - get this stuff to be properly implemented - push(_imuseDigital->_bundleSongPosInMs); + push(_imuseDigital->getCurMusicPosInMs()); break; case 0xE2: // musicLipSyncWidth + push(_imuseDigital->getCurMusicLipSyncWidth()); case 0xE3: // musicLipSyncHeight - { - // TODO - get lip sync data for the currently active music - int val = _rnd.getRandomNumber(255); -// warning("o8_kernelGetFunctions: musicLipSync(case 0x%x, len %d, val %d)", args[0], len, val); - push(val); - } + push(_imuseDigital->getCurMusicLipSyncHeight()); break; default: error("o8_kernelGetFunctions: default case 0x%x (len = %d)", args[0], len); diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index 554e72e428..a7a057c0d5 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -40,7 +40,7 @@ #include "scumm/costume.h" #include "scumm/debugger.h" #include "scumm/dialogs.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/imuse.h" #include "scumm/intern.h" #include "scumm/object.h" diff --git a/scumm/smush/insane.cpp b/scumm/smush/insane.cpp index ee84c79b94..e92b0b2b2a 100644 --- a/scumm/smush/insane.cpp +++ b/scumm/smush/insane.cpp @@ -32,7 +32,7 @@ #include "scumm/sound.h" #include "scumm/resource.h" #include "scumm/imuse.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/smush/smush_player.h" #include "scumm/smush/chunk_type.h" @@ -5914,30 +5914,16 @@ bool Insane::smlayer_isSoundRunning(int32 sound) { } bool Insane::smlayer_startSound1(int32 sound) { - // FIXME: original startSound parameters: - // startSound(id, 40, 1); - // second param is priority in imuse, - // third param set sound to group volume in imuse - // (0 - master, 1-sfx, 2-voice, 3 - music, - // 4 - background music) - // there are no equivalents in scummvm if (smlayer_loadSound(sound, 0, 2)) { - _scumm->_sound->playSound(readArray(_numberArray, sound)); + _scumm->_imuseDigital->startSfx(readArray(_numberArray, sound)); return true; } else return false; } bool Insane::smlayer_startSound2(int32 sound) { - // FIXME: original startSound parameters: - // startSound(id, 126, 2); - // second param is priority in imuse, - // third param set sound to group volume in imuse - // (0 - master, 1-sfx, 2-voice, 3 - music, - // 4 - background music) - // there are no equivalents in scummvm if (smlayer_loadSound(sound, 0, 2)) { - _scumm->_sound->playSound(readArray(_numberArray, sound)); + _scumm->_imuseDigital->startSfx(readArray(_numberArray, sound)); return true; } else return false; diff --git a/scumm/smush/smush_player.cpp b/scumm/smush/smush_player.cpp index 0d6aa66a7c..d3e6867fdf 100644 --- a/scumm/smush/smush_player.cpp +++ b/scumm/smush/smush_player.cpp @@ -29,7 +29,7 @@ #include "common/timer.h" #include "scumm/bomp.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/imuse.h" #include "scumm/scumm.h" #include "scumm/sound.h" diff --git a/scumm/sound.cpp b/scumm/sound.cpp index ade7faf0ba..91f007e684 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -23,7 +23,7 @@ #include "stdafx.h" #include "scumm/actor.h" #include "scumm/imuse.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/scumm.h" #include "scumm/sound.h" @@ -126,11 +126,6 @@ void Sound::playSound(int soundID) { return; } - if (_scumm->_features & GF_DIGI_IMUSE) { - _scumm->_musicEngine->startSound(soundID); - return; - } - // Support for SFX in Monkey Island 1, Mac version // This is rather hackish right now, but works OK. SFX are not sounding // 100% correct, though, not sure right now what is causing this. @@ -815,7 +810,6 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle, AudioStream *input; - if (file_size > 0) { if (_vorbis_mode) { #ifdef USE_VORBIS @@ -831,7 +825,8 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle, } if (_scumm->_imuseDigital) { - _scumm->_imuseDigital->startSound(kTalkSoundID, 0, input); + _scumm->_imuseDigital->stopSound(kTalkSoundID); + _scumm->_imuseDigital->startVoice(kTalkSoundID, input); } else { _scumm->_mixer->playInputStream(handle, input, false, 255, 0, id); } diff --git a/scumm/string.cpp b/scumm/string.cpp index 0940a85527..be1c9128f3 100644 --- a/scumm/string.cpp +++ b/scumm/string.cpp @@ -28,7 +28,7 @@ #include "scumm/actor.h" #include "scumm/charset.h" #include "scumm/dialogs.h" -#include "scumm/imuse_digi.h" +#include "scumm/imuse_digi/dimuse.h" #include "scumm/verbs.h" #include "scumm/sound.h" @@ -921,7 +921,10 @@ const byte *ScummEngine::translateTextAndPlaySpeech(const byte *ptr) { pointer[j] = 0; // Play speech - _imuseDigital->playBundleSound(pointer); + if (!(_features & GF_DEMO) && (_gameId == GID_CMI)) // CMI demo does not have .IMX for voice + strcat(pointer, ".IMX"); + _imuseDigital->stopSound(kTalkSoundID); + _imuseDigital->startVoice(kTalkSoundID, pointer); ptr = _transText; } -- cgit v1.2.3