[Scummvm-cvs-logs] SF.net SVN: scummvm:[50174] scummvm/trunk/engines/m4/sprite.cpp

dreammaster at users.sourceforge.net dreammaster at users.sourceforge.net
Wed Jun 23 12:11:01 CEST 2010


Revision: 50174
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50174&view=rev
Author:   dreammaster
Date:     2010-06-23 10:11:01 +0000 (Wed, 23 Jun 2010)

Log Message:
-----------
Rewrote the MADS animation frame decoder to better guard against invalid data causing memory overruns

Modified Paths:
--------------
    scummvm/trunk/engines/m4/sprite.cpp

Modified: scummvm/trunk/engines/m4/sprite.cpp
===================================================================
--- scummvm/trunk/engines/m4/sprite.cpp	2010-06-22 23:55:25 UTC (rev 50173)
+++ scummvm/trunk/engines/m4/sprite.cpp	2010-06-23 10:11:01 UTC (rev 50174)
@@ -121,56 +121,70 @@
 
 // TODO: The sprite outlines (pixel value 0xFD) are not shown
 void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
-	byte *outp, *lineStart;
-	bool newLine = false;
+	// Set entire sprite contents to transparent pixels
+	fillRect(bounds(), TRANSPARENT_COLOUR_INDEX);
 
-	outp = getBasePtr();
-	lineStart = getBasePtr();
+	// Major line loop
+	for (int y = 0; y < h; ++y) {
+		byte *destP = getBasePtr(0, y);
+		bool newLine = false;
+		byte cmd = source->readByte();
+		int x = 0;
 
-	while (1) {
-		byte cmd1, cmd2, count, pixel;
-
-		if (newLine) {
-			if (outp < (lineStart + w))
-				Common::set_to(outp, lineStart + w, TRANSPARENT_COLOUR_INDEX);
-
-			outp = lineStart + w;
-			lineStart = outp;
-			newLine = false;
-		}
-
-		cmd1 = source->readByte();
-
-		if (cmd1 == 0xFC)
-			break;
-		else if (cmd1 == 0xFF)
+		if (cmd == 0xff)
+			// The entire line is empty
 			newLine = true;
-		else if (cmd1 == 0xFD) {
-			while (!newLine) {
-				count = source->readByte();
-				if (count == 0xFF) {
+		else if (cmd == 0xFD) {
+			// Lines contains only run lenghs of pixels
+			while (x < w) {
+				byte cmd = source->readByte();
+				if (cmd == 0xff) {
+					// End of line reached
 					newLine = true;
-				} else {
-					pixel = source->readByte();
-					while (count--)
-						*outp++ = (pixel == 0xFD) ? TRANSPARENT_COLOUR_INDEX : pixel;
+					break;
 				}
+
+				byte v = source->readByte();
+				while (cmd-- > 0) {
+					if (x < w)
+						*destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v;
+					++x;
+				}
 			}
 		} else {
-			while (!newLine) {
-				cmd2 = source->readByte();
-				if (cmd2 == 0xFF) {
+			// Line intermixes run lengths with individual pixels
+			while (x < w) {
+				cmd = source->readByte();
+				if (cmd == 0xff) {
+					// End of line reached
 					newLine = true;
-				} else if (cmd2 == 0xFE) {
-					count = source->readByte();
-					pixel = source->readByte();
-					while (count--)
-						*outp++ = (pixel == 0xFD) ? TRANSPARENT_COLOUR_INDEX : pixel;
+					break;
+				}
+
+				if (cmd == 0xFE) {
+					// Handle repeated sequence
+					cmd = source->readByte();
+					byte v = source->readByte();
+					while (cmd-- > 0) {
+						if (x < w) {
+							*destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v;
+						}
+						++x;
+					}
 				} else {
-					*outp++ = (cmd2 == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd2;
+					// Handle writing out single pixel
+					*destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd;
+					++x;
 				}
 			}
 		}
+		
+		// Check if we need to scan forward to find the end of the line
+		if (!newLine) {
+			do {
+				assert(!source->eos());
+			} while (source->readByte() != 0xff);
+		}
 	}
 }
 


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