aboutsummaryrefslogtreecommitdiff
path: root/engines/draci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/draci')
-rw-r--r--engines/draci/barchive.cpp8
-rw-r--r--engines/draci/barchive.h6
-rw-r--r--engines/draci/draci.cpp32
-rw-r--r--engines/draci/draci.h4
-rw-r--r--engines/draci/module.mk1
-rw-r--r--engines/draci/sound.cpp160
-rw-r--r--engines/draci/sound.h83
7 files changed, 274 insertions, 20 deletions
diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp
index 30652a0b5a..408fe0c7de 100644
--- a/engines/draci/barchive.cpp
+++ b/engines/draci/barchive.cpp
@@ -268,10 +268,8 @@ void BArchive::closeArchive(void) {
* @return Pointer to a BAFile coresponding to the opened file or NULL (on failure)
*
* Loads individual BAR files from an archive to memory on demand.
- * Should not be called directly. Instead, one should access files
- * through the operator[] interface.
*/
-BAFile *BArchive::loadFileBAR(uint i) const {
+BAFile *BArchive::loadFileBAR(uint i) {
Common::File f;
// Else open archive and read in requested file
@@ -310,7 +308,7 @@ BAFile *BArchive::loadFileBAR(uint i) const {
* Should not be called directly. Instead, one should access files
* through the operator[] interface.
*/
-BAFile *BArchive::loadFileDFW(uint i) const {
+BAFile *BArchive::loadFileDFW(uint i) {
Common::File f;
byte *buf;
@@ -390,7 +388,7 @@ void BArchive::clearCache() {
}
}
-const BAFile *BArchive::getFile(uint i) const {
+const BAFile *BArchive::getFile(uint i) {
// Check whether requested file exists
if (i >= _fileCount) {
return NULL;
diff --git a/engines/draci/barchive.h b/engines/draci/barchive.h
index 0d77742de2..020e5e305a 100644
--- a/engines/draci/barchive.h
+++ b/engines/draci/barchive.h
@@ -71,7 +71,7 @@ public:
void clearCache();
- const BAFile *getFile(uint i) const;
+ const BAFile *getFile(uint i);
private:
// Archive header data
@@ -89,8 +89,8 @@ private:
bool _opened; ///< True if the archive is opened, false otherwise
void openDFW(const Common::String &path);
- BAFile *loadFileDFW(uint i) const;
- BAFile *loadFileBAR(uint i) const;
+ BAFile *loadFileDFW(uint i);
+ BAFile *loadFileBAR(uint i);
};
} // End of namespace Draci
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index c21f087479..ce0d59f8fe 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -47,18 +47,20 @@ namespace Draci {
// Data file paths
-const Common::String objectsPath("OBJEKTY.DFW");
-const Common::String palettePath("PALETY.DFW");
-const Common::String spritesPath("OBR_AN.DFW");
-const Common::String overlaysPath("OBR_MAS.DFW");
-const Common::String roomsPath("MIST.DFW");
-const Common::String animationsPath("ANIM.DFW");
-const Common::String iconsPath("HRA.DFW");
-const Common::String walkingMapsPath("MAPY.DFW");
-const Common::String itemsPath("IKONY.DFW");
-const Common::String itemImagesPath("OBR_IK.DFW");
-const Common::String initPath("INIT.DFW");
-const Common::String stringsPath("RETEZCE.DFW");
+const char *objectsPath = "OBJEKTY.DFW";
+const char *palettePath = "PALETY.DFW";
+const char *spritesPath = "OBR_AN.DFW";
+const char *overlaysPath = "OBR_MAS.DFW";
+const char *roomsPath = "MIST.DFW";
+const char *animationsPath = "ANIM.DFW";
+const char *iconsPath = "HRA.DFW";
+const char *walkingMapsPath = "MAPY.DFW";
+const char *itemsPath = "IKONY.DFW";
+const char *itemImagesPath = "OBR_IK.DFW";
+const char *initPath = "INIT.DFW";
+const char *stringsPath = "RETEZCE.DFW";
+const char *soundsPath = "CD2.SAM";
+const char *dubbingPath = "CD.SAM";
DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc)
: Engine(syst) {
@@ -107,6 +109,9 @@ int DraciEngine::init() {
_itemImagesArchive = new BArchive(itemImagesPath);
_stringsArchive = new BArchive(stringsPath);
+ _soundsArchive = new SoundArchive(soundsPath);
+ _dubbingArchive = new SoundArchive(dubbingPath);
+
// Load the game's fonts
_smallFont = new Font(kFontSmall);
_bigFont = new Font(kFontBig);
@@ -281,6 +286,9 @@ DraciEngine::~DraciEngine() {
delete _itemImagesArchive;
delete _stringsArchive;
+ delete _soundsArchive;
+ delete _dubbingArchive;
+
// Remove all of our debug levels here
Common::clearAllDebugChannels();
}
diff --git a/engines/draci/draci.h b/engines/draci/draci.h
index fed7cfed7e..d5683d5516 100644
--- a/engines/draci/draci.h
+++ b/engines/draci/draci.h
@@ -37,6 +37,7 @@
#include "draci/script.h"
#include "draci/barchive.h"
#include "draci/animation.h"
+#include "draci/sound.h"
namespace Draci {
@@ -82,6 +83,9 @@ public:
BArchive *_initArchive;
BArchive *_stringsArchive;
+ SoundArchive *_soundsArchive;
+ SoundArchive *_dubbingArchive;
+
bool _showWalkingMap;
Common::RandomSource _rnd;
diff --git a/engines/draci/module.mk b/engines/draci/module.mk
index 10abad2b44..1810ddff2f 100644
--- a/engines/draci/module.mk
+++ b/engines/draci/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
script.o \
font.o \
saveload.o \
+ sound.o \
sprite.o \
screen.o \
surface.o \
diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp
new file mode 100644
index 0000000000..bd2f68658b
--- /dev/null
+++ b/engines/draci/sound.cpp
@@ -0,0 +1,160 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/draci/barchive.cpp $
+ * $Id: barchive.cpp 44493 2009-09-30 16:04:21Z fingolfin $
+ *
+ */
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+#include "draci/sound.h"
+#include "draci/draci.h"
+
+namespace Draci {
+
+void SoundArchive::openArchive(const Common::String &path) {
+ // Close previously opened archive (if any)
+ closeArchive();
+
+ debugCN(2, kDraciArchiverDebugLevel, "Loading samples %s: ", path.c_str());
+
+ _f = new Common::File();
+ _f->open(path);
+ if (_f->isOpen()) {
+ debugC(2, kDraciArchiverDebugLevel, "Success");
+ } else {
+ debugC(2, kDraciArchiverDebugLevel, "Error");
+ return;
+ }
+
+ // Save path for reading in files later on
+ _path = path;
+
+ // Read archive header
+ debugC(2, kDraciArchiverDebugLevel, "Loading header");
+
+ uint totalLength = _f->readUint32LE();
+ const uint kMaxSamples = 4095; // The no-sound file is exactly 16K bytes long, so don't fail on short reads
+ uint sampleStarts[kMaxSamples];
+ for (uint i = 0; i < kMaxSamples; ++i) {
+ sampleStarts[i] = _f->readUint32LE();
+ }
+
+ // Fill the sample table
+ for (_sampleCount = 0; _sampleCount < kMaxSamples - 1; ++_sampleCount) {
+ int length = sampleStarts[_sampleCount + 1] - sampleStarts[_sampleCount];
+ if (length <= 0 && sampleStarts[_sampleCount] >= totalLength) // heuristics to detect the last sample
+ break;
+ }
+ if (_sampleCount > 0) {
+ debugC(2, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length",
+ _sampleCount, totalLength);
+ _samples = new SoundSample[_sampleCount];
+ for (uint i = 0; i < _sampleCount; ++i) {
+ _samples[i]._offset = sampleStarts[i];
+ _samples[i]._length = sampleStarts[i+1] - sampleStarts[i];
+ _samples[i]._data = NULL;
+ }
+ if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength &&
+ _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) {
+ // WORKAROUND: the stored length is stored with the header for sounds and without the hader for dubbing. Crazy.
+ debugC(2, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d",
+ _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length,
+ totalLength);
+ closeArchive();
+ return;
+ }
+ } else {
+ debugC(2, kDraciArchiverDebugLevel, "Archive info: empty");
+ }
+
+ // Indicate that the archive has been successfully opened
+ _opened = true;
+}
+
+/**
+ * @brief SoundArchive close method
+ *
+ * Closes the currently opened archive. It can be called explicitly to
+ * free up memory.
+ */
+void SoundArchive::closeArchive() {
+ clearCache();
+ delete _f;
+ _f = NULL;
+ delete[] _samples;
+ _samples = NULL;
+ _sampleCount = 0;
+ _path = "";
+ _opened = false;
+}
+
+/**
+ * Clears the cache of the open files inside the archive without closing it.
+ * If the files are subsequently accessed, they are read from the disk.
+ */
+void SoundArchive::clearCache() {
+ // Delete all cached data
+ for (uint i = 0; i < _sampleCount; ++i) {
+ _samples[i].close();
+ }
+}
+
+/**
+ * @brief On-demand sound sample loader
+ * @param i Index of file inside an archive
+ * @return Pointer to a SoundSample coresponding to the opened file or NULL (on failure)
+ *
+ * Loads individual samples from an archive to memory on demand.
+ */
+const SoundSample *SoundArchive::getSample(uint i) {
+ // Check whether requested file exists
+ if (i >= _sampleCount) {
+ return NULL;
+ }
+
+ debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d from archive %s... ",
+ i, _path.c_str());
+
+ // Check if file has already been opened and return that
+ if (_samples[i]._data) {
+ debugC(2, kDraciArchiverDebugLevel, "Success");
+ return _samples + i;
+ }
+
+ // Read in the file (without the file header)
+ _f->seek(_samples[i]._offset);
+ _samples[i]._data = new byte[_samples[i]._length];
+ _f->read(_samples[i]._data, _samples[i]._length);
+
+ debugC(3, kDraciArchiverDebugLevel, "Cached sample %d from archive %s",
+ i, _path.c_str());
+
+ return _samples + i;
+}
+
+} // End of namespace Draci
+
+
+
diff --git a/engines/draci/sound.h b/engines/draci/sound.h
new file mode 100644
index 0000000000..9c8c571af4
--- /dev/null
+++ b/engines/draci/sound.h
@@ -0,0 +1,83 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/draci/barchive.h $
+ * $Id: barchive.h 44802 2009-10-08 21:28:57Z fingolfin $
+ *
+ */
+
+#ifndef DRACI_SOUND_H
+#define DRACI_SOUND_H
+
+#include "common/str.h"
+#include "common/file.h"
+
+namespace Draci {
+
+/**
+ * Represents individual files inside the archive.
+ */
+struct SoundSample {
+ uint _offset;
+ uint _length;
+ byte* _data;
+
+ void close(void) {
+ delete[] _data;
+ _data = NULL;
+ }
+};
+
+class SoundArchive {
+public:
+ SoundArchive() : _path(), _samples(NULL), _sampleCount(0), _opened(false), _f(NULL) {}
+
+ SoundArchive(const Common::String &path) :
+ _path(), _samples(NULL), _sampleCount(0), _opened(false), _f(NULL) {
+ openArchive(path);
+ }
+
+ ~SoundArchive() { closeArchive(); }
+
+ void closeArchive();
+ void openArchive(const Common::String &path);
+ uint size() const { return _sampleCount; }
+
+ /**
+ * Checks whether there is an archive opened. Should be called before reading
+ * from the archive to check whether openArchive() succeeded.
+ */
+ bool isOpen() const { return _opened; }
+
+ void clearCache();
+
+ const SoundSample *getSample(uint i);
+
+private:
+ Common::String _path; ///< Path to file
+ SoundSample *_samples; ///< Internal array of files
+ uint _sampleCount; ///< Number of files in archive
+ bool _opened; ///< True if the archive is opened, false otherwise
+ Common::File *_f; ///< Opened file
+};
+
+} // End of namespace Draci
+
+#endif // DRACI_SOUND_H