aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.common2
-rw-r--r--bundle.cpp535
-rw-r--r--bundle.h71
-rw-r--r--morphos/Makefile2
-rw-r--r--scumm.h3
-rw-r--r--scummvm.cpp2
-rw-r--r--scummvm.dsp8
-rw-r--r--sound.cpp407
-rw-r--r--sound/mixer.h5
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 \
diff --git a/scumm.h b/scumm.h
index 6b567e77aa..3c60c3cdf9 100644
--- a/scumm.h
+++ b/scumm.h
@@ -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
diff --git a/sound.cpp b/sound.cpp
index fe37ddbba6..72217d5a27 100644
--- a/sound.cpp
+++ b/sound.cpp
@@ -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 */