From 6d03ddef0bcc06041b385224c003d78c8214cf4f Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 8 Aug 2010 01:01:17 +0000 Subject: VIDEO: Implement CoktelDecoder::renderBlockRLE() svn-id: r51907 --- graphics/video/coktel_decoder.cpp | 81 ++++++++++++++++++++++++++++++++++++++- graphics/video/coktel_decoder.h | 1 + 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/graphics/video/coktel_decoder.cpp b/graphics/video/coktel_decoder.cpp index 019ed77019..cc4745b535 100644 --- a/graphics/video/coktel_decoder.cpp +++ b/graphics/video/coktel_decoder.cpp @@ -341,6 +341,48 @@ void CoktelDecoder::deLZ77(byte *dest, byte *src) { } } +void CoktelDecoder::deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen) { + srcPtr++; + + if (srcLen & 1) { + byte data = *srcPtr++; + + if (destLen > 0) { + *destPtr++ = data; + destLen--; + } + } + + srcLen >>= 1; + + while (srcLen > 0) { + uint8 tmp = *srcPtr++; + if (tmp & 0x80) { // Verbatim copy + tmp &= 0x7F; + + int16 copyCount = MAX(0, MIN(destLen, tmp * 2)); + + memcpy(destPtr, srcPtr, copyCount); + + srcPtr += tmp * 2; + destPtr += copyCount; + destLen -= copyCount; + } else { // 2 bytes tmp times + for (int i = 0; (i < tmp) && (destLen > 0); i++) { + for (int j = 0; j < 2; j++) { + if (destLen <= 0) + break; + + *destPtr++ = srcPtr[j]; + destLen--; + } + } + srcPtr += 2; + } + srcLen -= tmp; + } +} + // A whole, completely filled block void CoktelDecoder::renderBlockWhole(const byte *src, Common::Rect &rect) { Common::Rect srcRect = rect; @@ -477,9 +519,44 @@ void CoktelDecoder::renderBlockSparse2Y(const byte *src, Common::Rect &rect) { } void CoktelDecoder::renderBlockRLE(const byte *src, Common::Rect &rect) { - warning("renderBlockRLE"); + Common::Rect srcRect = rect; - // TODO + rect.clip(_surface.w, _surface.h); + + byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left; + for (int i = 0; i < rect.height(); i++) { + byte *dstRow = dst; + int16 pixWritten = 0; + + while (pixWritten < srcRect.width()) { + int16 pixCount = *src++; + + if (pixCount & 0x80) { + int16 copyCount; + + pixCount = MIN((pixCount & 0x7F) + 1, srcRect.width() - pixWritten); + copyCount = CLIP(rect.width() - pixWritten, 0, pixCount); + + if (*src != 0xFF) { // Normal copy + + memcpy(dstRow, src, copyCount); + dstRow += copyCount; + src += pixCount; + } else + deRLE(dstRow, src, copyCount, pixCount); + + pixWritten += pixCount; + } else { // "Hole" + int16 copyCount = CLIP(rect.width() - pixWritten, 0, pixCount + 1); + + dstRow += copyCount; + pixWritten += pixCount + 1; + } + + } + + dst += _surface.pitch; + } } Common::Rational CoktelDecoder::getFrameRate() const { diff --git a/graphics/video/coktel_decoder.h b/graphics/video/coktel_decoder.h index 48d43962e7..408523ff48 100644 --- a/graphics/video/coktel_decoder.h +++ b/graphics/video/coktel_decoder.h @@ -186,6 +186,7 @@ protected: // Decompression void deLZ77(byte *dest, byte *src); + void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen); // Block rendering void renderBlockWhole (const byte *src, Common::Rect &rect); -- cgit v1.2.3