PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/engines/lastexpress/data/sequence.cpp

http://github.com/scummvm/scummvm
C++ | 481 lines | 328 code | 81 blank | 72 comment | 70 complexity | 9f726bdaef779eed287804e666c0fbd9 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
  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. // Based on Deniz Oezmen's code: http://oezmen.eu/
  23. #include "lastexpress/data/sequence.h"
  24. #include "lastexpress/debug.h"
  25. #include "common/stream.h"
  26. namespace LastExpress {
  27. void FrameInfo::read(Common::SeekableReadStream *in, bool isSequence) {
  28. // Save the current position
  29. int32 basePos = in->pos();
  30. dataOffset = in->readUint32LE();
  31. unknown = in->readUint32LE();
  32. paletteOffset = in->readUint32LE();
  33. xPos1 = in->readUint32LE();
  34. yPos1 = in->readUint32LE();
  35. xPos2 = in->readUint32LE();
  36. yPos2 = in->readUint32LE();
  37. initialSkip = in->readUint32LE();
  38. decompressedEndOffset = in->readUint32LE();
  39. // Read the compression type for NIS files
  40. if (!isSequence) {
  41. in->seek(basePos + 0x124);
  42. } else {
  43. hotspot.left = (int16)in->readUint16LE();
  44. hotspot.right = (int16)in->readUint16LE();
  45. hotspot.top = (int16)in->readUint16LE();
  46. hotspot.bottom = (int16)in->readUint16LE();
  47. }
  48. compressionType = in->readByte();
  49. subType = (FrameSubType)in->readByte();
  50. // Sequence information
  51. field_2E = in->readByte();
  52. keepPreviousFrame = in->readByte();
  53. field_30 = in->readByte();
  54. field_31 = in->readByte();
  55. soundAction = in->readByte();
  56. field_33 = in->readByte();
  57. position = in->readByte();
  58. field_35 = in->readByte();
  59. field_36 = in->readUint16LE();
  60. field_38 = in->readUint32LE();
  61. entityPosition = (EntityPosition)in->readUint16LE();
  62. location = in->readUint16LE();
  63. next = in->readUint32LE();
  64. }
  65. // AnimFrame
  66. AnimFrame::AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f, bool /* ignoreSubtype */) : _palette(NULL) {
  67. _palSize = 1;
  68. // TODO: use just the needed rectangle
  69. _image.create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
  70. //debugC(6, kLastExpressDebugGraphics, " Offsets: data=%d, unknown=%d, palette=%d", f.dataOffset, f.unknown, f.paletteOffset);
  71. //debugC(6, kLastExpressDebugGraphics, " Position: (%d, %d) - (%d, %d)", f.xPos1, f.yPos1, f.xPos2, f.yPos2);
  72. //debugC(6, kLastExpressDebugGraphics, " Initial Skip: %d", f.initialSkip);
  73. //debugC(6, kLastExpressDebugGraphics, " Decompressed end offset: %d", f.decompressedEndOffset);
  74. //debugC(6, kLastExpressDebugGraphics, " Hotspot: (%d, %d) x (%d, %d)\n", f.hotspot.left, f.hotspot.top, f.hotspot.right, f.hotspot.bottom);
  75. //debugC(6, kLastExpressDebugGraphics, " Compression type: %u / %u", f.compressionType, f.subType);
  76. //debugC(6, kLastExpressDebugGraphics, " Unknown: %u - %u - %u - %u - %u - %u - %u - %d", f.field_2E, f.field_2F, f.field_30, f.field_31, f.field_33, f.field_35, f.field_36, f.field_38);
  77. //debugC(6, kLastExpressDebugGraphics, " Sound action: %u", f.soundAction);
  78. //debugC(6, kLastExpressDebugGraphics, " Position: %d", f.position);
  79. //debugC(6, kLastExpressDebugGraphics, " Entity Position: %d", f.entityPosition);
  80. //debugC(6, kLastExpressDebugGraphics, " Location: %d", f.location);
  81. //debugC(6, kLastExpressDebugGraphics, " next: %d", f.next);
  82. switch (f.compressionType) {
  83. case 0:
  84. // Empty frame
  85. break;
  86. case 3:
  87. decomp3(in, f);
  88. break;
  89. case 4:
  90. decomp4(in, f);
  91. break;
  92. case 5:
  93. decomp5(in, f);
  94. break;
  95. case 7:
  96. decomp7(in, f);
  97. break;
  98. case 255:
  99. decompFF(in, f);
  100. break;
  101. default:
  102. error("[AnimFrame::AnimFrame] Unknown frame compression: %d", f.compressionType);
  103. }
  104. readPalette(in, f);
  105. _rect = Common::Rect((int16)f.xPos1, (int16)f.yPos1, (int16)f.xPos2, (int16)f.yPos2);
  106. //_rect.debugPrint(0, "Frame rect:");
  107. }
  108. AnimFrame::~AnimFrame() {
  109. _image.free();
  110. delete[] _palette;
  111. }
  112. Common::Rect AnimFrame::draw(Graphics::Surface *s) {
  113. byte *inp = (byte *)_image.getPixels();
  114. uint16 *outp = (uint16 *)s->getPixels();
  115. for (int i = 0; i < 640 * 480; i++, inp++, outp++) {
  116. if (*inp)
  117. *outp = _palette[*inp];
  118. }
  119. return _rect;
  120. }
  121. void AnimFrame::readPalette(Common::SeekableReadStream *in, const FrameInfo &f) {
  122. // Read the palette
  123. in->seek((int)f.paletteOffset);
  124. _palette = new uint16[_palSize];
  125. for (uint32 i = 0; i < _palSize; i++) {
  126. _palette[i] = in->readUint16LE();
  127. }
  128. }
  129. void AnimFrame::decomp3(Common::SeekableReadStream *in, const FrameInfo &f) {
  130. decomp34(in, f, 0x7, 3);
  131. }
  132. void AnimFrame::decomp4(Common::SeekableReadStream *in, const FrameInfo &f) {
  133. decomp34(in, f, 0xf, 4);
  134. }
  135. void AnimFrame::decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byte mask, byte shift) {
  136. byte *p = (byte *)_image.getPixels();
  137. uint32 skip = f.initialSkip / 2;
  138. uint32 size = f.decompressedEndOffset / 2;
  139. //warning("skip: %d, %d", skip % 640, skip / 640);
  140. //warning("size: %d, %d", size % 640, size / 640);
  141. //assert (f.yPos1 == skip / 640);
  142. //assert (f.yPos2 == size / 640);
  143. uint32 numBlanks = 640 - (f.xPos2 - f.xPos1);
  144. in->seek((int)f.dataOffset);
  145. for (uint32 out = skip; out < size; ) {
  146. uint16 opcode = in->readByte();
  147. if (opcode & 0x80) {
  148. if (opcode & 0x40) {
  149. opcode &= 0x3f;
  150. out += numBlanks + opcode + 1;
  151. } else {
  152. opcode &= 0x3f;
  153. if (opcode & 0x20) {
  154. opcode = ((opcode & 0x1f) << 8) + in->readByte();
  155. if (opcode & 0x1000) {
  156. out += opcode & 0xfff;
  157. continue;
  158. }
  159. }
  160. out += opcode + 2;
  161. }
  162. } else {
  163. byte value = opcode & mask;
  164. opcode >>= shift;
  165. if (_palSize <= value)
  166. _palSize = value + 1;
  167. if (!opcode)
  168. opcode = in->readByte();
  169. for (int i = 0; i < opcode; i++, out++) {
  170. p[out] = value;
  171. }
  172. }
  173. }
  174. }
  175. void AnimFrame::decomp5(Common::SeekableReadStream *in, const FrameInfo &f) {
  176. byte *p = (byte *)_image.getPixels();
  177. uint32 skip = f.initialSkip / 2;
  178. uint32 size = f.decompressedEndOffset / 2;
  179. //warning("skip: %d, %d", skip % 640, skip / 640);
  180. //warning("size: %d, %d", size % 640, size / 640);
  181. //assert (f.yPos1 == skip / 640);
  182. //assert (f.yPos2 == size / 640);
  183. in->seek((int)f.dataOffset);
  184. for (uint32 out = skip; out < size; ) {
  185. uint16 opcode = in->readByte();
  186. if (!(opcode & 0x1f)) {
  187. opcode = (uint16)((opcode << 3) + in->readByte());
  188. if (opcode & 0x400) {
  189. // skip these 10 bits
  190. out += (opcode & 0x3ff);
  191. } else {
  192. out += opcode + 2;
  193. }
  194. } else {
  195. byte value = opcode & 0x1f;
  196. opcode >>= 5;
  197. if (_palSize <= value)
  198. _palSize = value + 1;
  199. if (!opcode)
  200. opcode = in->readByte();
  201. for (int i = 0; i < opcode; i++, out++) {
  202. p[out] = value;
  203. }
  204. }
  205. }
  206. }
  207. void AnimFrame::decomp7(Common::SeekableReadStream *in, const FrameInfo &f) {
  208. byte *p = (byte *)_image.getPixels();
  209. uint32 skip = f.initialSkip / 2;
  210. uint32 size = f.decompressedEndOffset / 2;
  211. //warning("skip: %d, %d", skip % 640, skip / 640);
  212. //warning("size: %d, %d", size % 640, size / 640);
  213. //assert (f.yPos1 == skip / 640);
  214. //assert (f.yPos2 == size / 640);
  215. uint32 numBlanks = 640 - (f.xPos2 - f.xPos1);
  216. in->seek((int)f.dataOffset);
  217. for (uint32 out = skip; out < size; ) {
  218. uint16 opcode = in->readByte();
  219. if (opcode & 0x80) {
  220. if (opcode & 0x40) {
  221. if (opcode & 0x20) {
  222. opcode &= 0x1f;
  223. out += numBlanks + opcode + 1;
  224. } else {
  225. opcode &= 0x1f;
  226. if (opcode & 0x10) {
  227. opcode = ((opcode & 0xf) << 8) + in->readByte();
  228. if (opcode & 0x800) {
  229. // skip these 11 bits
  230. out += (opcode & 0x7ff);
  231. continue;
  232. }
  233. }
  234. // skip these 4 bits
  235. out += opcode + 2;
  236. }
  237. } else {
  238. opcode &= 0x3f;
  239. byte value = in->readByte();
  240. if (_palSize <= value)
  241. _palSize = value + 1;
  242. for (int i = 0; i < opcode; i++, out++) {
  243. p[out] = value;
  244. }
  245. }
  246. } else {
  247. if (_palSize <= opcode)
  248. _palSize = opcode + 1;
  249. // set the given value
  250. p[out] = (byte)opcode;
  251. out++;
  252. }
  253. }
  254. }
  255. void AnimFrame::decompFF(Common::SeekableReadStream *in, const FrameInfo &f) {
  256. byte *p = (byte *)_image.getPixels();
  257. uint32 skip = f.initialSkip / 2;
  258. uint32 size = f.decompressedEndOffset / 2;
  259. in->seek((int)f.dataOffset);
  260. for (uint32 out = skip; out < size; ) {
  261. uint16 opcode = in->readByte();
  262. if (opcode < 0x80) {
  263. if (_palSize <= opcode)
  264. _palSize = opcode + 1;
  265. // set the given value
  266. p[out] = (byte)opcode;
  267. out++;
  268. } else {
  269. if (opcode < 0xf0) {
  270. if (opcode < 0xe0) {
  271. // copy old part
  272. uint32 old = out + ((opcode & 0x7) << 8) + in->readByte() - 2048;
  273. opcode = ((opcode >> 3) & 0xf) + 3;
  274. for (int i = 0; i < opcode; i++, out++, old++) {
  275. p[out] = p[old];
  276. }
  277. } else {
  278. opcode = (opcode & 0xf) + 1;
  279. byte value = in->readByte();
  280. if (_palSize <= value)
  281. _palSize = value + 1;
  282. for (int i = 0; i < opcode; i++, out++) {
  283. p[out] = value;
  284. }
  285. }
  286. } else {
  287. out += ((opcode & 0xf) << 8) + in->readByte();
  288. }
  289. }
  290. }
  291. }
  292. //////////////////////////////////////////////////////////////////////////
  293. // SEQUENCE
  294. //////////////////////////////////////////////////////////////////////////
  295. Sequence::~Sequence() {
  296. reset();
  297. }
  298. void Sequence::reset() {
  299. _frames.clear();
  300. delete _stream;
  301. _stream = NULL;
  302. }
  303. Sequence *Sequence::load(Common::String name, Common::SeekableReadStream *stream, byte field30) {
  304. Sequence *sequence = new Sequence(name);
  305. if (!sequence->load(stream, field30)) {
  306. delete sequence;
  307. return NULL;
  308. }
  309. return sequence;
  310. }
  311. bool Sequence::load(Common::SeekableReadStream *stream, byte field30) {
  312. if (!stream)
  313. return false;
  314. // Reset data
  315. reset();
  316. _field30 = field30;
  317. // Keep stream for later decoding of sequence
  318. _stream = stream;
  319. // Read header to get the number of frames
  320. _stream->seek(0);
  321. uint32 numframes = _stream->readUint32LE();
  322. uint32 unknown = _stream->readUint32LE();
  323. debugC(3, kLastExpressDebugGraphics, "Number of frames in sequence: %d / unknown=0x%x", numframes, unknown);
  324. // Store frames information
  325. for (uint i = 0; i < numframes; i++) {
  326. // Move stream to start of frame
  327. _stream->seek((int32)(_sequenceHeaderSize + i * _sequenceFrameSize), SEEK_SET);
  328. if (_stream->eos())
  329. error("[Sequence::load] Couldn't seek to the current frame data");
  330. // Check if there is enough data
  331. if ((unsigned)(_stream->size() - _stream->pos()) < _sequenceFrameSize)
  332. error("[Sequence::load] The sequence frame does not have a valid header");
  333. FrameInfo info;
  334. info.read(_stream, true);
  335. _frames.push_back(info);
  336. }
  337. _isLoaded = true;
  338. return true;
  339. }
  340. FrameInfo *Sequence::getFrameInfo(uint16 index) {
  341. if (_frames.size() == 0)
  342. error("[Sequence::getFrameInfo] Trying to decode a sequence before loading its data");
  343. if (index > _frames.size() - 1)
  344. error("[Sequence::getFrameInfo] Invalid sequence frame requested: %d, max %d", index, _frames.size() - 1);
  345. return &_frames[index];
  346. }
  347. AnimFrame *Sequence::getFrame(uint16 index) {
  348. FrameInfo *frame = getFrameInfo(index);
  349. if (!frame)
  350. return NULL;
  351. // Skip "invalid" frames
  352. if (frame->compressionType == 0)
  353. return NULL;
  354. debugC(9, kLastExpressDebugGraphics, "Decoding sequence %s: frame %d / %d", _name.c_str(), index, _frames.size() - 1);
  355. return new AnimFrame(_stream, *frame);
  356. }
  357. //////////////////////////////////////////////////////////////////////////
  358. // SequenceFrame
  359. SequenceFrame::~SequenceFrame() {
  360. if (_dispose && _sequence) {
  361. delete _sequence;
  362. }
  363. _sequence = NULL;
  364. }
  365. Common::Rect SequenceFrame::draw(Graphics::Surface *surface) {
  366. if (!_sequence || _frame >= _sequence->count())
  367. return Common::Rect();
  368. AnimFrame *f = _sequence->getFrame(_frame);
  369. if (!f)
  370. return Common::Rect();
  371. Common::Rect rect = f->draw(surface);
  372. delete f;
  373. return rect;
  374. }
  375. bool SequenceFrame::setFrame(uint16 frame) {
  376. if (!_sequence)
  377. return false;
  378. if (frame < _sequence->count()) {
  379. _frame = frame;
  380. return true;
  381. } else
  382. return false;
  383. }
  384. bool SequenceFrame::nextFrame() {
  385. return setFrame(_frame + 1);
  386. }
  387. FrameInfo *SequenceFrame::getInfo() {
  388. if (!_sequence)
  389. error("[SequenceFrame::getInfo] Invalid sequence");
  390. return _sequence->getFrameInfo(_frame);
  391. }
  392. Common::String SequenceFrame::getName() {
  393. if (!_sequence)
  394. error("[SequenceFrame::getName] Invalid sequence");
  395. return _sequence->getName();
  396. }
  397. bool SequenceFrame::equal(const SequenceFrame *other) const {
  398. return _sequence->getName() == other->_sequence->getName() && _frame == other->_frame;
  399. }
  400. } // End of namespace LastExpress