ScummVM API documentation
datafile.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 #ifndef MEDIASTATION_DATAFILE_H
23 #define MEDIASTATION_DATAFILE_H
24 
25 #include "common/file.h"
26 #include "common/stream.h"
27 #include "common/path.h"
28 #include "common/rect.h"
29 #include "common/str.h"
30 
31 namespace MediaStation {
32 
33 // The version number of this engine,
34 // in the form 4.0r8 (major . minor r revision).
35 struct VersionInfo {
36  uint16 major = 0;
37  uint16 minor = 0;
38  uint16 patch = 0;
39 };
40 
41 // A Media Station datafile consists of one or more RIFF-style "subfiles". Aside
42 // from some oddness at the start of the subfile, each subfile is basically
43 // standard sequence of chunks inside a LIST chunk, like you'd see in any RIFF
44 // file. These chunks have special IDs:
45 // - igod: Indicates a chunk that contains metadata about actor(s) in metadata sections.
46 // - a000, where 000 is a string that represents a 3-digit hexadecimal number.
47 // Indicates a chunk that contains actor data (sounds and bitmaps).
48 
49 enum DatumType {
50  kDatumTypeEmpty = 0x00,
51  kDatumTypeUint8 = 0x02,
52  kDatumTypeUint16 = 0x03,
53  kDatumTypeUint32 = 0x04,
54  kDatumTypeInt8 = 0x05,
55  kDatumTypeInt16 = 0x06,
56  kDatumTypeInt32 = 0x07,
57  kDatumTypeFloat = 0x08,
58  kDatumTypeDouble = 0x09,
59  kDatumTypeFilename = 0x0a,
60  kDatumTypeRect = 0x0d,
61  kDatumTypePoint = 0x0e,
62  kDatumTypeGraphicSize = 0x0f,
63  kDatumTypeGraphicUnit = 0x10,
64  kDatumTypeTime = 0x11,
65  kDatumTypeString = 0x12,
66  kDatumTypeVersion = 0x13,
67  kDatumTypeChannelIdent = 0x1b,
68  kDatumTypePolygon = 0x1d,
69 };
70 
72 public:
73  // Data files are internally little-endian, even on game versions targeting
74  // big-endian systems. The original engine has code for swapping byte order
75  // at runtime when needed. All of these internally assume the data files are
76  // stored little-endian on disk.
77  byte readTypedByte();
78  uint16 readTypedUint16();
79  uint32 readTypedUint32();
80  int8 readTypedSByte();
81  int16 readTypedSint16();
82  int32 readTypedSint32();
83  float readTypedFloat();
84  double readTypedDouble();
85  Common::String readTypedFilename();
86  Common::Rect readTypedRect();
87  Common::Point readTypedPoint();
88  Common::Point readTypedGraphicSize();
89  int16 readTypedGraphicUnit();
90  double readTypedTime();
91  Common::String readTypedString();
92  VersionInfo readTypedVersion();
93  uint32 readTypedChannelIdent();
94 
95 private:
96  void readAndVerifyType(DatumType type);
97 };
98 
99 class Chunk : public ParameterReadStream {
100 public:
101  Chunk() = default;
103 
104  uint32 bytesRemaining();
105  uint32 startPos() const { return _dataStartOffset; }
106 
107  uint32 _id = 0;
108  uint32 _length = 0;
109 
110  // ReadStream implementation
111  virtual bool eos() const { return _parentStream->eos(); };
112  virtual bool err() const { return _parentStream->err(); };
113  virtual void clearErr() { _parentStream->clearErr(); };
114  virtual uint32 read(void *dataPtr, uint32 dataSize);
115  virtual int64 pos() const { return _parentStream->pos(); };
116  virtual int64 size() const { return _parentStream->size(); };
117  virtual bool skip(uint32 offset) { return seek(offset, SEEK_CUR); };
118  virtual bool seek(int64 offset, int whence = SEEK_SET);
119 
120 private:
121  Common::SeekableReadStream *_parentStream = nullptr;
122  uint32 _dataStartOffset = 0;
123  uint32 _dataEndOffset = 0;
124 };
125 
126 class Subfile {
127 public:
128  Subfile() = default;
130 
131  Chunk nextChunk();
132  bool atEnd();
133 
134  Chunk _currentChunk;
135  uint32 _rate;
136 
137 private:
138  Common::SeekableReadStream *_stream = nullptr;
139  Chunk _rootChunk;
140 };
141 
142 // The stream loading class hierarchy presented below is a bit complex for reading directly
143 // from streams, like we can do on modern computers, without needing to worry about
144 // buffering from CD-ROM. But we are staying close to the original logic and class
145 // hierarchy where possible, so some of that original architecture is reflected here.
146 typedef uint32 ChannelIdent;
147 
148 class CdRomStream : public Common::File {
149 public:
150  CdRomStream() {};
151  void openStream(uint streamId);
152  void closeStream() { close(); }
153 
154  Subfile getNextSubfile();
155 
156 private:
157  uint _fileId = 0;
158 };
159 
161 public:
162  virtual ~ChannelClient() {};
163 
164  void setChannelIdent(ChannelIdent channelIdent) { _channelIdent = channelIdent; }
165  ChannelIdent channelIdent() const { return _channelIdent; }
166 
167  virtual void readChunk(Chunk &chunk) {};
168 
169  void registerWithStreamManager();
170  void unregisterWithStreamManager();
171 
172 protected:
173  ChannelIdent _channelIdent = 0;
174 };
175 
176 class StreamFeed {
177 public:
178  StreamFeed(uint streamId) : _id(streamId) {};
179  virtual ~StreamFeed() {};
180 
181  virtual void openFeed(uint streamId, uint startOffset) = 0;
182 
183  // The original also has forceCloseFeed, which doesn't do some other cleanup
184  // that the regular closeFeed does. However, since we are not doing caching and
185  // some other functionality in the original, we don't need this.
186  virtual void closeFeed() = 0;
187  virtual void stopFeed() = 0;
188  virtual void readData() = 0;
189 
190  uint _id = 0;
191 
192 protected:
193  CdRomStream *_stream = nullptr;
194 };
195 
196 class ImtStreamFeed : public StreamFeed {
197 public:
198  ImtStreamFeed(uint streamId);
199  ~ImtStreamFeed();
200 
201  virtual void openFeed(uint streamId, uint startOffset) override;
202  virtual void closeFeed() override;
203  // This implementation is currently empty because all this has to do with read timing.
204  virtual void stopFeed() override {};
205  virtual void readData() override;
206 };
207 
209 public:
211 
212  void registerChannelClient(ChannelClient *client);
213  void unregisterChannelClient(ChannelClient *client);
214  ChannelClient *channelClientForChannel(uint clientId) { return _channelClients.getValOrDefault(clientId); }
215 
216  ImtStreamFeed *openStreamFeed(uint streamId, uint offsetInStream = 0, uint maxBytesToRead = 0);
217  void closeStreamFeed(StreamFeed *streamFeed);
218 
219 private:
222 };
223 
224 } // End of namespace MediaStation
225 
226 #endif
virtual void clearErr()
Definition: datafile.h:113
virtual int64 size() const
Definition: datafile.h:116
Definition: datafile.h:35
Definition: str.h:59
virtual bool eos() const
Definition: datafile.h:111
Definition: actor.h:34
Definition: datafile.h:196
Definition: datafile.h:99
Definition: datafile.h:160
virtual int64 pos() const
Definition: datafile.h:115
Definition: rect.h:524
Definition: datafile.h:148
Definition: stream.h:745
Definition: datafile.h:208
Definition: datafile.h:176
Definition: hashmap.h:85
Definition: file.h:47
virtual bool skip(uint32 offset)
Definition: datafile.h:117
Definition: rect.h:144
Definition: datafile.h:126
virtual bool err() const
Definition: datafile.h:112
Definition: datafile.h:71