/* 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 3 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, see . * */ #include "ultima/shared/engine/resources.h" #include "ultima/shared/early/font_resources.h" #include "common/endian.h" #ifndef RELEASE_BUILD #include "ultima/ultima1/core/resources.h" #endif namespace Ultima { namespace Shared { /*-------------------------------------------------------------------*/ bool Resources::open() { // Save locally constructred resources to the archive manager for access Shared::FontResources sharedFonts(this); sharedFonts.save(); #ifndef RELEASE_BUILD Ultima1::GameResources u1Data(this); u1Data.save(); #endif return true; } void Resources::addResource(const Common::Path &name, const byte *data, size_t size) { // Add a new entry to the local resources list for the passed data _localResources.push_back(LocalResource()); LocalResource &lr = _localResources[_localResources.size() - 1]; lr._name = name; lr._data.resize(size); Common::copy(data, data + size, &lr._data[0]); } bool Resources::hasFile(const Common::Path &path) const { for (uint idx = 0; idx < _localResources.size(); ++idx) if (_localResources[idx]._name.equalsIgnoreCase(path)) return true; return false; } int Resources::listMembers(Common::ArchiveMemberList &list) const { for (uint idx = 0; idx < _localResources.size(); ++idx) { list.push_back(Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_localResources[idx]._name, *this))); } return _localResources.size(); } const Common::ArchiveMemberPtr Resources::getMember(const Common::Path &path) const { if (!hasFile(path)) return Common::ArchiveMemberPtr(); return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this)); } Common::SeekableReadStream *Resources::createReadStreamForMember(const Common::Path &path) const { for (uint idx = 0; idx < _localResources.size(); ++idx) { const LocalResource &lr = _localResources[idx]; if (lr._name.equalsIgnoreCase(path)) return new Common::MemoryReadStream(&lr._data[0], lr._data.size()); } return nullptr; } /*-------------------------------------------------------------------*/ void Resources::FileResource::load(File &f) { _name = f.readString(); _offset = f.readUint32LE(); _size = f.readUint16LE(); } /*-------------------------------------------------------------------*/ ResourceFile::ResourceFile(const Common::Path &filename) : _filename(filename), _bufferP(_buffer) { Common::fill(_buffer, _buffer + STRING_BUFFER_SIZE, 0); } void ResourceFile::load() { _file.open(_filename); synchronize(); _file.close(); } void ResourceFile::syncString(const char *&str) { str = _bufferP; do { *_bufferP = _file.readByte(); } while (*_bufferP++); assert(_bufferP < (_buffer + STRING_BUFFER_SIZE)); } void ResourceFile::syncStrings(const char **str, size_t count) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count, 0, 0, 0)); for (size_t idx = 0; idx < count; ++idx) syncString(str[idx]); } void ResourceFile::syncStrings2D(const char **str, size_t count1, size_t count2) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count1, count2, 0, 0)); for (size_t idx = 0; idx < count1 * count2; ++idx) syncString(str[idx]); } void ResourceFile::syncNumber(int &val) { val = _file.readSint32LE(); } void ResourceFile::syncNumbers(int *vals, size_t count) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count, 0, 0, 0)); for (size_t idx = 0; idx < count; ++idx) vals[idx] = _file.readSint32LE(); } void ResourceFile::syncNumbers2D(int *vals, size_t count1, size_t count2) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count1, count2, 0, 0)); for (size_t idx = 0; idx < count1 * count2; ++idx) vals[idx] = _file.readSint32LE(); } void ResourceFile::syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count1, count2, count3, 0)); for (size_t idx = 0; idx < count1 * count2 * count3; ++idx) vals[idx] = _file.readSint32LE(); } void ResourceFile::syncBytes(byte *vals, size_t count) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count, 0, 0, 0)); _file.read(vals, count); } void ResourceFile::syncBytes2D(byte *vals, size_t count1, size_t count2) { uint tag = _file.readUint32LE(); assert(tag == MKTAG(count1, count2, 0, 0)); _file.read(vals, count1 * count2); } /*-------------------------------------------------------------------*/ void LocalResourceFile::save() { synchronize(); _file.finalize(); _owner->addResource(_filename, _file.getData(), _file.size()); } void LocalResourceFile::syncString(const char *&str) { if (!_owner) { ResourceFile::syncString(str); } else { _file.writeString(str); _file.writeByte('\0'); } } void LocalResourceFile::syncStrings(const char **str, size_t count) { if (!_owner) { ResourceFile::syncStrings(str, count); } else { _file.writeUint32LE(MKTAG(count, 0, 0, 0)); for (size_t idx = 0; idx < count; ++idx) syncString(str[idx]); } } void LocalResourceFile::syncStrings2D(const char **str, size_t count1, size_t count2) { if (!_owner) { ResourceFile::syncStrings2D(str, count1, count2); } else { _file.writeUint32LE(MKTAG(count1, count2, 0, 0)); for (size_t idx = 0; idx < count1 * count2; ++idx) syncString(str[idx]); } } void LocalResourceFile::syncNumber(int &val) { if (!_owner) ResourceFile::syncNumber(val); else _file.writeUint32LE(val); } void LocalResourceFile::syncNumbers(int *vals, size_t count) { if (!_owner) { ResourceFile::syncNumbers(vals, count); } else { _file.writeUint32LE(MKTAG(count, 0, 0, 0)); for (size_t idx = 0; idx < count; ++idx) _file.writeUint32LE(vals[idx]); } } void LocalResourceFile::syncNumbers2D(int *vals, size_t count1, size_t count2) { if (!_owner) { ResourceFile::syncNumbers2D(vals, count1, count2); } else { _file.writeUint32LE(MKTAG(count1, count2, 0, 0)); for (size_t idx = 0; idx < count1 * count2; ++idx) _file.writeUint32LE(vals[idx]); } } void LocalResourceFile::syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) { if (!_owner) { ResourceFile::syncNumbers3D(vals, count1, count2, count3); } else { _file.writeUint32LE(MKTAG(count1, count2, count3, 0)); for (size_t idx = 0; idx < count1 * count2 * count3; ++idx) _file.writeUint32LE(vals[idx]); } } void LocalResourceFile::syncBytes(byte *vals, size_t count) { if (!_owner) { ResourceFile::syncBytes(vals, count); } else { _file.writeUint32LE(MKTAG(count, 0, 0, 0)); _file.write(vals, count); } } void LocalResourceFile::syncBytes2D(byte *vals, size_t count1, size_t count2) { if (!_owner) { ResourceFile::syncBytes2D(vals, count1, count2); } else { _file.writeUint32LE(MKTAG(count1, count2, 0, 0)); _file.write(vals, count1 * count2); } } } // End of namespace Shared } // End of namespace Ultima