aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/imuse_digi/dimuse.cpp7
-rw-r--r--scumm/imuse_digi/dimuse.h1
-rw-r--r--scumm/imuse_digi/dimuse_bndmgr.cpp68
-rw-r--r--scumm/imuse_digi/dimuse_bndmgr.h17
-rw-r--r--scumm/imuse_digi/dimuse_sndmgr.cpp93
-rw-r--r--scumm/imuse_digi/dimuse_sndmgr.h6
-rw-r--r--scumm/imuse_digi/dimuse_track.cpp5
-rw-r--r--scumm/saveload.h2
8 files changed, 158 insertions, 41 deletions
diff --git a/scumm/imuse_digi/dimuse.cpp b/scumm/imuse_digi/dimuse.cpp
index 1f9b702282..bb6000145d 100644
--- a/scumm/imuse_digi/dimuse.cpp
+++ b/scumm/imuse_digi/dimuse.cpp
@@ -116,6 +116,7 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
MKLINE(Track, mixerFlags, sleInt32, VER(31)),
MK_OBSOLETE(Track, mixerVol, sleInt32, VER(31), VER(42)),
MK_OBSOLETE(Track, mixerPan, sleInt32, VER(31), VER(42)),
+ MKLINE(Track, compressed, sleByte, VER(45)),
MKEND()
};
@@ -143,6 +144,10 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
track->soundName, track->soundType,
track->volGroupId, -1);
assert(track->soundHandle);
+ if (track->compressed) {
+ track->regionOffset = 0;
+ track->dataOffset = _sound->getRegionOffset(track->soundHandle, track->curRegion);
+ }
int32 streamBufferSize = track->iteration;
int freq = _sound->getFreq(track->soundHandle);
track->stream2 = NULL;
@@ -282,8 +287,8 @@ void IMuseDigital::callback() {
_vm->_mixer->setChannelBalance(track->handle, pan);
track->stream->append(data, result);
track->regionOffset += result;
- free(data);
}
+ free(data);
if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
switchToNextRegion(track);
diff --git a/scumm/imuse_digi/dimuse.h b/scumm/imuse_digi/dimuse.h
index 94d7877e83..8a6e95519a 100644
--- a/scumm/imuse_digi/dimuse.h
+++ b/scumm/imuse_digi/dimuse.h
@@ -64,6 +64,7 @@ private:
bool readyToRemove;
bool started;
bool souStream;
+ bool compressed;
int32 priority;
int32 regionOffset;
int32 dataOffset;
diff --git a/scumm/imuse_digi/dimuse_bndmgr.cpp b/scumm/imuse_digi/dimuse_bndmgr.cpp
index 2e1481caa1..5a7de3dfd7 100644
--- a/scumm/imuse_digi/dimuse_bndmgr.cpp
+++ b/scumm/imuse_digi/dimuse_bndmgr.cpp
@@ -30,6 +30,7 @@ BundleDirCache::BundleDirCache() {
_budleDirCache[fileId].bundleTable = NULL;
_budleDirCache[fileId].fileName[0] = 0;
_budleDirCache[fileId].numFiles = 0;
+ _budleDirCache[fileId].compressedBun = false;
}
}
@@ -40,18 +41,18 @@ BundleDirCache::~BundleDirCache() {
}
}
-BundleDirCache::AudioTable *BundleDirCache::getTable(const char *filename) {
- int slot = matchFile(filename);
- assert(slot != -1);
+BundleDirCache::AudioTable *BundleDirCache::getTable(const char *filename, int slot) {
return _budleDirCache[slot].bundleTable;
}
-int32 BundleDirCache::getNumFiles(const char *filename) {
- int slot = matchFile(filename);
- assert(slot != -1);
+int32 BundleDirCache::getNumFiles(const char *filename, int slot) {
return _budleDirCache[slot].numFiles;
}
+bool BundleDirCache::isCompressed(int slot) {
+ return _budleDirCache[slot].compressedBun;
+}
+
int BundleDirCache::matchFile(const char *filename) {
int32 tag, offset;
bool found = false;
@@ -80,6 +81,8 @@ int BundleDirCache::matchFile(const char *filename) {
error("BundleDirCache::matchFileFile() Can't find free slot for file bundle dir cache");
tag = file.readUint32BE();
+ if (tag == 'LB23')
+ _budleDirCache[freeSlot].compressedBun = true;
offset = file.readUint32BE();
strcpy(_budleDirCache[freeSlot].fileName, filename);
@@ -89,22 +92,26 @@ int BundleDirCache::matchFile(const char *filename) {
file.seek(offset, SEEK_SET);
for (int32 i = 0; i < _budleDirCache[freeSlot].numFiles; i++) {
- char name[13], c;
+ char name[24], 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(_budleDirCache[freeSlot].bundleTable[i].filename, name);
+ if (tag == 'LB23') {
+ file.read(_budleDirCache[freeSlot].bundleTable[i].filename, 24);
+ } else {
+ 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(_budleDirCache[freeSlot].bundleTable[i].filename, name);
+ }
_budleDirCache[freeSlot].bundleTable[i].offset = file.readUint32BE();
- file.seek(4, SEEK_CUR);
+ _budleDirCache[freeSlot].bundleTable[i].size = file.readUint32BE();
}
return freeSlot;
} else {
@@ -124,10 +131,22 @@ BundleMgr::BundleMgr(BundleDirCache *cache) {
}
BundleMgr::~BundleMgr() {
- closeFile();
+ close();
}
-bool BundleMgr::openFile(const char *filename) {
+File *BundleMgr::getFile(const char *filename, int32 &offset, int32 &size) {
+ for (int i = 0; i < _numFiles; i++) {
+ if (!scumm_stricmp(filename, _bundleTable[i].filename)) {
+ _file.seek(_bundleTable[i].offset, SEEK_SET);
+ offset = _bundleTable[i].offset;
+ size = _bundleTable[i].size;
+ break;
+ }
+ }
+ return &_file;
+}
+
+bool BundleMgr::open(const char *filename, bool &compressed) {
if (_file.isOpen())
return true;
@@ -136,9 +155,12 @@ bool BundleMgr::openFile(const char *filename) {
return false;
}
- _numFiles = _cache->getNumFiles(filename);
+ int slot = _cache->matchFile(filename);
+ assert(slot != -1);
+ compressed = _cache->isCompressed(slot);
+ _numFiles = _cache->getNumFiles(filename, slot);
assert(_numFiles);
- _bundleTable = _cache->getTable(filename);
+ _bundleTable = _cache->getTable(filename, slot);
assert(_bundleTable);
_compTableLoaded = false;
_outputSize = 0;
@@ -147,7 +169,7 @@ bool BundleMgr::openFile(const char *filename) {
return true;
}
-void BundleMgr::closeFile() {
+void BundleMgr::close() {
if (_file.isOpen()) {
_file.close();
_bundleTable = NULL;
diff --git a/scumm/imuse_digi/dimuse_bndmgr.h b/scumm/imuse_digi/dimuse_bndmgr.h
index c79232efdc..5457ae20b8 100644
--- a/scumm/imuse_digi/dimuse_bndmgr.h
+++ b/scumm/imuse_digi/dimuse_bndmgr.h
@@ -29,8 +29,9 @@ namespace Scumm {
class BundleDirCache {
public:
struct AudioTable {
- char filename[13];
+ char filename[24];
int32 offset;
+ int32 size;
};
private:
@@ -38,16 +39,17 @@ private:
char fileName[20];
AudioTable *bundleTable;
int32 numFiles;
+ bool compressedBun;
} _budleDirCache[4];
- int matchFile(const char *filename);
-
public:
BundleDirCache();
~BundleDirCache();
- AudioTable *getTable(const char *filename);
- int32 getNumFiles(const char *filename);
+ int matchFile(const char *filename);
+ AudioTable *getTable(const char *filename, int slot);
+ int32 getNumFiles(const char *filename, int slot);
+ bool isCompressed(int slot);
};
class BundleMgr {
@@ -80,8 +82,9 @@ public:
BundleMgr(BundleDirCache *_cache);
~BundleMgr();
- bool openFile(const char *filename);
- void closeFile();
+ bool open(const char *filename, bool &compressed);
+ void close();
+ File *getFile(const char *filename, int32 &offset, int32 &size);
int32 decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final, bool header_outside);
int32 decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size, bool header_outside);
int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size, bool header_outside);
diff --git a/scumm/imuse_digi/dimuse_sndmgr.cpp b/scumm/imuse_digi/dimuse_sndmgr.cpp
index d0eb9ff525..cc9ca79de2 100644
--- a/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -22,6 +22,7 @@
#include "common/scummsys.h"
#include "common/util.h"
#include "sound/voc.h"
+#include "sound/vorbis.h"
#include "scumm/scumm.h"
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse_digi/dimuse_sndmgr.h"
@@ -79,6 +80,39 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i
} while (tag != MKID_BE('DATA'));
}
+void ImuseDigiSndMgr::prepareSoundFromRMAP(File *file, soundStruct *sound, int32 offset, int32 size) {
+ int l;
+
+ file->seek(offset, SEEK_SET);
+ uint32 tag = file->readUint32BE();
+ assert(tag == 'RMAP');
+ assert(file->readUint32BE() == 1); // version
+ sound->bits = 16;
+ sound->freq = 22050;
+ sound->channels = 2;
+ sound->numRegions = file->readUint32BE();
+ sound->numJumps = file->readUint32BE();
+ sound->numSyncs = file->readUint32BE();
+ sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions);
+ sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps);
+ sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs);
+ for (l = 0; l < sound->numRegions; l++) {
+ sound->region[l].offset = file->readUint32BE();
+ sound->region[l].length = file->readUint32BE();
+ }
+ for (l = 0; l < sound->numJumps; l++) {
+ sound->jump[l].offset = file->readUint32BE();
+ sound->jump[l].dest = file->readUint32BE();
+ sound->jump[l].hookId = file->readUint32BE();
+ sound->jump[l].fadeDelay = file->readUint32BE();
+ }
+ for (l = 0; l < sound->numSyncs; l++) {
+ sound->sync[l].size = file->readUint32BE();
+ sound->sync[l].ptr = (byte *)malloc(sound->sync[l].size);
+ file->read(sound->sync[l].ptr, sound->sync[l].size);
+ }
+}
+
void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {
if (READ_UINT32(ptr) == MKID('Crea')) {
bool quit = false;
@@ -224,7 +258,7 @@ bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) {
sound->bundle = new BundleMgr(_cacheBundleDir);
if (_vm->_gameId == GID_CMI) {
if (_vm->_features & GF_DEMO) {
- result = sound->bundle->openFile("music.bun");
+ result = sound->bundle->open("music.bun", sound->compressed);
} else {
char musicfile[20];
if (disk == -1)
@@ -237,13 +271,13 @@ bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) {
// sound->bundle->closeFile();
// }
- result = sound->bundle->openFile(musicfile);
+ result = sound->bundle->open(musicfile, sound->compressed);
// FIXME: Shouldn't we only set _disk if result == true?
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
}
} else if (_vm->_gameId == GID_DIG)
- result = sound->bundle->openFile("digmusic.bun");
+ result = sound->bundle->open("digmusic.bun", sound->compressed);
else
error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load");
@@ -258,7 +292,7 @@ bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) {
sound->bundle = new BundleMgr(_cacheBundleDir);
if (_vm->_gameId == GID_CMI) {
if (_vm->_features & GF_DEMO) {
- result = sound->bundle->openFile("voice.bun");
+ result = sound->bundle->open("voice.bun", sound->compressed);
} else {
char voxfile[20];
if (disk == -1)
@@ -271,13 +305,13 @@ bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) {
// sound->bundle->closeFile();
// }
- result = sound->bundle->openFile(voxfile);
+ result = sound->bundle->open(voxfile, sound->compressed);
// FIXME: Shouldn't we only set _disk if result == true?
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
}
} else if (_vm->_gameId == GID_DIG)
- result = sound->bundle->openFile("digvoice.bun");
+ result = sound->bundle->open("digvoice.bun", sound->compressed);
else
error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load");
@@ -323,7 +357,19 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch
closeSound(sound);
return NULL;
}
- if (soundName[0] == 0) {
+ if (sound->compressed) {
+ char fileName[24];
+ int32 offset = 0, size = 0;
+ sprintf(fileName, "%s.map", soundName);
+ File *rmapFile = sound->bundle->getFile(fileName, offset, size);
+ prepareSoundFromRMAP(rmapFile, sound, offset, size);
+ strcpy(sound->name, soundName);
+ sound->soundId = soundId;
+ sound->type = soundType;
+ sound->volGroupId = volGroupId;
+ sound->disk = _disk;
+ return sound;
+ } else if (soundName[0] == 0) {
if (sound->bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0, header_outside) == 0 || ptr == NULL) {
closeSound(sound);
return NULL;
@@ -362,7 +408,11 @@ void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) {
_vm->unlock(rtSound, soundHandle->soundId);
}
+ if (soundHandle->compressedStream)
+ delete soundHandle->compressedStream;
+
delete soundHandle->bundle;
+
for (int r = 0; r < soundHandle->numSyncs; r++)
free(soundHandle->sync[r].ptr);
free(soundHandle->region);
@@ -387,6 +437,11 @@ bool ImuseDigiSndMgr::checkForProperHandle(soundStruct *soundHandle) {
return false;
}
+bool ImuseDigiSndMgr::isCompressed(soundStruct *soundHandle) {
+ assert(checkForProperHandle(soundHandle));
+ return soundHandle->compressed;
+}
+
int ImuseDigiSndMgr::getFreq(soundStruct *soundHandle) {
assert(checkForProperHandle(soundHandle));
return soundHandle->freq;
@@ -500,13 +555,33 @@ int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, b
int header_size = soundHandle->offsetData;
bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO));
- if (soundHandle->bundle) {
+ if ((soundHandle->bundle) && (!soundHandle->compressed)) {
size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
} else if (soundHandle->resPtr) {
*buf = (byte *)malloc(size);
memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size);
+ } else if ((soundHandle->bundle) && (soundHandle->compressed)) {
+ *buf = (byte *)malloc(size);
+ char fileName[24];
+ sprintf(fileName, "%s_reg%03d.ogg", soundHandle->name, region);
+ if (scumm_stricmp(fileName, soundHandle->lastFileName) != 0) {
+ int32 offset = 0, size = 0;
+ File *oggFile = soundHandle->bundle->getFile(fileName, offset, size);
+ if (!soundHandle->compressedStream) {
+ soundHandle->compressedStream = makeVorbisStream(oggFile, size);
+ assert(soundHandle->compressedStream);
+ assert(soundHandle->compressedStream->getRate() == 22050);
+ assert(soundHandle->compressedStream->isStereo());
+ }
+ strcpy(soundHandle->lastFileName, fileName);
+ }
+ size = soundHandle->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2;
+ if (soundHandle->compressedStream->endOfData()) {
+ delete soundHandle->compressedStream;
+ soundHandle->compressedStream = NULL;
+ }
}
-
+
return size;
}
diff --git a/scumm/imuse_digi/dimuse_sndmgr.h b/scumm/imuse_digi/dimuse_sndmgr.h
index 3435e256b2..3e6713a290 100644
--- a/scumm/imuse_digi/dimuse_sndmgr.h
+++ b/scumm/imuse_digi/dimuse_sndmgr.h
@@ -23,6 +23,7 @@
#include "stdafx.h"
#include "common/scummsys.h"
+#include "sound/audiostream.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
namespace Scumm {
@@ -83,6 +84,9 @@ public:
int type;
int volGroupId;
int disk;
+ AudioStream *compressedStream;
+ bool compressed;
+ char lastFileName[24];
};
private:
@@ -92,6 +96,7 @@ private:
bool checkForProperHandle(soundStruct *soundHandle);
soundStruct *allocSlot();
void prepareSound(byte *ptr, soundStruct *sound);
+ void prepareSoundFromRMAP(File *file, soundStruct *sound, int32 offset, int32 size);
ScummEngine *_vm;
byte _disk;
@@ -111,6 +116,7 @@ public:
void closeSound(soundStruct *soundHandle);
soundStruct *cloneSound(soundStruct *soundHandle);
+ bool isCompressed(soundStruct *soundHandle);
int getFreq(soundStruct *soundHandle);
int getBits(soundStruct *soundHandle);
int getChannels(soundStruct *soundHandle);
diff --git a/scumm/imuse_digi/dimuse_track.cpp b/scumm/imuse_digi/dimuse_track.cpp
index 4aeaaba651..7ee5fd1beb 100644
--- a/scumm/imuse_digi/dimuse_track.cpp
+++ b/scumm/imuse_digi/dimuse_track.cpp
@@ -119,6 +119,8 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
if (track->soundHandle == NULL)
return;
+ track->compressed = _sound->isCompressed(track->soundHandle);
+
bits = _sound->getBits(track->soundHandle);
channels = _sound->getChannels(track->soundHandle);
freq = _sound->getFreq(track->soundHandle);
@@ -147,6 +149,9 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
track->mixerFlags |= SoundMixer::FLAG_UNSIGNED;
} else
error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
+
+ if (track->compressed)
+ track->mixerFlags |= SoundMixer::FLAG_LITTLE_ENDIAN;
}
if (input) {
diff --git a/scumm/saveload.h b/scumm/saveload.h
index deb4cc20bd..747e06799f 100644
--- a/scumm/saveload.h
+++ b/scumm/saveload.h
@@ -32,7 +32,7 @@ namespace Scumm {
// Can be useful for other ports too :)
#define VER(x) x
-#define CURRENT_VER 44
+#define CURRENT_VER 45
// To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types,
// we use a small trick: instead of 0 we use 42. Why? Well, it seems newer GCC