From cefff90ac61e95641950ae694e3334c1c344c32d Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Mon, 19 May 2008 19:34:55 +0000 Subject: RtZ: Fixed bug which caused PMV videos to look odd (noticeable in the intro movie) and optimized frame decompression code. svn-id: r32182 --- engines/made/graphics.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++- engines/made/graphics.h | 1 + engines/made/pmvplayer.cpp | 30 +++++++----- 3 files changed, 129 insertions(+), 13 deletions(-) diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp index 081621ef18..76b39ed43a 100644 --- a/engines/made/graphics.cpp +++ b/engines/made/graphics.cpp @@ -47,7 +47,6 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u byte *destPtr = (byte*)surface.getBasePtr(0, 0); - //byte lineBuf[320 * 4]; byte lineBuf[640 * 4]; byte bitBuf[40]; @@ -149,4 +148,114 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u } +void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize) { + + uint16 width = surface.w; + uint16 height = surface.h; + uint16 bx = 0, by = 0, bw = ((width + 3) / 4) * 4; + + byte *cmdBuffer = source + cmdOffs; + byte *maskBuffer = source + maskOffs; + byte *pixelBuffer = source + pixelOffs; + + byte *destPtr = (byte*)surface.getBasePtr(0, 0); + + byte bitBuf[40]; + + int bitBufLastOfs = (((lineSize + 1) >> 1) << 1) - 2; + int bitBufLastCount = ((width + 3) >> 2) & 7; + if (bitBufLastCount == 0) + bitBufLastCount = 8; + + debug(1, "width = %d; bw = %d", width, bw); + + while (height > 0) { + + int drawDestOfs = 0; + + memcpy(bitBuf, cmdBuffer, lineSize); + cmdBuffer += lineSize; + + for (uint16 bitBufOfs = 0; bitBufOfs < lineSize; bitBufOfs += 2) { + + uint16 bits = READ_LE_UINT16(&bitBuf[bitBufOfs]); + + int bitCount; + if (bitBufOfs == bitBufLastOfs) + bitCount = bitBufLastCount; + else + bitCount = 8; + + for (int curCmd = 0; curCmd < bitCount; curCmd++) { + uint cmd = bits & 3; + bits >>= 2; + + byte pixels[4], block[16]; + uint32 mask; + + switch (cmd) { + + case 0: + pixels[0] = *pixelBuffer++; + for (int i = 0; i < 16; i++) + block[i] = pixels[0]; + break; + + case 1: + pixels[0] = *pixelBuffer++; + pixels[1] = *pixelBuffer++; + mask = READ_LE_UINT16(maskBuffer); + maskBuffer += 2; + for (int i = 0; i < 16; i++) { + block[i] = pixels[mask & 1]; + mask >>= 1; + } + break; + + case 2: + pixels[0] = *pixelBuffer++; + pixels[1] = *pixelBuffer++; + pixels[2] = *pixelBuffer++; + pixels[3] = *pixelBuffer++; + mask = READ_LE_UINT32(maskBuffer); + maskBuffer += 4; + for (int i = 0; i < 16; i++) { + block[i] = pixels[mask & 3]; + mask >>= 2; + } + break; + + case 3: + break; + + } + + if (cmd != 3) { + uint16 blockPos = 0; + uint32 maxW = MIN(4, surface.w - bx); + uint32 maxH = (MIN(4, surface.h - by) + by) * width; + for (uint32 yc = by * width; yc < maxH; yc += width) { + for (uint32 xc = 0; xc < maxW; xc++) { + destPtr[(bx + xc) + yc] = block[xc + blockPos]; + } + blockPos += 4; + } + } + + bx += 4; + if (bx >= bw) { + bx = 0; + by += 4; + } + + } + + } + + height -= 4; + + } + +} + } // End of namespace Made diff --git a/engines/made/graphics.h b/engines/made/graphics.h index 3c56bb4231..31c747a89b 100644 --- a/engines/made/graphics.h +++ b/engines/made/graphics.h @@ -34,6 +34,7 @@ namespace Made { void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame = false); +void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize); } // End of namespace Made diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index db56235a67..8180758d61 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -74,7 +74,7 @@ void PmvPlayer::play(const char *filename) { uint32 frameCount = 0; uint16 chunkCount = 0; uint32 soundSize = 0; - uint32 palChunkOfs = 0; + uint32 soundChunkOfs = 0, palChunkOfs = 0; uint32 palSize = 0; byte *frameData, *audioData, *soundData, *palData, *imageData; bool firstTime = true; @@ -100,23 +100,29 @@ void PmvPlayer::play(const char *filename) { frameData = new byte[chunkSize]; _fd->read(frameData, chunkSize); + + soundChunkOfs = READ_LE_UINT32(frameData + 8); + palChunkOfs = READ_LE_UINT32(frameData + 16); // Handle audio - audioData = frameData + READ_LE_UINT32(frameData + 8) - 8; - chunkSize = READ_LE_UINT16(audioData + 4); - chunkCount = READ_LE_UINT16(audioData + 6); + if (soundChunkOfs) { + + audioData = frameData + soundChunkOfs - 8; + chunkSize = READ_LE_UINT16(audioData + 4); + chunkCount = READ_LE_UINT16(audioData + 6); - if (chunkCount > 50) break; // FIXME: this is a hack + debug(1, "chunkCount = %d; chunkSize = %d; total = %d\n", chunkCount, chunkSize, chunkCount * chunkSize); - debug(1, "chunkCount = %d; chunkSize = %d; total = %d\n", chunkCount, chunkSize, chunkCount * chunkSize); + if (chunkCount > 50) break; // FIXME: this is a hack - soundSize = chunkCount * chunkSize; - soundData = new byte[soundSize]; - decompressSound(audioData + 8, soundData, chunkSize, chunkCount); - _audioStream->queueBuffer(soundData, soundSize); + soundSize = chunkCount * chunkSize; + soundData = new byte[soundSize]; + decompressSound(audioData + 8, soundData, chunkSize, chunkCount); + _audioStream->queueBuffer(soundData, soundSize); + + } // Handle palette - palChunkOfs = READ_LE_UINT32(frameData + 16); if (palChunkOfs) { palData = frameData + palChunkOfs - 8; palSize = READ_LE_UINT32(palData + 4); @@ -143,7 +149,7 @@ void PmvPlayer::play(const char *filename) { _surface->create(width, height, 1); } - decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0); + decompressMovieImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize); if (firstTime) { _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream); -- cgit v1.2.3