1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef GNAP_RESOURCE_H 24 #define GNAP_RESOURCE_H 25 26 #include "common/array.h" 27 #include "common/events.h" 28 #include "common/file.h" 29 #include "common/memstream.h" 30 #include "common/str.h" 31 #include "common/stream.h" 32 #include "common/substream.h" 33 #include "common/system.h" 34 35 #include "graphics/surface.h" 36 37 #include "gnap/datarchive.h" 38 39 namespace Gnap { 40 41 enum { 42 kResTypeSprite = 0, 43 kResTypeBitmap = 1, 44 kResTypeSound = 2, 45 kResTypeSequence = 3 46 }; 47 48 struct SequenceFrame { 49 int16 _duration; 50 bool _isScaled; 51 Common::Rect _rect; 52 int32 _spriteId; 53 int32 _soundId; 54 void loadFromStream(Common::MemoryReadStream &stream); 55 }; 56 57 struct SequenceAnimation { 58 int32 _additionalDelay; 59 int16 _framesCount; 60 int16 _maxTotalDuration; 61 SequenceFrame *frames; 62 SequenceAnimationSequenceAnimation63 SequenceAnimation() : frames(nullptr), _additionalDelay(0), _framesCount(0), _maxTotalDuration(0) {} ~SequenceAnimationSequenceAnimation64 ~SequenceAnimation() { delete[] frames; } 65 void loadFromStream(Common::MemoryReadStream &stream); 66 }; 67 68 class SequenceResource { 69 public: 70 SequenceResource(byte *data, uint32 size); 71 ~SequenceResource(); 72 public: 73 int32 _sequenceId; 74 int32 _defaultId; 75 int32 _sequenceId2; 76 uint32 _defaultId2; 77 uint32 _flags; 78 int32 _totalDuration; 79 int16 _xOffs; 80 int16 _yOffs; 81 int32 _animationsCount; 82 SequenceAnimation *_animations; 83 }; 84 85 class SpriteResource { 86 public: 87 SpriteResource(byte *data, uint32 size); 88 ~SpriteResource(); 89 public: 90 byte *_data; 91 byte *_pixels; 92 uint32 *_palette; 93 int16 _width, _height; 94 uint16 _unknownVal1; 95 uint16 _unknownVal2; 96 bool _transparent; 97 uint16 _colorsCount; 98 }; 99 100 class SoundResource { 101 public: 102 SoundResource(byte *data, uint32 size); 103 ~SoundResource(); 104 public: 105 byte *_data; 106 uint32 _size; 107 }; 108 109 template <class ResourceClass, int ResourceType, bool FreeAfterLoad> 110 class ResourceCacheTemplate { 111 public: 112 ResourceCacheTemplate(DatManager * dat)113 ResourceCacheTemplate(DatManager *dat) : _dat(dat) { 114 } 115 ~ResourceCacheTemplate()116 ~ResourceCacheTemplate() { 117 } 118 get(int resourceId)119 ResourceClass *get(int resourceId) { 120 Resource *resource = find(resourceId); 121 if (!resource) { 122 debug(9, "Loading resource type %d with ID %08X from disk", ResourceType, resourceId); 123 resource = new Resource(load(resourceId)); 124 _cache[resourceId] = resource; 125 } else { 126 debug(9, "Resource type %d with ID %08X was in cache", ResourceType, resourceId); 127 } 128 resource->_isLocked = true; 129 return resource->_obj; 130 } 131 release(int resourceId)132 void release(int resourceId) { 133 Resource *resource = find(resourceId); 134 if (resource) 135 resource->_isLocked = false; 136 } 137 138 void purge(bool force = false) { 139 for (CacheMapIterator it = _cache.begin(); it != _cache.end(); ++it) { 140 Resource *resource = it->_value; 141 if (force || !resource->_isLocked) { 142 delete resource; 143 _cache.erase(it); 144 } 145 } 146 } 147 148 protected: 149 150 struct Resource { 151 ResourceClass *_obj; 152 bool _isLocked; ResourceResource153 Resource(ResourceClass *obj) : _obj(obj), _isLocked(false) {} ~ResourceResource154 ~Resource() { delete _obj; } 155 }; 156 157 typedef Common::HashMap<int, Resource *> CacheMap; 158 typedef typename CacheMap::iterator CacheMapIterator; 159 160 DatManager *_dat; 161 CacheMap _cache; 162 find(int resourceId)163 Resource *find(int resourceId) { 164 CacheMapIterator it = _cache.find(resourceId); 165 if (it != _cache.end()) 166 return it->_value; 167 return nullptr; 168 } 169 load(int resourceId)170 ResourceClass *load(int resourceId) { 171 if (_dat->getResourceType(resourceId) != ResourceType) 172 error("ResourceCache::load() Wrong resource type: Expected %d, got %d", ResourceType, _dat->getResourceType(resourceId)); 173 174 byte *resourceData = _dat->loadResource(resourceId); 175 uint32 resourceSize = _dat->getResourceSize(resourceId); 176 ResourceClass *obj = new ResourceClass(resourceData, resourceSize); 177 if (FreeAfterLoad) 178 delete[] resourceData; 179 return obj; 180 } 181 182 }; 183 184 typedef ResourceCacheTemplate<SpriteResource, kResTypeSprite, false> SpriteCache; 185 typedef ResourceCacheTemplate<SoundResource, kResTypeSound, false> SoundCache; 186 typedef ResourceCacheTemplate<SequenceResource, kResTypeSequence, true> SequenceCache; 187 188 } // End of namespace Gnap 189 190 #endif // GNAP_RESOURCE_H 191