aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2010-06-23 10:11:01 +0000
committerPaul Gilbert2010-06-23 10:11:01 +0000
commit717005bf25b6e74f22418324845f363eb4a1068d (patch)
treec5143c613db7226435a06e3adebddaf8d6edf861 /engines
parentb68180efe525c37f48a81ce7946d9e6f2045cf07 (diff)
downloadscummvm-rg350-717005bf25b6e74f22418324845f363eb4a1068d.tar.gz
scummvm-rg350-717005bf25b6e74f22418324845f363eb4a1068d.tar.bz2
scummvm-rg350-717005bf25b6e74f22418324845f363eb4a1068d.zip
Rewrote the MADS animation frame decoder to better guard against invalid data causing memory overruns
svn-id: r50174
Diffstat (limited to 'engines')
-rw-r--r--engines/m4/sprite.cpp94
1 files changed, 54 insertions, 40 deletions
diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp
index da043c695f..553b27dd9a 100644
--- a/engines/m4/sprite.cpp
+++ b/engines/m4/sprite.cpp
@@ -121,56 +121,70 @@ void M4Sprite::loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int
// TODO: The sprite outlines (pixel value 0xFD) are not shown
void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) {
- byte *outp, *lineStart;
- bool newLine = false;
-
- outp = getBasePtr();
- lineStart = getBasePtr();
-
- 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)
+ // Set entire sprite contents to transparent pixels
+ fillRect(bounds(), TRANSPARENT_COLOUR_INDEX);
+
+ // 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;
+
+ 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);
+ }
}
}