/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #ifndef LASTEXPRESS_SEQUENCE_H #define LASTEXPRESS_SEQUENCE_H /* Sequence format (.SEQ / .NIS (frame header & data only)) uint32 {4} - Number of frames in sequence uint32 {4} - Unknown frames headers (68 bytes): // for each frame uint32 {4} - Data offset (from beginning of file) uint32 {4} - Unknown uint32 {4} - Palette offset (from beginning of file) uint32 {4} - Top-left X coordinate uint32 {4} - Top-left Y coordinate uint32 {4} - Bottom-right X coordinate uint32 {4} - Bottom-right Y coordinate uint32 {4} - Initial offset of decompressed data (doubled, since each pixel occupies one color word) uint32 {4} - End of data after decompression (for SEQ files only) uint16 {2} - Hotspot left uint16 {2} - Hotspot right uint16 {2} - Hotspot top uint16 {2} - Hotspot bottom byte {1} - Compression type byte {1} - Subtype (determines which set of decompression functions will be called) => 0, 1, 2, 3 byte {1} - Unknown byte {1} - Unknown uint16 {2} - Unknown byte {1} - Sound action byte {1} - Unknown uint32 {4} - positionId uint32 {4} - Unknown uint16 {2} - Entity Position uint16 {2} - Location (~z-order) uint32 {4} - Next sequence in the linked list (for NIS files: found at 0x124) byte {1} - Compression type palette data: uint16 {x} - palette data (max size: 256) data byte {x} - compressed image data */ #include "lastexpress/drawable.h" #include "lastexpress/shared.h" #include "common/array.h" #include "common/rect.h" #include "common/str.h" namespace Common { class SeekableReadStream; } namespace LastExpress { enum FrameSubType { kFrameTypeNone = 0, kFrameType1 = 1, kFrameType2 = 2, kFrameType3 = 3 }; struct FrameInfo { void read(Common::SeekableReadStream *in, bool isSequence); uint32 dataOffset; ///< Data offset (from beginning of file) uint32 unknown; ///< FIXME: unknown data uint32 paletteOffset; ///< Palette offset (from beginning of file) uint32 xPos1; ///< Top-left X coordinate uint32 yPos1; ///< Top-left Y coordinate uint32 xPos2; ///< Bottom-right X coordinate uint32 yPos2; ///< Bottom-right Y coordinate uint32 initialSkip; ///< Initial on-screen offset of decompressed data (doubled, since each pixel occupies one color word) uint32 decompressedEndOffset; ///< End of data after decompression // NIS frame headers end here. SEQ frame headers have additional 32 bytes of // data, notably the compression type at the position outlined above in // CompPos_SEQ Common::Rect hotspot; byte compressionType; ///< Type of frame compression (0x03, 0x04, 0x05, 0x07, 0xFF) FrameSubType subType; ///< Subtype (byte) byte field_2E; byte keepPreviousFrame; byte field_30; byte field_31; byte soundAction; byte field_33; Position position; byte field_35; int16 field_36; uint32 field_38; EntityPosition entityPosition; uint16 location; uint32 next; }; class AnimFrame : public Drawable { public: AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f); ~AnimFrame(); Common::Rect draw(Graphics::Surface *s); private: void decomp3(Common::SeekableReadStream *in, const FrameInfo &f); void decomp4(Common::SeekableReadStream *in, const FrameInfo &f); void decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byte mask, byte shift); void decomp5(Common::SeekableReadStream *in, const FrameInfo &f); void decomp7(Common::SeekableReadStream *in, const FrameInfo &f); void decompFF(Common::SeekableReadStream *in, const FrameInfo &f); void readPalette(Common::SeekableReadStream *in, const FrameInfo &f); Graphics::Surface _image; uint16 _palSize; uint16 *_palette; Common::Rect _rect; }; class Sequence { public: Sequence(Common::String name) : _stream(NULL), _isLoaded(false), _name(name), _field30(15) {} ~Sequence(); static Sequence *load(Common::String name, Common::SeekableReadStream *stream = NULL, byte field30 = 15); bool load(Common::SeekableReadStream *stream, byte field30 = 15); uint16 count() const { return (uint16)_frames.size(); } AnimFrame *getFrame(uint16 index = 0); FrameInfo *getFrameInfo(uint16 index = 0); Common::String getName() { return _name; } byte getField30() { return _field30; } bool isLoaded() { return _isLoaded; } private: static const uint32 _sequenceHeaderSize = 8; static const uint32 _sequenceFrameSize = 68; void reset(); Common::Array _frames; Common::SeekableReadStream *_stream; bool _isLoaded; Common::String _name; byte _field30; // used when copying sequences }; class SequenceFrame : public Drawable { public: SequenceFrame(Sequence *sequence, uint16 frame = 0, bool dispose = false) : _sequence(sequence), _frame(frame), _dispose(dispose) {} ~SequenceFrame(); Common::Rect draw(Graphics::Surface *surface); bool setFrame(uint16 frame); uint32 getFrame() { return _frame; } bool nextFrame(); Common::String getName(); FrameInfo *getInfo(); bool equal(const SequenceFrame *other) const; private: Sequence *_sequence; uint16 _frame; bool _dispose; }; } // End of namespace LastExpress #endif // LASTEXPRESS_SEQUENCE_H