diff options
-rw-r--r-- | Makefile.common | 2 | ||||
-rw-r--r-- | bundle.cpp | 535 | ||||
-rw-r--r-- | bundle.h | 71 | ||||
-rw-r--r-- | morphos/Makefile | 2 | ||||
-rw-r--r-- | scumm.h | 3 | ||||
-rw-r--r-- | scummvm.cpp | 2 | ||||
-rw-r--r-- | scummvm.dsp | 8 | ||||
-rw-r--r-- | sound.cpp | 407 | ||||
-rw-r--r-- | sound/mixer.h | 5 |
9 files changed, 658 insertions, 377 deletions
diff --git a/Makefile.common b/Makefile.common index 80161337d7..0fce38f34b 100644 --- a/Makefile.common +++ b/Makefile.common @@ -16,7 +16,7 @@ OBJS += util.o newgui.o gui/widget.o gui/dialog.o \ v3/resource_v3.o v4/resource_v4.o scaler.o main.o \ simon/midi.o simon/simon.o simon/simonsys.o simon/simonvga.o \ simon/simondebug.o simon/simonres.o simon/simonitems.o simon/simonverb.o \ - sound/mididrv.o config-file.o + sound/mididrv.o config-file.o bundle.o DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \ debugrl.h whatsnew.txt readme.txt copying.txt \ diff --git a/bundle.cpp b/bundle.cpp new file mode 100644 index 0000000000..ca695c9c2b --- /dev/null +++ b/bundle.cpp @@ -0,0 +1,535 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002 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.h" +#include "scummsys.h" +#include "bundle.h" + +Bundle::Bundle(Scumm * parent) { + _voiceFile = NULL; + _musicFile = NULL; + _scumm = parent; +} + +Bundle::~Bundle() { + if (_voiceFile != NULL) + fclose (_voiceFile); + + if (_musicFile != NULL) + fclose (_musicFile); +} + +int32 Bundle::openVoiceFile(char * filename) { + int32 tag, offset; + + if (_voiceFile != NULL) { + return false; + } + + _voiceFile = fopen(filename, "rb"); + if (_voiceFile == NULL) { + printf("Bundle: Can't open voice bundle file: %s\n", filename); + return false; + } + + tag = _scumm->fileReadDwordBE(_voiceFile); + offset = _scumm->fileReadDwordBE(_voiceFile); + _numVoiceFiles = _scumm->fileReadDwordBE(_voiceFile); + + _bundleVoiceTable = (BundleAudioTable *) malloc(_numVoiceFiles * sizeof(BundleAudioTable)); + + _scumm->fileSeek(_voiceFile, 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 = _scumm->fileReadByte(_voiceFile)) != 0) + name[z++] = c; + name[z++] = '.'; + for (z2 = 0; z2 < 4; z2++) + if ((c = _scumm->fileReadByte(_voiceFile)) != 0) + name[z++] = c; + name[z] = '\0'; + strcpy(_bundleVoiceTable[i].filename, name); + _bundleVoiceTable[i].offset = _scumm->fileReadDwordBE(_voiceFile); + _bundleVoiceTable[i].size = _scumm->fileReadDwordBE(_voiceFile); + } + + return true; +} + +int32 Bundle::openMusicFile(char * filename) { + int32 tag, offset; + + if (_musicFile != NULL) { + return false; + } + + _musicFile = fopen(filename, "rb"); + if (_musicFile == NULL) { + printf("Bundle: Can't open music bundle file: %s\n", filename); + return false; + } + + tag = _scumm->fileReadDwordBE(_musicFile); + offset = _scumm->fileReadDwordBE(_musicFile); + _numMusicFiles = _scumm->fileReadDwordBE(_musicFile); + + _bundleMusicTable = (BundleAudioTable *) malloc(_numMusicFiles * sizeof(BundleAudioTable)); + + _scumm->fileSeek(_musicFile, 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 = _scumm->fileReadByte(_musicFile)) != 0) + name[z++] = c; + name[z++] = '.'; + for (z2 = 0;z2 < 4; z2++) + if ((c = _scumm->fileReadByte(_musicFile)) != 0) + name[z++] = c; + name[z] = '\0'; + strcpy(_bundleVoiceTable[i].filename, name); + _bundleVoiceTable[i].offset = _scumm->fileReadDwordBE(_musicFile); + _bundleVoiceTable[i].size = _scumm->fileReadDwordBE(_musicFile); + } + + return true; +} + +int32 Bundle::decompressVoiceSampleByIndex(int32 index, byte * comp_final) { + int32 i, tag, num, final_size, output_size; + byte * comp_input, * comp_output; + + if (_voiceFile == NULL) { + printf("Bundle: voice file is not open !\n"); + return 0; + } + + _scumm->fileSeek(_voiceFile, _bundleVoiceTable[index].offset, SEEK_SET); + tag = _scumm->fileReadDwordBE(_voiceFile); + num = _scumm->fileReadDwordBE(_voiceFile); + _scumm->fileReadDwordBE(_voiceFile); + _scumm->fileReadDwordBE(_voiceFile); + + if (tag != MKID_BE('COMP')) { + warning("Bundle: Compressed sound %d invalid (%c%c%c%c)", index, tag>>24, tag>>16, tag>>8, tag); + return 0; + } + + for (i = 0; i < num; i++) { + _compVoiceTable[i].offset = _scumm->fileReadDwordBE(_voiceFile); + _compVoiceTable[i].size = _scumm->fileReadDwordBE(_voiceFile); + _compVoiceTable[i].codec = _scumm->fileReadDwordBE(_voiceFile); + _scumm->fileReadDwordBE(_voiceFile); + } + + final_size = 0; + + comp_output = (byte *)malloc(10000); + for (i = 0; i < num; i++) { + comp_input = (byte *)malloc(_compVoiceTable[i].size); + + _scumm->fileSeek(_voiceFile, _bundleVoiceTable[index].offset + _compVoiceTable[i].offset, SEEK_SET); + _scumm->fileRead(_voiceFile, comp_input, _compVoiceTable[i].size); + + output_size = decompressCodec(_compVoiceTable[i].codec, comp_input, comp_output, _compVoiceTable[i].size); + memcpy((byte *)&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) { + int32 i, tag, num, final_size; + byte * comp_input; + + if (_musicFile == NULL) { + printf("Bundle: music file is not open !\n"); + return 0; + } + + _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset, SEEK_SET); + tag = _scumm->fileReadDwordBE(_musicFile); + num = _scumm->fileReadDwordBE(_musicFile); + _scumm->fileReadDwordBE(_musicFile); + _scumm->fileReadDwordBE(_musicFile); + + if (tag != MKID_BE('COMP')) { + warning("Bundle: Compressed sound %d invalid (%c%c%c%c)", index, tag>>24, tag>>16, tag>>8, tag); + return 0; + } + + for (i = 0; i < num; i++) { + _compMusicTable[i].offset = _scumm->fileReadDwordBE(_musicFile); + _compMusicTable[i].size = _scumm->fileReadDwordBE(_musicFile); + _compMusicTable[i].codec = _scumm->fileReadDwordBE(_musicFile); + _scumm->fileReadDwordBE(_musicFile); + } + + comp_input = (byte *)malloc(_compMusicTable[i].size); + + _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset + _compMusicTable[i].offset, SEEK_SET); + _scumm->fileRead(_musicFile, comp_input, _compMusicTable[i].size); + final_size = decompressCodec(_compMusicTable[i].codec, comp_input, comp_final, _compMusicTable[i].size); + + free(comp_input); + + return final_size; +} + + +int32 Bundle::decompressVoiceSampleByName(char * name, byte * comp_final) { + int32 final_size = 0, i; + + if (_voiceFile == NULL) { + printf("Bundle: voice file is not open !\n"); + return 0; + } + + for (i = 0; i < _numVoiceFiles; i++) { + if (!scumm_stricmp(name, _bundleVoiceTable[i].filename)) { + final_size = decompressVoiceSampleByIndex(i, comp_final); + return final_size; + } + } + return final_size; +} + +int32 Bundle::decompressMusicSampleByName(char * name, int32 number, byte * comp_final) { + int32 final_size = 0, i; + + if (_voiceFile == NULL) { + printf("Bundle: voice file is not open !\n"); + 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; + } + } + return final_size; +} + +int32 Bundle::getNumberOfMusicSamplesByIndex(int32 index) +{ + if (_musicFile == NULL) { + printf("Bundle: music file is not open !\n"); + return 0; + } + + _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset, SEEK_SET); + _scumm->fileReadDwordBE(_musicFile); + return _scumm->fileReadDwordBE(_musicFile); +} + +int32 Bundle::getNumberOfMusicSamplesByName(char * name) { + int32 number = 0, i; + + if (_musicFile == NULL) { + printf("Bundle: music file is not open !\n"); + return 0; + } + + for (i = 0; i < _numMusicFiles; i++) { + if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) { + number = getNumberOfMusicSamplesByIndex (i); + return number; + } + } + return number; +} + +#define NextBit bit = mask & 1; mask >>= 1; if (!--bitsleft) {mask = READ_LE_UINT16(srcptr); srcptr += 2; bitsleft=16;} + +int32 Bundle::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 = input_size; + int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z; + byte * src, * t_table, * p; + byte t_tmp1, t_tmp2; + + switch(codec) { + case 0: + memcpy(comp_input, comp_output, output_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); + + // FIXME: not implemented yet + memset (comp_output, 0, output_size); + break; + + case 5: + output_size = compDecode(comp_input, comp_output); + + // FIXME: not implemented yet + memset (comp_output, 0, output_size); + break; + + case 6: + output_size = compDecode(comp_input, comp_output); + + // FIXME: not implemented yet + memset (comp_output, 0, output_size); + 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 & 0xf0) >> 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 & 0xf0) >> 4); + } + s += 12; + k++; + c += 12; + } while (k <= length); + } + 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)) >> 4; + *(src) = 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 & 0xf0) >> 4; + *(src + r - 1) = ((t_tmp1 & 0x0f) << 4) | ((t_tmp2 & 0xf0) >> 4); + } + s += 12; + k++; + c += 12; + } 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) = *(output_size + t_table - 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 & 0xf0) >> 4); + } else { + r = c / 8; + t_tmp1 = *(t_table + k); + t_tmp2 = *(t_table + j); + *(src + r + 2) = (t_tmp1 & 0xf0) >> 4; + *(src + r + 1) = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f); + } + s += 12; + k++; + c += 12; + } while (k < t); + } + free (t_table); + break; + + default: + printf("Bundle: Unknown codec %d!\n", codec); + output_size = 0; + break; + } + + return output_size; +} + diff --git a/bundle.h b/bundle.h new file mode 100644 index 0000000000..0a094b1021 --- /dev/null +++ b/bundle.h @@ -0,0 +1,71 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002 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 "scummsys.h" + +struct CompTable { + int32 offset; + int32 size; + int32 codec; +}; + +struct BundleAudioTable { + char filename[13]; + int32 size; + int32 offset; +}; + +class Scumm; + +class Bundle { +protected: + +private: + int32 compDecode(byte * src, byte * dst); + int32 decompressCodec(int32 codec, byte * comp_input, byte * comp_output, int32 size); + CompTable _compVoiceTable[50]; + CompTable _compMusicTable[2500]; + FILE * _voiceFile; + FILE * _musicFile; + BundleAudioTable * _bundleVoiceTable; + BundleAudioTable * _bundleMusicTable; + int32 _numVoiceFiles; + int32 _numMusicFiles; + Scumm * _scumm; + +public: + Bundle(Scumm * parent); + ~Bundle(); + + int32 openVoiceFile(char * filename); + int32 openMusicFile(char * filename); + int32 decompressVoiceSampleByName(char * name, byte * comp_final); + int32 decompressVoiceSampleByIndex(int32 index, byte * comp_final); + int32 decompressMusicSampleByName(char * name, int32 number, byte * comp_final); + int32 decompressMusicSampleByIndex(int32 index, int32 number, byte * comp_final); + int32 getNumberOfMusicSamplesByIndex(int32 index); + int32 getNumberOfMusicSamplesByName(char * name); +}; + +#endif + diff --git a/morphos/Makefile b/morphos/Makefile index 367de01f2d..82e5fa55a4 100644 --- a/morphos/Makefile +++ b/morphos/Makefile @@ -21,7 +21,7 @@ OBJS = actor.o akos.o boxes.o config-file.o costume.o gfx.o object.o resource.o morphos.o morphos_sound.o morphos_start.o script_v1.o script_v2.o debug.o gui.o \ imuse.o fmopl.o mixer.o mididrv.o debugrl.o vars.o insane.o \ gameDetector.o init.o resource_v3.o resource_v4.o util.o main.o \ - $(GUIOBJS) $(SIMONOBJS) + bundle.o $(GUIOBJS) $(SIMONOBJS) DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \ windows.cpp debugrl.h whatsnew.txt readme.txt copying.txt \ @@ -26,6 +26,7 @@ #include "scummsys.h" #include "system.h" #include "sound/mixer.h" +#include "bundle.h" #define SCUMMVM_VERSION "0.2.2 CVS" #define SCUMMVM_CVS "2002-07-16" @@ -337,6 +338,7 @@ public: VerbSlot *_verbs; ObjectData *_objs; ScummDebugger *_debugger; + Bundle * _bundle; struct { byte mode[rtNumTypes]; @@ -765,7 +767,6 @@ public: MP3OffsetTable *offset_table; // SO3 MP3 compressed audio int num_sound_effects; // SO3 MP3 compressed audio - BundleAudioTable *bundle_table; // DIG/CMI bundles void pauseSounds(bool pause); bool isSfxFinished(); void playBundleSound(char *sound); diff --git a/scummvm.cpp b/scummvm.cpp index d1c60cc260..b82b9a173e 100644 --- a/scummvm.cpp +++ b/scummvm.cpp @@ -84,6 +84,7 @@ void Scumm::scummInit() setShake(0); setupCursor(); + _bundle = new Bundle(this); /* Allocate and initilise actors */ _actors = new Actor[MAX_ACTORS]; for (i = 1, a = getFirstActor(); ++a, i < NUM_ACTORS; i++) { @@ -1582,6 +1583,7 @@ void Scumm::go() { launch(); setupGUIColors(); mainRun(); + delete _bundle; } diff --git a/scummvm.dsp b/scummvm.dsp index b155e4f600..891380824e 100644 --- a/scummvm.dsp +++ b/scummvm.dsp @@ -297,6 +297,10 @@ SOURCE=.\boxes.cpp # End Source File
# Begin Source File
+SOURCE=.\bundle.cpp
+# End Source File
+# Begin Source File
+
SOURCE=".\config-file.cpp"
# End Source File
# Begin Source File
@@ -557,6 +561,10 @@ SOURCE=.\boxes.h # End Source File
# Begin Source File
+SOURCE=.\bundle.h
+# End Source File
+# Begin Source File
+
SOURCE=.\cdmusic.h
# End Source File
# Begin Source File
@@ -710,46 +710,6 @@ void *Scumm::openSfxFile() char buf[256]; FILE *file = NULL; - if (_gameId == GID_DIG) { - int tag, offset, num_files; - - sprintf(buf, "%s%svoice.bun", _gameDataPath, _exe_name); - file = fopen(buf, "rb"); - if (!file) { - warning("Unable to open DIG voice bundle: %s", buf); - return NULL; - } - - tag = fileReadDwordBE(file); - offset = fileReadDwordBE(file); - num_files = fileReadDwordBE(file); - - bundle_table = (BundleAudioTable *) malloc(num_files * sizeof(BundleAudioTable)); - num_sound_effects = num_files; - fileSeek(file, offset, SEEK_SET); - - for (int i=0; i < num_files; i++) { - char filename[13], c; - int z = 0; - int z2; - - /* Construct filename */ - for (z2=0;z2<8; z2++) - if ((c = fileReadByte(file)) != 0) - filename[z++] = c; - filename[z++] = '.'; - for (z2=0;z2<4;z2++) - if ((c = fileReadByte(file)) != 0) - filename[z++] = c; - filename[z] = '\0'; - strcpy(bundle_table[i].filename, filename); - bundle_table[i].offset = fileReadDwordBE(file); - bundle_table[i].size = fileReadDwordBE(file); - } - - return file; - } - /* Try opening the file <_exe_name>.sou first, eg tentacle.sou. * That way, you can keep .sou files for multiple games in the * same directory */ @@ -817,353 +777,62 @@ bool Scumm::isSfxFinished() return !_mixer->has_active_channel(); } -#define NextBit bit = mask&1; mask>>=1; if (!--bitsleft) {mask = READ_LE_UINT16(srcptr); srcptr+=2; bitsleft=16;} -int CompDecode(unsigned char *src, unsigned char *dst) +void Scumm::playBundleSound(char *sound) { - unsigned char *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; /* End of buffer */ - } - result = dstptr+data; - while (size--) - *dstptr++=*result++; - } - } -} -#undef NextBit - -typedef struct {int offset, size, codec;} COMP_table; -void Scumm::decompressBundleSound(int index) { - int i, z; - COMP_table table[50]; - unsigned char *CompInput, *CompOutput, *CompFinal, *Final; - int outputSize, finalSize; - int32 offset1, offset2, offset3, length, k, c, s, j, r, t; - byte * src, * t_table; - byte t_tmp1, t_tmp2; - - fileSeek(_sfxFile, bundle_table[index].offset, SEEK_SET); - - int tag = fileReadDwordBE(_sfxFile); - int num = fileReadDwordBE(_sfxFile); - fileReadDwordBE(_sfxFile); fileReadDwordBE(_sfxFile); - + char buf[256]; + byte * ptr; - // DO -NOT- change these MKID_BE calls to MKID! If you have - // to do so, then your ScummSys.H file is detecting the - // wrong endian. - Ender - if (tag != MKID_BE('COMP')) { - warning("Compressed sound %d invalid (%c%c%c%c)", index, tag>>24, tag>>16, tag>>8, tag); + sprintf(buf, "%s%svoice.bun", _gameDataPath, _exe_name); + _bundle->openVoiceFile((char*)&buf); + ptr = (byte *)malloc(1000000); + if (_bundle->decompressVoiceSampleByName(sound, ptr) == 0) { + delete ptr; return; } - /* Read compression table */ - for (i=0; i<num; i++) { - table[i].offset = fileReadDwordBE(_sfxFile); - table[i].size = fileReadDwordBE(_sfxFile); - table[i].codec = fileReadDwordBE(_sfxFile); - fileReadDwordBE(_sfxFile); - } - - CompFinal = (unsigned char *)malloc(1000000); - - finalSize = 0; - - /* Decompress data */ - for (i=0; i<num; i++) { - unsigned char *p; - fileSeek(_sfxFile, bundle_table[index].offset + table[i].offset, SEEK_SET); - - CompInput = (unsigned char *)malloc(table[i].size); - CompOutput = (unsigned char *)malloc(10000); - - fileRead((FILE *)_sfxFile, CompInput, table[i].size); - - switch(table[i].codec) { - case 0: - outputSize = table[i].size; - memcpy(&CompOutput[0], &CompInput[0], outputSize); - break; + int rate = 22050; + int tag, size = -1; - case 1: - outputSize = CompDecode(&CompInput[0], &CompOutput[0]); - break; - - case 2: - outputSize = CompDecode(&CompInput[0], &CompOutput[0]); - p = CompOutput; - for (z = 1; z < outputSize; z++) - p[z] += p[z - 1]; - break; - - case 3: - outputSize = CompDecode(&CompInput[0], &CompOutput[0]); - p = CompOutput; - for (z = 2; z < outputSize; z++) - p[z] += p[z - 1]; - for (z = 1; z < outputSize; z++) - p[z] += p[z - 1]; - break; + tag = READ_BE_UINT32(ptr); ptr+=4; + if (tag != MKID_BE('iMUS')) { + warning("Decompression of bundle sound failed"); + free(ptr); + return; + } - case 10: - outputSize = CompDecode(&CompInput[0], &CompOutput[0]); - p = CompOutput; - for (z = 2; z < outputSize; z++) - p[z] += p[z - 1]; - for (z = 1; z < outputSize; z++) - p[z] += p[z - 1]; - - t_table = (byte*)malloc(outputSize); - memcpy (t_table, p, outputSize); - - offset1 = outputSize / 3; - offset2 = offset1 * 2; - offset3 = offset2; - src = CompOutput; - do { - if (offset1 == 0) break; - offset1--; - offset2 -= 2; - offset3--; - *(t_table + offset2 + 0) = *(src + offset1); - *(t_table + offset2 + 1) = *(src + offset3); - } while(1); - - src = CompOutput; - length = (outputSize * 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 & 0xf0) >> 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 & 0xf0) >> 4); - } - s += 12; - k++; - c += 12; - } while (k <= length); - } + ptr += 12; + while(tag != MKID_BE('DATA')) { + tag = READ_BE_UINT32(ptr); ptr+=4; + switch(tag) { + case MKID_BE('FRMT'): + size = READ_BE_UINT32(ptr); ptr+=16; + rate = READ_BE_UINT32(ptr); ptr+=8; break; - - case 11: - outputSize = CompDecode(&CompInput[0], &CompOutput[0]); - p = CompOutput; - for (z = 2; z < outputSize; z++) - p[z] += p[z - 1]; - for (z = 1; z < outputSize; z++) - p[z] += p[z - 1]; - - t_table = (byte*)malloc(outputSize); - memcpy (t_table, p, outputSize); - - offset1 = outputSize / 3; - offset2 = offset1 * 2; - offset3 = offset2; - src = CompOutput; - do { - if (offset1 == 0) break; - offset1--; - offset2 -= 2; - offset3--; - *(t_table + offset2 + 0) = *(src + offset1); - *(t_table + offset2 + 1) = *(src + offset3); - } while(1); - - src = CompOutput; - length = (outputSize * 8) / 12; - k = 1; - c = 0; - s = 12; - t_tmp1 = (*(t_table + length)) >> 4; - *(src) = 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 & 0xf0) >> 4; - *(src + r - 1) = ((t_tmp1 & 0x0f) << 4) | ((t_tmp2 & 0xf0) >> 4); - } - s += 12; - k++; - c += 12; - } while (k < t); - } - + case MKID_BE('TEXT'): + case MKID_BE('REGN'): + case MKID_BE('STOP'): + case MKID_BE('JUMP'): + size = READ_BE_UINT32(ptr); ptr+=size+4; break; - case 12: - outputSize = CompDecode(&CompInput[0], &CompOutput[0]); - p = CompOutput; - for (z = 2; z < outputSize; z++) - p[z] += p[z - 1]; - for (z = 1; z < outputSize; z++) - p[z] += p[z - 1]; - - t_table = (byte*)malloc(outputSize); - memcpy (t_table, p, outputSize); - - offset1 = outputSize / 3; - offset2 = offset1 * 2; - offset3 = offset2; - src = CompOutput; - do { - if (offset1 == 0) break; - offset1--; - offset2 -= 2; - offset3--; - *(t_table + offset2 + 0) = *(src + offset1); - *(t_table + offset2 + 1) = *(src + offset3); - } while(1); - - src = CompOutput; - length = (outputSize * 8) / 12; - k = 0; - c = 0; - s = -12; - *(src) = *(outputSize + t_table - 1); - *(src + outputSize - 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 & 0xf0) >> 4); - } else { - r = c / 8; - t_tmp1 = *(t_table + k); - t_tmp2 = *(t_table + j); - *(src + r + 2) = (t_tmp1 & 0xf0) >> 4; - *(src + r + 1) = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f); - } - s += 12; - k++; - c += 12; - } while (k < t); - } - + case MKID_BE('DATA'): + size = READ_BE_UINT32(ptr); ptr+=4; break; default: - printf("Unknown codec %d!\n", table[i].codec); - outputSize = 0; - break; - } - memcpy(&CompFinal[finalSize], &CompOutput[0], outputSize); - finalSize+=outputSize; - - free(CompInput); CompInput = NULL; - free(CompOutput); CompOutput= NULL; - } - - { /* Parse decompressed data */ - int rate = 22050; - byte *ptr = CompFinal; - int tag, size = -1; - tag = READ_BE_UINT32(ptr); ptr+=4; - if (tag != MKID_BE('iMUS')) { - warning("Decompression of bundle sound failed"); - free(CompFinal); - return; - } - - ptr+=12; /* Skip header */ - while(tag != MKID_BE('DATA')) { - tag = READ_BE_UINT32(ptr); ptr+=4; - switch(tag) { - case MKID_BE('FRMT'): - size = READ_BE_UINT32(ptr); ptr+=16; - rate = READ_BE_UINT32(ptr); ptr+=8; - break; - case MKID_BE('TEXT'): - case MKID_BE('REGN'): - case MKID_BE('STOP'): - size = READ_BE_UINT32(ptr); ptr+=size+4; - break; - - case MKID_BE('DATA'): - size = READ_BE_UINT32(ptr); ptr+=4; - break; - - default: - error("Unknown bundle header %c%c%c%c", tag>>24, tag>>16, tag>>8, tag); - } - } - - if (size < 0) { - warning("Decompression of bundle sound failed (no size field)"); - free(CompFinal); - return; + error("Unknown sound header %c%c%c%c", tag>>24, tag>>16, tag>>8, tag); } - Final = (unsigned char *)malloc(size); - memcpy(&Final[0], &ptr[0], size); - _mixer->play_raw(NULL, Final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE); - free(CompFinal); } -} -void Scumm::playBundleSound(char *sound) -{ - if (!_sfxFile) { - warning("playBundleSound: SFX file is not open"); + if (size < 0) { + warning("Decompression sound failed (no size field)"); + free(ptr); return; } - - for (int i=0; i < num_sound_effects; i++) { - if (!scumm_stricmp(sound, bundle_table[i].filename)) { - decompressBundleSound(i); - return; - } - } - - warning("playBundleSound can't find %s", sound); + + byte * final = (byte *)malloc(size); + memcpy(final, ptr, size); + _mixer->play_raw(NULL, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE); } int Scumm::playSfxSound(void *sound, uint32 size, uint rate) diff --git a/sound/mixer.h b/sound/mixer.h index 49fe0eca19..7f52e88f54 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -207,9 +207,4 @@ struct MP3OffsetTable { /* Compressed Sound (.SO3) */ int compressed_size; }; -struct BundleAudioTable { /* Dig/CMI .bun audio */ - char filename[13]; - int size; - int offset; -}; #endif /* _mixer_h_included */ |