aboutsummaryrefslogtreecommitdiff
path: root/engines/draci
diff options
context:
space:
mode:
authorRobert Špalek2009-10-11 22:30:40 +0000
committerRobert Špalek2009-10-11 22:30:40 +0000
commitc4563616ae06194087b467746fe2b820b6311ac0 (patch)
treea31010111c1c0900e8c951d90b309063b8e9f33f /engines/draci
parentb6baadff535fd48fbf94a2519ac4a2404088d273 (diff)
downloadscummvm-rg350-c4563616ae06194087b467746fe2b820b6311ac0.tar.gz
scummvm-rg350-c4563616ae06194087b467746fe2b820b6311ac0.tar.bz2
scummvm-rg350-c4563616ae06194087b467746fe2b820b6311ac0.zip
Added support for sound archives.
We initialize them in the DraciEngine constructor, but don't play any sounds yet. Checked that it works for all existing sound files (required several work-arounds against unspoken specification). When copying the interface from barchive.h, I decided to remove some const's from there, because getFile() wasn't really behaving like const. Removed some static Common::String instances. svn-id: r44953
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