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 SHERLOCK_RESOURCES_H
24 #define SHERLOCK_RESOURCES_H
25 
26 #include "common/array.h"
27 #include "common/file.h"
28 #include "common/hashmap.h"
29 #include "common/hash-str.h"
30 #include "common/rect.h"
31 #include "common/str.h"
32 #include "common/str-array.h"
33 #include "common/stream.h"
34 #include "graphics/surface.h"
35 
36 namespace Sherlock {
37 
38 typedef Common::Array<byte> CacheEntry;
39 typedef Common::HashMap<Common::String, CacheEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CacheHash;
40 
41 struct LibraryEntry {
42 	uint32 _offset, _size;
43 	int _index;
44 
LibraryEntryLibraryEntry45 	LibraryEntry() : _index(0), _offset(0), _size(0) {}
LibraryEntryLibraryEntry46 	LibraryEntry(int index, uint32 offset, uint32 size) :
47 		_index(index), _offset(offset), _size(size) {}
48 };
49 typedef Common::HashMap<Common::String, LibraryEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LibraryIndex;
50 typedef Common::HashMap<Common::String, LibraryIndex, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LibraryIndexes;
51 
52 class SherlockEngine;
53 
54 class Cache {
55 private:
56 	SherlockEngine *_vm;
57 	CacheHash _resources;
58 public:
59 	Cache(SherlockEngine *_vm);
60 
61 	/**
62 	 * Returns true if a given file is currently being cached
63 	 */
64 	bool isCached(const Common::String &filename) const;
65 
66 	/**
67 	 * Loads a file into the cache if it's not already present, and returns it.
68 	 * If the file is LZW compressed, automatically decompresses it and loads
69 	 * the uncompressed version into memory
70 	 */
71 	void load(const Common::String &name);
72 
73 	/**
74 	 * Load a cache entry based on a passed stream
75 	 */
76 	void load(const Common::String &name, Common::SeekableReadStream &stream);
77 
78 	/**
79 	 * Get a file from the cache
80 	 */
81 	Common::SeekableReadStream *get(const Common::String &filename) const;
82 };
83 
84 class Resources {
85 private:
86 	SherlockEngine *_vm;
87 	Cache _cache;
88 	LibraryIndexes _indexes;
89 	int _resourceIndex;
90 
91 	/**
92 	 * Reads in the index from a library file, and caches its index for later use
93 	 */
94 	void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream, bool isNewStyle);
95 public:
96 	Resources(SherlockEngine *vm);
97 
98 	/**
99 	 * Adds the specified file to the cache. If it's a library file, takes care of
100 	 * loading its index for future use
101 	 */
102 	void addToCache(const Common::String &filename);
103 
104 	/**
105 	 * Adds a resource from a library file to the cache
106 	 */
107 	void addToCache(const Common::String &filename, const Common::String &libFilename);
108 
109 	/**
110 	 * Adds a given stream to the cache under the given name
111 	 */
112 	void addToCache(const Common::String &filename, Common::SeekableReadStream &stream);
113 
isInCache(const Common::String & filename)114 	bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); }
115 
116 	/**
117 	 * Checks the passed stream, and if is compressed, deletes it and replaces it with its uncompressed data
118 	 */
119 	void decompressIfNecessary(Common::SeekableReadStream *&stream);
120 
121 	/**
122 	 * Returns a stream for a given file
123 	 */
124 	Common::SeekableReadStream *load(const Common::String &filename);
125 
126 	/**
127 	 * Loads a specific resource from a given library file
128 	 */
129 	Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile, bool suppressErrors = false);
130 
131 	/**
132 	 * Returns true if the given file exists on disk or in the cache
133 	 */
134 	bool exists(const Common::String &filename) const;
135 
136 	/**
137 	 * Returns the index of the last loaded resource in its given library file.
138 	 * This will be used primarily when loading talk files, so the engine can
139 	 * update the given conversation number in the journal
140 	 */
141 	int resourceIndex() const;
142 
143 	/**
144 	 * Produces a list of all resource names within a file. Used by the debugger.
145 	 */
146 	void getResourceNames(const Common::String &libraryFile, Common::StringArray &names);
147 
148 	/**
149 	 * Decompresses LZW compressed data
150 	 */
151 	Common::SeekableReadStream *decompress(Common::SeekableReadStream &source);
152 
153 	/**
154 	 * Decompresses LZW compressed data
155 	 */
156 	Common::SeekableReadStream *decompress(Common::SeekableReadStream &source, uint32 outSize);
157 
158 	/**
159 	 * Decompresses LZW compressed data
160 	 */
161 	void decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize);
162 
163 	/**
164 	 * Decompresses LZW compressed data
165 	 */
166 	static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
167 
168 	/**
169 	 * Decompresses LZW compressed data
170 	 */
171 	static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
172 };
173 
174 } // End of namespace Sherlock
175 
176 #endif
177