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
28namespace Scumm {
29
31 uint32 tag;
32 uint32 size;
33 int64 offset;
34 int64 dataOffset;
35 int64 endOffset;
36 int64 nextOffset;
37 const byte *data;
38};
39
41public:
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
76private:
77 const byte *_data;
78 uint32 _offset;
79 uint32 _endOffset;
80};
81
83public:
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
115private:
117 int64 _endOffset;
118};
119
121public:
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
170private:
172 int32 &_remaining;
173};
174
175} // End of namespace Scumm
176
177#endif
uint32 readUint32BE()
Definition: stream.h:515
byte readByte()
Definition: stream.h:434
Definition: stream.h:745
virtual int64 pos() const =0
virtual bool skip(uint32 offset)
Definition: stream.h:793
virtual bool seek(int64 offset, int whence=SEEK_SET)=0
Definition: anim_ra1.h:40
Definition: anim_ra1.h:82
Definition: anim_ra1.h:120
Definition: actor.h:30
Definition: anim_ra1.h:30