diff options
author | Robert Špalek | 2009-10-11 22:30:40 +0000 |
---|---|---|
committer | Robert Špalek | 2009-10-11 22:30:40 +0000 |
commit | c4563616ae06194087b467746fe2b820b6311ac0 (patch) | |
tree | a31010111c1c0900e8c951d90b309063b8e9f33f /engines/draci | |
parent | b6baadff535fd48fbf94a2519ac4a2404088d273 (diff) | |
download | scummvm-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.cpp | 8 | ||||
-rw-r--r-- | engines/draci/barchive.h | 6 | ||||
-rw-r--r-- | engines/draci/draci.cpp | 32 | ||||
-rw-r--r-- | engines/draci/draci.h | 4 | ||||
-rw-r--r-- | engines/draci/module.mk | 1 | ||||
-rw-r--r-- | engines/draci/sound.cpp | 160 | ||||
-rw-r--r-- | engines/draci/sound.h | 83 |
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 |