[Scummvm-cvs-logs] SF.net SVN: scummvm:[35068] scummvm/trunk/graphics

cyx at users.sourceforge.net cyx at users.sourceforge.net
Sat Nov 15 03:31:12 CET 2008


Revision: 35068
          http://scummvm.svn.sourceforge.net/scummvm/?rev=35068&view=rev
Author:   cyx
Date:     2008-11-15 02:31:11 +0000 (Sat, 15 Nov 2008)

Log Message:
-----------
added FLIC player from KoM engine module.
changes :
- changed methods name to match the ones from DXAPlayer
- added file read streaming
- added possibiltiy to reset playback

Modified Paths:
--------------
    scummvm/trunk/graphics/module.mk

Added Paths:
-----------
    scummvm/trunk/graphics/flic_player.cpp
    scummvm/trunk/graphics/flic_player.h

Added: scummvm/trunk/graphics/flic_player.cpp
===================================================================
--- scummvm/trunk/graphics/flic_player.cpp	                        (rev 0)
+++ scummvm/trunk/graphics/flic_player.cpp	2008-11-15 02:31:11 UTC (rev 35068)
@@ -0,0 +1,264 @@
+/* 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$
+ *
+ */
+
+#include "flic_player.h"
+
+namespace Graphics {
+
+FlicPlayer::FlicPlayer(const char *fileName)
+	: _paletteDirty(false), _offscreen(0), _currFrame(0) {
+
+	memset(&_flicInfo, 0, sizeof(_flicInfo));
+	_fileStream.open(fileName);
+
+	_flicInfo.size = _fileStream.readUint32LE();
+	_flicInfo.type = _fileStream.readUint16LE();
+	_flicInfo.numFrames = _fileStream.readUint16LE();
+	_flicInfo.width = _fileStream.readUint16LE();
+	_flicInfo.height = _fileStream.readUint16LE();
+	_fileStream.skip(4);
+	_flicInfo.speed = _fileStream.readUint32LE();
+
+	_fileStream.seek(80);
+	_flicInfo.offsetFrame1 = _fileStream.readUint32LE();
+	_flicInfo.offsetFrame2 = _fileStream.readUint32LE();
+
+	// Check FLC magic number
+	if (_flicInfo.type != 0xAF12) {
+		error("FlicPlayer::FlicPlayer(): attempted to load non-FLC data (type = 0x%04X)", _flicInfo.type);
+	}
+
+	_offscreen = new uint8[_flicInfo.width * _flicInfo.height];
+	memset(_palette, 0, sizeof(_palette));
+
+	// Seek to the first frame
+	_fileStream.seek(_flicInfo.offsetFrame1);
+}
+
+FlicPlayer::~FlicPlayer() {
+	delete[] _offscreen;
+}
+
+void FlicPlayer::redraw() {
+	_dirtyRects.clear();
+	_dirtyRects.push_back(Common::Rect(0, 0, _flicInfo.width, _flicInfo.height));
+}
+
+ChunkHeader FlicPlayer::readChunkHeader() {
+	ChunkHeader head;
+	head.size = _fileStream.readUint32LE();
+	head.type = _fileStream.readUint16LE();
+
+	/* XXX: You'll want to read the rest of the chunk here as well! */
+
+	return head;
+}
+
+FrameTypeChunkHeader FlicPlayer::readFrameTypeChunkHeader(ChunkHeader chunkHead) {
+	FrameTypeChunkHeader head;
+
+	head.header = chunkHead;
+	head.numChunks = _fileStream.readUint16LE();
+	head.delay = _fileStream.readUint16LE();
+	head.reserved = _fileStream.readUint16LE();
+	head.widthOverride = _fileStream.readUint16LE();
+	head.heightOverride = _fileStream.readUint16LE();
+
+	return head;
+}
+
+void FlicPlayer::decodeByteRun(uint8 *data) {
+	uint8 *ptr = (uint8 *)_offscreen;
+	while((ptr - _offscreen) < (_flicInfo.width * _flicInfo.height)) {
+		uint8 chunks = *data++;
+		while (chunks--) {
+			int8 count = *data++;
+			if (count > 0) {
+				memset(ptr, *data++, count);
+				ptr += count;
+			} else {
+				uint8 copyBytes = -count;
+				memcpy(ptr, data, copyBytes);
+				ptr += copyBytes;
+				data += copyBytes;
+			}
+		}
+	}
+
+	redraw();
+}
+
+#define OP_PACKETCOUNT   0
+#define OP_UNDEFINED     1
+#define OP_LASTPIXEL     2
+#define OP_LINESKIPCOUNT 3
+
+void FlicPlayer::decodeDeltaFLC(uint8 *data) {
+	uint16 linesInChunk = READ_LE_UINT16(data); data += 2;
+	uint16 currentLine = 0;
+	uint16 packetCount = 0;
+
+	while (linesInChunk--) {
+		uint16 opcode;
+
+		// First process all the opcodes.
+		do {
+			opcode = READ_LE_UINT16(data); data += 2;
+
+			switch ((opcode >> 14) & 3) {
+			case OP_PACKETCOUNT:
+				packetCount = opcode;
+				break;
+			case OP_UNDEFINED:
+				break;
+			case OP_LASTPIXEL:
+				*(uint8 *)(_offscreen + (currentLine * _flicInfo.width) + (_flicInfo.width - 1)) = (opcode & 0xFF);
+				_dirtyRects.push_back(Common::Rect(_flicInfo.width - 1, currentLine, _flicInfo.width, currentLine + 1));
+				break;
+			case OP_LINESKIPCOUNT:
+				currentLine += -(int16)opcode;
+				break;
+			}
+		} while (((opcode >> 14) & 3) != OP_PACKETCOUNT);
+
+		uint16 column = 0;
+
+		// Now interpret the RLE data
+		while (packetCount--) {
+			column += *data++;
+			int8 rleCount = (int8)*data++;
+			if (rleCount > 0) {
+				memcpy((void *)(_offscreen + (currentLine * _flicInfo.width) + column), data, rleCount * 2);
+				_dirtyRects.push_back(Common::Rect(column, currentLine, column + (rleCount * 2), currentLine + 1));
+				data += rleCount * 2;
+				column += rleCount * 2;
+			} else if (rleCount < 0) {
+				uint16 dataWord = *(uint16 *)data; data += 2;
+				for (int i = 0; i < -(int16)rleCount; ++i) {
+					WRITE_LE_UINT16(_offscreen + (currentLine * _flicInfo.width) + column + (i * 2), dataWord);
+				}
+				_dirtyRects.push_back(Common::Rect(column, currentLine, column + (-(int16)rleCount * 2), currentLine + 1));
+
+				column += (-(int16)rleCount) * 2;
+			} else { // End of cutscene ?
+				return;
+			}
+		}
+
+		currentLine++;
+	}
+}
+
+#define COLOR_256  4
+#define FLI_SS2    7
+#define FLI_BRUN   15
+#define PSTAMP     18
+#define FRAME_TYPE 0xF1FA
+
+void FlicPlayer::decodeFrame() {
+	FrameTypeChunkHeader frameHeader;
+
+	// Read chunk
+	ChunkHeader cHeader = readChunkHeader();
+	switch (cHeader.type) {
+	case FRAME_TYPE:
+		frameHeader = readFrameTypeChunkHeader(cHeader);
+		_currFrame++;
+		break;
+	default:
+		error("FlicPlayer::decodeFrame(): unknown main chunk type (type = 0x%02X)", cHeader.type);
+		break;
+	 }
+
+	// Read subchunks
+	if (cHeader.type == FRAME_TYPE) {
+		for (int i = 0; i < frameHeader.numChunks; ++i) {
+			cHeader = readChunkHeader();
+			uint8 *data = new uint8[cHeader.size - 6];
+			_fileStream.read(data, cHeader.size - 6);
+			switch (cHeader.type) {
+			case COLOR_256:
+				setPalette(data);
+				_paletteDirty = true;
+				break;
+			case FLI_SS2:
+				decodeDeltaFLC(data);
+				break;
+			case FLI_BRUN:
+				decodeByteRun(data);
+				break;
+			case PSTAMP:
+				/* PSTAMP - skip for now */
+				break;
+			default:
+				error("FlicPlayer::decodeFrame(): unknown subchunk type (type = 0x%02X)", cHeader.type);
+				break;
+			 }
+
+			delete[] data;
+		}
+	}
+
+	// If we just processed the ring frame, set the next frame
+	if (_currFrame == _flicInfo.numFrames + 1) {
+		_currFrame = 1;
+		_fileStream.seek(_flicInfo.offsetFrame2);
+	}
+}
+
+void FlicPlayer::reset() {
+	_fileStream.seek(_flicInfo.offsetFrame1);
+}
+
+void FlicPlayer::setPalette(uint8 *mem) {
+	uint16 numPackets = READ_LE_UINT16(mem); mem += 2;
+
+	if (0 == READ_LE_UINT16(mem)) { //special case
+		mem += 2;
+		for (int i = 0; i < 256; ++i) {
+			for (int j = 0; j < 3; ++j)
+				_palette[i * 4 + j] = (mem[i * 3 + j]);
+			_palette[i * 4 + 3] = 0;
+		}
+	} else {
+		uint8 palPos = 0;
+
+		while (numPackets--) {
+			palPos += *mem++;
+			uint8 change = *mem++;
+
+			for (int i = 0; i < change; ++i) {
+				for (int j = 0; j < 3; ++j)
+					_palette[(palPos + i) * 4 + j] = (mem[i * 3 + j]);
+				_palette[(palPos + i) * 4 + 3] = 0;
+			}
+
+			palPos += change;
+			mem += (change * 3);
+		}
+	}
+}
+
+} // End of namespace Graphics


