ScummVM API documentation
anim_ra1.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 SCUMM_SMUSH_REBEL_ANIM_RA1_H
23 #define SCUMM_SMUSH_REBEL_ANIM_RA1_H
24 
25 #include "common/endian.h"
26 #include "common/stream.h"
27 
28 namespace Scumm {
29 
30 struct RA1AnimChunk {
31  uint32 tag;
32  uint32 size;
33  int64 offset;
34  int64 dataOffset;
35  int64 endOffset;
36  int64 nextOffset;
37  const byte *data;
38 };
39 
41 public:
42  RA1AnimChunkIterator(const byte *data, uint32 size)
43  : _data(data), _offset(0), _endOffset(size) {}
44 
45  RA1AnimChunkIterator(const byte *data, uint32 startOffset, uint32 endOffset)
46  : _data(data), _offset(startOffset), _endOffset(endOffset) {
47  if (_offset > _endOffset)
48  _offset = _endOffset;
49  }
50 
51  bool next(RA1AnimChunk &chunk) {
52  if (_data == nullptr || _offset + 8 > _endOffset)
53  return false;
54 
55  const uint32 size = READ_BE_UINT32(_data + _offset + 4);
56  const uint32 dataOffset = _offset + 8;
57  if (size > _endOffset - dataOffset) {
58  _offset = _endOffset;
59  return false;
60  }
61 
62  chunk.tag = READ_BE_UINT32(_data + _offset);
63  chunk.size = size;
64  chunk.offset = _offset;
65  chunk.dataOffset = dataOffset;
66  chunk.endOffset = dataOffset + size;
67  chunk.nextOffset = chunk.endOffset + (size & 1);
68  if (chunk.nextOffset > _endOffset)
69  chunk.nextOffset = _endOffset;
70  chunk.data = _data + dataOffset;
71 
72  _offset = (uint32)chunk.nextOffset;
73  return true;
74  }
75 
76 private:
77  const byte *_data;
78  uint32 _offset;
79  uint32 _endOffset;
80 };
81 
83 public:
85  : _stream(stream), _endOffset(endOffset) {}
86 
87  bool next(RA1AnimChunk &chunk) {
88  if (_stream.pos() + 8 > _endOffset)
89  return false;
90 
91  const int64 chunkOffset = _stream.pos();
92  const uint32 tag = _stream.readUint32BE();
93  const uint32 size = _stream.readUint32BE();
94  const int64 dataOffset = _stream.pos();
95  const int64 endOffset = dataOffset + size;
96  if (endOffset < dataOffset || endOffset > _endOffset)
97  return false;
98 
99  chunk.tag = tag;
100  chunk.size = size;
101  chunk.offset = chunkOffset;
102  chunk.dataOffset = dataOffset;
103  chunk.endOffset = endOffset;
104  chunk.nextOffset = endOffset + (size & 1);
105  if (chunk.nextOffset > _endOffset)
106  chunk.nextOffset = _endOffset;
107  chunk.data = nullptr;
108  return true;
109  }
110 
111  void skip(const RA1AnimChunk &chunk) {
112  _stream.seek(chunk.nextOffset, SEEK_SET);
113  }
114 
115 private:
117  int64 _endOffset;
118 };
119 
121 public:
122  RA1FrameChunkIterator(Common::SeekableReadStream &stream, int32 &remaining)
123  : _stream(stream), _remaining(remaining) {}
124 
125  bool next(RA1AnimChunk &chunk) {
126  while (_remaining > 1) {
127  if ((_stream.pos() & 1) && _remaining > 0) {
128  const byte pad = _stream.readByte();
129  if (pad == 0) {
130  _remaining--;
131  } else {
132  _stream.seek(-1, SEEK_CUR);
133  }
134  }
135 
136  if (_remaining < 8) {
137  _stream.skip(_remaining);
138  _remaining = 0;
139  return false;
140  }
141 
142  const int64 chunkOffset = _stream.pos();
143  chunk.tag = _stream.readUint32BE();
144  chunk.size = _stream.readUint32BE();
145  chunk.offset = chunkOffset;
146  chunk.dataOffset = _stream.pos();
147  chunk.endOffset = chunk.dataOffset + chunk.size;
148  chunk.nextOffset = chunk.endOffset;
149  chunk.data = nullptr;
150  return true;
151  }
152 
153  if (_remaining == 1) {
154  _stream.skip(1);
155  _remaining = 0;
156  }
157  return false;
158  }
159 
160  bool fits(const RA1AnimChunk &chunk) const {
161  return _remaining >= 8 && chunk.size <= (uint32)(_remaining - 8);
162  }
163 
164  void skip(const RA1AnimChunk &chunk) {
165  const int32 consumed = fits(chunk) ? (int32)chunk.size + 8 : _remaining;
166  _remaining -= consumed;
167  _stream.seek(chunk.endOffset, SEEK_SET);
168  }
169 
170 private:
172  int32 &_remaining;
173 };
174 
175 } // End of namespace Scumm
176 
177 #endif
Definition: anim_ra1.h:30
Definition: stream.h:745
Definition: anim_ra1.h:40
Definition: anim_ra1.h:82
Definition: actor.h:30
Definition: anim_ra1.h:120