diff options
author | Paul Gilbert | 2014-12-24 09:58:47 +1100 |
---|---|---|
committer | Paul Gilbert | 2014-12-24 09:58:47 +1100 |
commit | 977a25ec35d63fab0db315b35a69a4a508f587e9 (patch) | |
tree | 0124b2b89794cae42e026d7f47576fd8c5998a7a | |
parent | d0225f753274d9a04045a14dfe9a1b1b8aeae371 (diff) | |
download | scummvm-rg350-977a25ec35d63fab0db315b35a69a4a508f587e9.tar.gz scummvm-rg350-977a25ec35d63fab0db315b35a69a4a508f587e9.tar.bz2 scummvm-rg350-977a25ec35d63fab0db315b35a69a4a508f587e9.zip |
XEEN: Implemented resource manager
-rw-r--r-- | engines/xeen/module.mk | 2 | ||||
-rw-r--r-- | engines/xeen/resources.cpp | 214 | ||||
-rw-r--r-- | engines/xeen/resources.h | 64 | ||||
-rw-r--r-- | engines/xeen/xeen.cpp | 4 |
4 files changed, 284 insertions, 0 deletions
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index a33b26a988..d129d10efe 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,7 +1,9 @@ MODULE := engines/xeen MODULE_OBJS := \ + debugger.o \ detection.o \ + resources.o \ xeen.o # This module can be built as a plugin diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp new file mode 100644 index 0000000000..f99be12c3d --- /dev/null +++ b/engines/xeen/resources.cpp @@ -0,0 +1,214 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/archive.h" +#include "common/memstream.h" +#include "common/textconsole.h" +#include "xeen/xeen.h" +#include "xeen/resources.h" + +namespace Xeen { + +/** + * Xeen CC file implementation + */ +class CCArchive : public Common::Archive { +private: + /** + * Details of a single entry in a CC file index + */ + struct CCEntry { + uint16 _id; + uint32 _offset; + uint16 _size; + + CCEntry() : _id(0), _offset(0), _size(0) {} + CCEntry(uint16 id, uint32 offset, uint32 size) + : _id(id), _offset(offset), _size(size) { + } + }; + + Common::Array<CCEntry> _index; + Common::String _filename; + + uint16 convertNameToId(const Common::String &resourceName) const; + + void loadIndex(Common::SeekableReadStream *stream); + + bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; +public: + CCArchive(const Common::String &filename); + virtual ~CCArchive(); + + // Archive implementation + virtual bool hasFile(const Common::String &name) const; + virtual int listMembers(Common::ArchiveMemberList &list) const; + virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + +CCArchive::CCArchive(const Common::String &filename): _filename(filename) { + File f(filename); + loadIndex(&f); +} + +CCArchive::~CCArchive() { +} + +// Archive implementation +bool CCArchive::hasFile(const Common::String &name) const { + CCEntry ccEntry; + return getHeaderEntry(name, ccEntry); +} + +int CCArchive::listMembers(Common::ArchiveMemberList &list) const { + // CC files don't maintain the original filenames, so we can't list it + return 0; +} + +const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { + CCEntry ccEntry; + + if (getHeaderEntry(name, ccEntry)) { + // Open the correct CC file + Common::File f; + if (!f.open(_filename)) + error("Could not open CC file"); + + // Read in the data for the specific resource + f.seek(ccEntry._offset); + byte *data = new byte[ccEntry._size]; + f.read(data, ccEntry._size); + + // Decrypt the data + for (int i = 0; i < ccEntry._size; ++i) + data[i] ^= 0x35; + + // Return the data as a stream + return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); + } + + return nullptr; +} + +/** + * Hash a given filename to produce the Id that represents it + */ +uint16 CCArchive::convertNameToId(const Common::String &resourceName) const { + if (resourceName.empty()) + return 0xffff; + + Common::String name = resourceName; + name.toUppercase(); + + const byte *msgP = (const byte *)name.c_str(); + int total = *msgP++; + for (; *msgP; total += *msgP++) { + // Rotate the bits in 'total' right 7 places + total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7; + } + + return total; +} + +/** + * Load the index of a given CC file + */ +void CCArchive::loadIndex(Common::SeekableReadStream *stream) { + int count = stream->readUint16LE(); + + // Read in the data for the archive's index + byte *rawIndex = new byte[count * 8]; + stream->read(rawIndex, count * 8); + + // Decrypt the index + int ah = 0xac; + for (int i = 0; i < count * 8; ++i) { + rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff); + ah += 0x67; + } + + // Extract the index data into entry structures + _index.reserve(count); + const byte *entryP = &rawIndex[0]; + for (int i = 0; i < count; ++i, entryP += 8) { + CCEntry entry; + entry._id = READ_LE_UINT16(entryP); + entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff; + entry._size = READ_LE_UINT16(entryP + 5); + assert(!entryP[7]); + + _index.push_back(entry); + } + + delete[] rawIndex; +} + +/** +* Given a resource name, returns whether an entry exists, and returns +* the header index data for that entry +*/ +bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { + uint16 id = convertNameToId(resourceName); + + // Loop through the index + for (uint i = 0; i < _index.size(); ++i) { + if (_index[i]._id == id) { + ccEntry = _index[i]; + return true; + } + } + + // Could not find an entry + return false; +} + +/*------------------------------------------------------------------------*/ + +void Resources::init(XeenEngine *vm) { + Common::File f; + + const char *ARCHIVES[3] = { "xeen", "dark", "intro" }; + for (int i = 0; i < 3; ++i) { + Common::String filename = Common::String::format("%s.cc", ARCHIVES[i]); + if (f.exists(filename)) { + SearchMan.add(ARCHIVES[i], new CCArchive(filename)); + } + } +} + +/*------------------------------------------------------------------------*/ + +void File::openFile(const Common::String &filename) { + if (!Common::File::open(filename)) + error("Could not open file - %s", filename.c_str()); +} + +} // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h new file mode 100644 index 0000000000..61b6310874 --- /dev/null +++ b/engines/xeen/resources.h @@ -0,0 +1,64 @@ +/* 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. + * + */ + +#ifndef XEEN_RESOURCES_H +#define XEEN_RESOURCES_H + +#include "common/scummsys.h" +#include "common/file.h" + +namespace Xeen { + +class XeenEngine; + +class Resources { +public: + /** + * Instantiates the resource manager + */ + static void init(XeenEngine *vm); +}; + +/** + * Derived file class + */ +class File : public Common::File { +public: + /** + * Constructor + */ + File() : Common::File() {} + + /** + * Constructor + */ + File(const Common::String &filename) { openFile(filename); } + + /** + * Opens the given file, throwing an error if it can't be opened + */ + void openFile(const Common::String &filename); +}; + +} // End of namespace MADS + +#endif /* MADS_RESOURCES_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 3fe75e10a0..12871fda91 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -28,6 +28,7 @@ #include "graphics/scaler.h" #include "graphics/thumbnail.h" #include "xeen/xeen.h" +#include "xeen/resources.h" namespace Xeen { @@ -49,6 +50,7 @@ void XeenEngine::initialize() { // Create sub-objects of the engine _debugger = new Debugger(this); + Resources::init(this); // Set graphics mode initGraphics(320, 200, false); @@ -204,6 +206,8 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade void XeenEngine::playGame() { // TODO + // Test resource manager + File f("FNT"); } } // End of namespace Xeen |