Property changes on: scummvm/trunk/graphics/flic_player.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/graphics/flic_player.h
===================================================================
--- scummvm/trunk/graphics/flic_player.h	                        (rev 0)
+++ scummvm/trunk/graphics/flic_player.h	2008-11-15 02:31:11 UTC (rev 35068)
@@ -0,0 +1,100 @@
+/* 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 GRAPHICS_FLICPLAYER_H
+#define GRAPHICS_FLICPLAYER_H
+
+#include "common/endian.h"
+#include "common/list.h"
+#include "common/rect.h"
+#include "common/file.h"
+
+namespace Graphics {
+
+struct FlicHeader {
+	uint32 size;
+	uint16 type;
+	uint16 numFrames;
+	uint16 width;
+	uint16 height;
+	uint32 speed;
+	uint16 offsetFrame1;
+	uint16 offsetFrame2;
+};
+
+struct ChunkHeader {
+	uint32 size;
+	uint16 type;
+};
+
+struct FrameTypeChunkHeader {
+	ChunkHeader header;
+	uint16 numChunks;
+	uint16 delay;
+	uint16 reserved; // always zero
+	uint16 widthOverride;
+	uint16 heightOverride;
+};
+
+class FlicPlayer {
+public:
+	FlicPlayer(const char *fileName);
+	~FlicPlayer();
+
+	void decodeFrame();
+	int getWidth() const { return _flicInfo.width; }
+	int getHeight() const { return _flicInfo.height; }
+	bool hasFrames() const { return _flicInfo.numFrames > 0; }
+	int getCurFrame() const { return _currFrame; }
+	int getFrameCount() const { return _flicInfo.numFrames; }
+	uint32 getSpeed() const { return _flicInfo.speed; }
+	bool isPaletteDirty() const { return _paletteDirty; }
+	const uint8 *getPalette() { _paletteDirty = false; return _palette; }
+	const uint8 *getOffscreen() const { return _offscreen; }
+	const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; }
+	void clearDirtyRects() { _dirtyRects.clear(); }
+	void redraw();
+	void reset();
+
+protected:
+	ChunkHeader readChunkHeader();
+	FrameTypeChunkHeader readFrameTypeChunkHeader(ChunkHeader chunkHead);
+	void decodeByteRun(uint8 *data);
+	void decodeDeltaFLC(uint8 *data);
+	void setPalette(uint8 *mem);
+
+	Common::File _fileStream;
+	bool _paletteDirty;
+	uint8 *_offscreen;
+	uint8 _palette[256 * 4];
+	FlicHeader _flicInfo;
+	uint16 _currFrame;
+	uint32 _lastFrameTime;
+	Common::List<Common::Rect> _dirtyRects;
+};
+
+} // End of namespace Graphics
+
+#endif


Property changes on: scummvm/trunk/graphics/flic_player.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Modified: scummvm/trunk/graphics/module.mk
===================================================================
--- scummvm/trunk/graphics/module.mk	2008-11-14 23:37:30 UTC (rev 35067)
+++ scummvm/trunk/graphics/module.mk	2008-11-15 02:31:11 UTC (rev 35068)
@@ -3,6 +3,7 @@
 MODULE_OBJS := \
 	cursorman.o \
 	dxa_player.o \
+	flic_player.o \
 	font.o \
 	fontman.o \
 	fonts/consolefont.o \


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list