diff options
-rw-r--r-- | common/file.cpp | 52 | ||||
-rw-r--r-- | common/file.h | 54 | ||||
-rw-r--r-- | engines/saga/music.cpp | 7 | ||||
-rw-r--r-- | engines/scumm/resource.cpp | 2 |
4 files changed, 81 insertions, 34 deletions
diff --git a/common/file.cpp b/common/file.cpp index 6558dfea33..ec605d45c1 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -65,61 +65,59 @@ File::~File() { close(); } - bool File::open(const String &filename) { + return open(filename, SearchMan); +} + +bool File::open(const String &filename, Archive &archive) { assert(!filename.empty()); assert(!_handle); - _name.clear(); clearIOFailed(); - if (SearchMan.hasFile(filename)) { + SeekableReadStream *stream = 0; + if (archive.hasFile(filename)) { debug(3, "Opening hashed: %s", filename.c_str()); - _handle = SearchMan.openFile(filename); - } else if (SearchMan.hasFile(filename + ".")) { + stream = archive.openFile(filename); + } else if (archive.hasFile(filename + ".")) { // WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails" // sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot) debug(3, "Opening hashed: %s.", filename.c_str()); - _handle = SearchMan.openFile(filename + "."); + stream = archive.openFile(filename + "."); } - if (_handle == NULL) - debug(2, "File::open: '%s' not found", filename.c_str()); - else - _name = filename; - - return _handle != NULL; + return open(stream, filename); } bool File::open(const FilesystemNode &node) { + assert(!_handle); if (!node.exists()) { - warning("File::open: FilesystemNode does not exist"); + warning("File::open: '%s' does not exist", node.getPath().c_str()); return false; } else if (node.isDirectory()) { - warning("File::open: FilesystemNode is a directory"); + warning("File::open: '%s' is a directory", node.getPath().c_str()); return false; } - String filename(node.getName()); - - if (_handle) { - error("File::open: This file object already is opened (%s), won't open '%s'", _name.c_str(), filename.c_str()); - } + SeekableReadStream *stream = node.openForReading(); + return open(stream, node.getPath()); +} +bool File::open(SeekableReadStream *stream, const Common::String &name) { + assert(!_handle); clearIOFailed(); - _name.clear(); - - _handle = node.openForReading(); - - if (_handle == NULL) - debug(2, "File::open: '%s' not found", node.getPath().c_str()); - else - _name = filename; + if (stream) { + _handle = stream; + _name = name; + } else { + debug(2, "File::open: opening '%s' failed", name.c_str()); + } return _handle != NULL; } + bool File::exists(const String &filename) { if (SearchMan.hasFile(filename)) { return true; diff --git a/common/file.h b/common/file.h index a2739f795f..079b0bba84 100644 --- a/common/file.h +++ b/common/file.h @@ -27,6 +27,7 @@ #define COMMON_FILE_H #include "common/scummsys.h" +#include "common/archive.h" #include "common/noncopyable.h" #include "common/str.h" #include "common/stream.h" @@ -43,7 +44,7 @@ protected: /** File handle to the actual file; 0 if no file is open. */ SeekableReadStream *_handle; - /** The name of this file, for debugging. */ + /** The name of this file, kept for debugging purposes. */ String _name; public: @@ -56,6 +57,7 @@ public: static void resetDefaultDirectories(); + File(); virtual ~File(); @@ -64,14 +66,56 @@ public: * (those were/are added by addDefaultDirectory and/or * addDefaultDirectoryRecursive). * - * @param filename: the file to check for - * @return: true if the file exists, else false + * @param filename the file to check for + * @return true if the file exists, false otherwise */ static bool exists(const String &filename); + /** + * Try to open the file with the given filename, by searching SearchMan. + * @note Must not be called if this file already is open (i.e. if isOpen returns true). + * + * @param filename the name of the file to open + * @return true if file was opened successfully, false otherwise + */ virtual bool open(const String &filename); + + /** + * Try to open the file with the given filename from within the given archive. + * @note Must not be called if this file already is open (i.e. if isOpen returns true). + * + * @param filename the name of the file to open + * @param archive the archive in which to search for the file + * @return true if file was opened successfully, false otherwise + */ + virtual bool open(const String &filename, Archive &archive); + + /** + * Try to open the file corresponding to the give node. Will check whether the + * node actually refers to an existing file (and not a directory), and handle + * those cases gracefully. + * @note Must not be called if this file already is open (i.e. if isOpen returns true). + * + * @param filename the name of the file to open + * @param archive the archive in which to search for the file + * @return true if file was opened successfully, false otherwise + */ virtual bool open(const FilesystemNode &node); + /** + * Try to 'open' the given stream. That is, we just wrap around it, and if stream + * is a NULL pointer, we gracefully treat this as if opening failed. + * @note Must not be called if this file already is open (i.e. if isOpen returns true). + * + * @param stream a pointer to a SeekableReadStream, or 0 + * @param name a string describing the 'file' corresponding to stream + * @return true if stream was 0, false otherwise + */ + virtual bool open(SeekableReadStream *stream, const Common::String &name); + + /** + * Close the file, if open. + */ virtual void close(); /** @@ -82,11 +126,11 @@ public: bool isOpen() const; /** - * Returns the filename of the opened file. + * Returns the filename of the opened file for debugging purposes. * * @return: the filename */ - const char *name() const { return _name.c_str(); } + const char *getName() const { return _name.c_str(); } bool ioFailed() const; void clearIOFailed(); diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 5bf0c0ec03..5d0c75d0ce 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -96,7 +96,12 @@ DigitalMusicInputStream::DigitalMusicInputStream(SagaEngine *vm, ResourceContext _compressedStream = NULL; - if (scumm_stricmp(_file->name(), "music.cmp") == 0 || scumm_stricmp(_file->name(), "musicd.cmp") == 0) { + // FIXME: It is a bad idea to use the File::getName() method to distinguish + // files here (note that it is for debugging purposes only, though that was + // not correctly documented in the past). + // A better way is to keep track of this via some flag, which indicates + // whether the music file contains compressed data. + if (scumm_stricmp(_file->getName(), "music.cmp") == 0 || scumm_stricmp(_file->getName(), "musicd.cmp") == 0) { // Read compressed header to determine compression type _file->seek((long)resourceData->offset, SEEK_SET); _file->read(compressedHeader, 9); diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp index 50e0d221ca..87ded6723b 100644 --- a/engines/scumm/resource.cpp +++ b/engines/scumm/resource.cpp @@ -676,7 +676,7 @@ int ScummEngine::loadResource(int type, int idx) { if (tag != _res->tags[type] && _game.heversion < 70) { error("%s %d not in room %d at %d+%d in file %s", _res->name[type], idx, roomNr, - _fileOffset, fileOffs, _fileHandle->name()); + _fileOffset, fileOffs, _fileHandle->getName()); } size = _fileHandle->readUint32BE(); |