ScummVM API documentation
resource.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 // RSC Resource file management header file
23 
24 #ifndef SAGA_RESOURCE_H
25 #define SAGA_RESOURCE_H
26 
27 #include "common/array.h"
28 #include "common/file.h"
29 #include "common/list.h"
30 #include "common/macresman.h"
31 
32 namespace Saga {
33 
34 #define RSC_TABLEINFO_SIZE 8
35 #define RSC_TABLEENTRY_SIZE 8
36 
37 #define RSC_MIN_FILESIZE (RSC_TABLEINFO_SIZE + RSC_TABLEENTRY_SIZE + 1)
38 
39 class SagaEngine;
40 class ByteArray;
41 
42 class PatchData {
43 private:
44  Common::SeekableReadStream *_patchFile;
45  const char *_fileName;
46  bool _deletePatchFile;
47  bool _patchFileOpened;
48 
49 public:
50  PatchData(const char *fileName): _fileName(fileName), _deletePatchFile(true), _patchFile(nullptr), _patchFileOpened(false) {
51  }
52  PatchData(Common::SeekableReadStream *patchFile, const char *fileName): _patchFile(patchFile), _fileName(fileName), _deletePatchFile(false), _patchFileOpened(true) {
53  }
54 
55  Common::SeekableReadStream *getStream() {
56  if (_patchFileOpened)
57  return _patchFile;
58 
59  Common::File *file = new Common::File();
60  _patchFileOpened = true;
61  if (!file->open(_fileName)) {
62  _patchFile = nullptr;
63  delete file;
64  return nullptr;
65  }
66  _patchFile = file;
67  return _patchFile;
68  }
69 
70  void closeStream() {
71  if (_deletePatchFile && _patchFileOpened) {
72  delete _patchFile;
73  _patchFile = nullptr;
74  _patchFileOpened = false;
75  }
76  }
77 
78  ~PatchData() {
79  if (_deletePatchFile) {
80  delete _patchFile;
81  }
82  }
83 };
84 
85 struct ResourceData {
86  size_t offset;
87  size_t size;
88  int diskNum; // -1 = without disk id. -2 = mac res fork
89  PatchData *patchData;
90 
91  ResourceData() :
92  offset(0), size(0), patchData(NULL), diskNum(-1) {
93  }
94 
95  ~ResourceData() {
96  if (patchData) {
97  delete patchData;
98  patchData = NULL;
99  }
100  }
101 };
102 
104 
106 friend class Resource;
107 public:
108 
109  ResourceContext():
110  _fileName(NULL), _fileType(0), _isCompressed(false), _serial(0),
111  _isBigEndian(false),
112  _fileSize(0), _tombstone(false) {
113  }
114 
115  virtual ~ResourceContext() { }
116 
117  bool isCompressed() const { return _isCompressed; }
118  uint16 fileType() const { return _fileType; }
119  int32 fileSize() const { return _fileSize; }
120  int serial() const { return _serial; }
121  bool isBigEndian() const { return _isBigEndian; }
122  const char * fileName() const { return _fileName; }
123 
124  Common::SeekableReadStream *getFile(ResourceData *resourceData) {
125  if (resourceData && resourceData->patchData != NULL) {
126  return resourceData->patchData->getStream();
127  } else {
128  if (!_file && !_tombstone)
129  _file.reset(Common::MacResManager::openFileOrDataFork(_fileName));
130  if (!_file)
131  _tombstone = true;
132 
133  return _file.get();
134  }
135  }
136 
137  bool validResourceId(uint32 resourceId) const {
138  return (resourceId < _table.size());
139  }
140 
141  ResourceData *getResourceData(uint32 resourceId) {
142  if (resourceId >= _table.size()) {
143  error("ResourceContext::getResourceData() wrong resourceId %d", resourceId);
144  }
145  return &_table[resourceId];
146  }
147 
148  void closeFile() {
149  _file.reset();
150  }
151 
152 protected:
153  const char *_fileName;
154  uint16 _fileType;
155  bool _isCompressed;
156  int _serial; // IHNM speech files
157 
158  bool _isBigEndian;
159  ResourceDataArray _table;
162  int32 _fileSize;
163  bool _tombstone;
164 
165  bool load(SagaEngine *_vm, Resource *resource);
166  bool loadResV1();
167  bool loadResIteAmiga(SagaEngine *_vm, int type, bool isFloppy);
168  bool loadResIteAmigaSound(SagaEngine *_vm, int type);
169 
170  virtual bool loadRes(SagaEngine *_vm, int type) = 0;
171  virtual void processPatches(Resource *resource, const GamePatchDescription *patchFiles) { }
172 };
173 
175 
176 struct MetaResource {
177  int16 sceneIndex;
178  int16 objectCount;
179  int32 objectsStringsResourceID;
180  int32 inventorySpritesID;
181  int32 mainSpritesID;
182  int32 objectsResourceID;
183  int16 actorCount;
184  int32 actorsStringsResourceID;
185  int32 actorsResourceID;
186  int32 protagFaceSpritesID;
187  int32 field_22;
188  int16 field_26;
189  int16 protagStatesCount;
190  int32 protagStatesResourceID;
191  int32 cutawayListResourceID;
192  int32 songTableID;
193 
194  MetaResource() {
195  memset(this, 0, sizeof(*this));
196  }
197 };
198 
199 class Resource {
200 public:
201  Resource(SagaEngine *vm);
202  virtual ~Resource();
203  bool createContexts();
204  void clearContexts();
205  void loadResource(ResourceContext *context, uint32 resourceId, ByteArray &resourceBuffer);
206 
207  virtual uint32 convertResourceId(uint32 resourceId) = 0;
208  virtual void loadGlobalResources(int chapter, int actorsEntrance) = 0;
209 
210  ResourceContext *getContext(uint16 fileType, int serial = 0);
211  virtual MetaResource* getMetaResource() = 0;
212 protected:
213  SagaEngine *_vm;
214  ResourceContextList _contexts;
215  char _voicesFileName[8][256];
216  char _musicFileName[256];
217  char _soundFileName[256];
218 
219  void addContext(const char *fileName, uint16 fileType, bool isCompressed = false, int serial = 0);
220  virtual ResourceContext *createContext() = 0;
221 };
222 
223 // ITE
225 protected:
226  bool loadRes(SagaEngine *_vm, int type) override {
227  return loadResV1();
228  }
229  void processPatches(Resource *resource, const GamePatchDescription *patchFiles) override;
230 };
231 
233 public:
234  ResourceContext_RSC_ITE_Amiga(bool isFloppy) : _isFloppy(isFloppy) {}
235 
236 protected:
237  bool loadRes(SagaEngine *_vm, int type) override {
238  return loadResIteAmiga(_vm, type, _isFloppy);
239  }
240 
241  bool _isFloppy;
242 };
243 
244 class Resource_RSC : public Resource {
245 public:
246  Resource_RSC(SagaEngine *vm) : Resource(vm) {}
247  uint32 convertResourceId(uint32 resourceId) override {
248  return _vm->isMacResources() ? resourceId - 2 : resourceId;
249  }
250  void loadGlobalResources(int chapter, int actorsEntrance) override {}
251  MetaResource* getMetaResource() override {
252  MetaResource *dummy = 0;
253  return dummy;
254  }
255 protected:
256  ResourceContext *createContext() override {
257  if (_vm->getPlatform() == Common::kPlatformAmiga && _vm->getGameId() == GID_ITE) {
258  return new ResourceContext_RSC_ITE_Amiga(_vm->getFeatures() & GF_ITE_FLOPPY);
259  }
260  return new ResourceContext_RSC();
261  }
262 };
263 
264 #ifdef ENABLE_IHNM
265 // IHNM
266 class ResourceContext_RES: public ResourceContext {
267 protected:
268  bool loadRes(SagaEngine *_vm, int type) override {
269  return loadResV1();
270  }
271 
272  void processPatches(Resource *resource, const GamePatchDescription *patchFiles) override;
273 };
274 
275 // TODO: move load routines from sndres
276 class VoiceResourceContext_RES: public ResourceContext {
277 protected:
278  bool loadRes(SagaEngine *_vm, int type) override {
279  return false;
280  }
281 public:
282  VoiceResourceContext_RES() : ResourceContext() {
283  _fileType = GAME_VOICEFILE;
284  _isBigEndian = true;
285  }
286 };
287 
288 class Resource_RES : public Resource {
289 public:
290  Resource_RES(SagaEngine *vm) : Resource(vm) {}
291  uint32 convertResourceId(uint32 resourceId) override { return resourceId; }
292  void loadGlobalResources(int chapter, int actorsEntrance) override;
293  MetaResource* getMetaResource() override { return &_metaResource; }
294 protected:
295  ResourceContext *createContext() override {
296  return new ResourceContext_RES();
297  }
298 private:
299  MetaResource _metaResource;
300 };
301 #endif
302 
303 } // End of namespace Saga
304 
305 #endif
Definition: resource.h:105
Definition: resource.h:244
Definition: saga.h:497
virtual bool open(const Path &filename)
Definition: stream.h:745
Definition: saga.h:464
Definition: resource.h:232
Definition: resource.h:199
Definition: actor.h:34
Definition: file.h:47
Definition: resource.h:85
Definition: resource.h:224
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: resource.h:176
Definition: resource.h:42
Definition: saga.h:295
static SeekableReadStream * openFileOrDataFork(const Path &fileName, Archive &archive)