diff options
author | Sven Hesse | 2007-07-31 23:06:25 +0000 |
---|---|---|
committer | Sven Hesse | 2007-07-31 23:06:25 +0000 |
commit | 507461e94df430484b0f377c17a54472810747c2 (patch) | |
tree | ab23e984009ac43cb93547bc29b7bfb7435b7f77 | |
parent | 6b590bf4d14a0f0d3024d85b9a6220956e131d23 (diff) | |
download | scummvm-rg350-507461e94df430484b0f377c17a54472810747c2.tar.gz scummvm-rg350-507461e94df430484b0f377c17a54472810747c2.tar.bz2 scummvm-rg350-507461e94df430484b0f377c17a54472810747c2.zip |
- VMD playing works a bit better now
- Minor cleanup
svn-id: r28373
-rw-r--r-- | engines/gob/coktelvideo.cpp | 305 | ||||
-rw-r--r-- | engines/gob/coktelvideo.h | 4 |
2 files changed, 159 insertions, 150 deletions
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp index bb50ddf04a..d8275c4ad3 100644 --- a/engines/gob/coktelvideo.cpp +++ b/engines/gob/coktelvideo.cpp @@ -315,7 +315,7 @@ void Imd::waitEndFrame() { if (waitTime < 0) { _skipFrames = -waitTime / _soundSliceLength; - warning("IMD A/V sync broken, skipping %d frame(s)", _skipFrames + 1); + warning("Video A/V sync broken, skipping %d frame(s)", _skipFrames + 1); } else if (waitTime > 0) g_system->delayMillis(waitTime); @@ -418,6 +418,7 @@ void Imd::clear(bool del) { _soundStartTime = 0; _skipFrames = 0; + _soundFlags = 0; _soundFreq = 0; _soundSliceSize = 0; _soundSlicesCount = 0; @@ -432,7 +433,6 @@ void Imd::clear(bool del) { CoktelVideo::State Imd::processFrame(uint16 frame) { State state; uint32 cmd = 0; - int16 xBak, yBak, heightBak, widthBak; bool hasNextCmd = false; bool startSound = false; @@ -446,34 +446,29 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { seekFrame(frame); } - state.left = xBak = _x; - state.top = yBak = _y; - state.bottom = heightBak = _height; - state.right = widthBak = _width; - state.right += state.left - 1; - state.bottom += state.top - 1; + if (!_vidMem) + setVideoMemory(); + + state.left = _x; + state.top = _y; + state.right = _width + state.left - 1; + state.bottom = _height + state.top - 1; do { if (frame != 0) { if (_stdX != -1) { - state.left = _x = _stdX; - state.top = _y = _stdY; - state.right = _width = _stdWidth; - state.bottom = _height = _stdHeight; - state.right += state.left - 1; - state.bottom += state.top - 1; + state.left = _stdX; + state.top = _stdY; + state.right = _stdWidth + state.left - 1; + state.bottom = _stdHeight + state.top - 1; state.flags |= kStateStdCoords; } if (_frameCoords && (_frameCoords[frame].left != -1)) { - state.left = _x = _frameCoords[frame].left; - state.top = _y = _frameCoords[frame].top; - state.right = _width = - _frameCoords[frame].right - _x + 1; - state.bottom = _height = - _frameCoords[frame].bottom - _y + 1; - state.right += state.left - 1; - state.bottom += state.top - 1; + state.left = _frameCoords[frame].left; + state.top = _frameCoords[frame].top; + state.right = _frameCoords[frame].right; + state.bottom = _frameCoords[frame].bottom; state.flags |= kStateFrameCoords; } } @@ -577,33 +572,20 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { cmd = _stream->readUint32LE(); _stream->read(_frameData, cmd + 2); - int16 left = _x; - int16 top = _y; - int16 right = _width + left; - int16 bottom = _height + top; - - if (!_vidMem) - setVideoMemory(); - - if (_vidMemWidth < right) { - left = 0; - right = _width; + if (_vidMemWidth <= state.right) { + state.left = 0; + state.right -= state.left; } - if (_vidMemWidth < right) - right = _vidMemWidth; - if (_vidMemHeight < bottom) { - top = 0; - bottom = _height; + if (_vidMemWidth <= state.right) + state.right = _vidMemWidth - 1; + if (_vidMemHeight <= state.bottom) { + state.top = 0; + state.bottom -= state.top; } - if (_vidMemHeight < bottom) - bottom = _vidMemHeight; - - _x = left; - _y = top; - _height = bottom - top; - _width = right - left; + if (_vidMemHeight <= state.bottom) + state.bottom = _vidMemHeight -1; - state.flags |= renderFrame(); + state.flags |= renderFrame(state.left, state.top, state.right, state.bottom); state.flags |= _frameData[0]; // Frame video data @@ -611,7 +593,7 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { _stream->read(_frameData, cmd + 2); - state.flags |= renderFrame(); + state.flags |= renderFrame(state.left, state.top, state.right, state.bottom); state.flags |= _frameData[0]; } else @@ -626,11 +608,6 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { _soundStage = 2; } - _x = xBak; - _y = yBak; - _width = widthBak; - _height = heightBak; - _curFrame++; if ((_curFrame == _framesCount) && (_soundStage == 2)) { _audioStream->finish(); @@ -643,23 +620,18 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { return state; } -uint32 Imd::renderFrame() { - if (!_frameData || (_width <= 0) || (_height <= 0)) +uint32 Imd::renderFrame(int16 left, int16 top, int16 right, int16 bottom) { + if (!_frameData || !_vidMem || (_width <= 0) || (_height <= 0)) return 0; - if (!_vidMem) - setVideoMemory(); - - byte *dataPtr = _frameData; - int16 imdX = _x; - int16 imdY = _y; - int16 imdW = _width; - int16 imdH = _height; + uint32 retVal = 0; + int16 width = right - left + 1; + int16 height = bottom - top + 1; int16 sW = _vidMemWidth; - byte *imdVidMem = _vidMem + sW * imdY + imdX; + byte *dataPtr = _frameData; + byte *imdVidMem = _vidMem + sW * top + left; + byte *srcPtr; uint8 type = *dataPtr++; - byte *srcPtr = dataPtr; - uint32 retVal = 0; if (type & 0x10) { // Palette data // One byte index @@ -673,10 +645,11 @@ uint32 Imd::renderFrame() { } srcPtr = dataPtr; + if (type & 0x80) { // Frame data is compressed srcPtr = _vidBuffer; type &= 0x7F; - if ((type == 2) && (imdW == sW)) { + if ((type == 2) && (width == sW)) { deLZ77(imdVidMem, dataPtr); return retVal; } else @@ -687,19 +660,19 @@ uint32 Imd::renderFrame() { byte *imdVidMemBak; if (type == 2) { // Whole block - for (int i = 0; i < imdH; i++) { - memcpy(imdVidMem, srcPtr, imdW); - srcPtr += imdW; + for (int i = 0; i < height; i++) { + memcpy(imdVidMem, srcPtr, width); + srcPtr += width; imdVidMem += sW; } } else if (type == 1) { // Sparse block imdVidMemBak = imdVidMem; - for (int i = 0; i < imdH; i++) { + for (int i = 0; i < height; i++) { pixWritten = 0; - while (pixWritten < imdW) { + while (pixWritten < width) { pixCount = *srcPtr++; if (pixCount & 0x80) { // data - pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten); + pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten); memcpy(imdVidMem, srcPtr, pixCount); pixWritten += pixCount; @@ -715,30 +688,30 @@ uint32 Imd::renderFrame() { imdVidMem = imdVidMemBak; } } else if (type == 0x42) { // Whole quarter-wide block - for (int i = 0; i < imdH; i++) { + for (int i = 0; i < height; i++) { imdVidMemBak = imdVidMem; - for (int j = 0; j < imdW; j += 4, imdVidMem += 4, srcPtr++) + for (int j = 0; j < width; j += 4, imdVidMem += 4, srcPtr++) memset(imdVidMem, *srcPtr, 4); imdVidMemBak += sW; imdVidMem = imdVidMemBak; } } else if ((type & 0xF) == 2) { // Whole half-high block - for (; imdH > 1; imdH -= 2, imdVidMem += sW + sW, srcPtr += imdW) { - memcpy(imdVidMem, srcPtr, imdW); - memcpy(imdVidMem + sW, srcPtr, imdW); + for (; height > 1; height -= 2, imdVidMem += sW + sW, srcPtr += width) { + memcpy(imdVidMem, srcPtr, width); + memcpy(imdVidMem + sW, srcPtr, width); } - if (imdH == -1) - memcpy(imdVidMem, srcPtr, imdW); + if (height == -1) + memcpy(imdVidMem, srcPtr, width); } else { // Sparse half-high block imdVidMemBak = imdVidMem; - for (int i = 0; i < imdH; i += 2) { + for (int i = 0; i < height; i += 2) { pixWritten = 0; - while (pixWritten < imdW) { + while (pixWritten < width) { pixCount = *srcPtr++; if (pixCount & 0x80) { // data - pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten); + pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten); memcpy(imdVidMem, srcPtr, pixCount); memcpy(imdVidMem + sW, srcPtr, pixCount); @@ -865,15 +838,13 @@ bool Vmd::load(Common::SeekableReadStream &stream) { // Version checking if ((headerLength != 814) || (handle != 0) || (_version != 1)) { - warning("IMD Version incorrect (%d, %d, %d)", headerLength, handle, _version); + warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version); unload(); return false; } _framesCount = _stream->readUint16LE(); - warning("# of frames: %d", _framesCount); - _x = _stream->readSint16LE(); _y = _stream->readSint16LE(); _width = _stream->readSint16LE(); @@ -881,19 +852,13 @@ bool Vmd::load(Common::SeekableReadStream &stream) { if ((_width != 0) && (_height != 0)) { _hasVideo = true; _features |= kFeaturesVideo; - - warning("%dx%d+%d+%d", _width, _height, _x, _y); - } else _hasVideo = false; _flags = _stream->readUint16LE(); _partsPerFrame = _stream->readUint16LE(); _firstFramePos = _stream->readUint32LE(); - uint32 unknown1 = _stream->readUint32LE(); - - warning("flags: %d (0x%X), #parts: %d, firstFramePos: %d, U1: %d (0x%X)", - _flags, _flags, _partsPerFrame, _firstFramePos, unknown1, unknown1); + _stream->skip(4); // Unknown _stream->read((byte *) _palette, 768); @@ -912,13 +877,12 @@ bool Vmd::load(Common::SeekableReadStream &stream) { _vidBuffer = new byte[_vidBufferSize]; assert(_vidBuffer); memset(_vidBuffer, 0, _vidBufferSize); - warning("Sizes: frameData: %d, vidBuffer: %d", _frameDataSize, _vidBufferSize); } _soundFreq = _stream->readSint16LE(); _soundSliceSize = _stream->readUint16LE(); _soundSlicesCount = _stream->readSint16LE(); - uint16 soundFlags = _stream->readUint16LE(); + _soundFlags = _stream->readUint16LE(); _hasSound = (_soundFreq != 0); if (_hasSound) { @@ -928,59 +892,45 @@ bool Vmd::load(Common::SeekableReadStream &stream) { _frameLength = _soundSliceLength; _soundStage = 1; - _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0); - - warning("Sound: Freq: %d, # slices %d, slideSize: %d, flags: %d (0x%X), sliceLen = %d", - _soundFreq, _soundSlicesCount, _soundSliceSize, soundFlags, soundFlags, _soundSliceLength); - } else _frameLength = 1000 / 12; // 12 FPS for a video without sound uint32 frameInfoOffset = _stream->readUint32LE(); - warning("frameInfoOffset: %d", frameInfoOffset); - _stream->seek(frameInfoOffset); _frames = new Frame[_framesCount]; for (uint16 i = 0; i < _framesCount; i++) { _frames[i].parts = new Part[_partsPerFrame]; - _stream->skip(2); + _stream->skip(2); // Unknown _frames[i].offset = _stream->readUint32LE(); } for (uint16 i = 0; i < _framesCount; i++) { for (uint16 j = 0; j < _partsPerFrame; j++) { + _frames[i].parts[j].type = (PartType) _stream->readByte(); - uint16 Unknown3 = _stream->readByte(); + _stream->skip(1); // Unknown _frames[i].parts[j].size = _stream->readUint32LE(); + if (_frames[i].parts[j].type == kPartTypeAudio) { + _frames[i].parts[j].flags = _stream->readByte(); - _stream->skip(9); - warning("%d.%d (%d): Audio: %d (0x%X), %d (0x%X)", - i, j, _frames[i].parts[j].size, - Unknown3, Unknown3, _frames[i].parts[j].flags, _frames[i].parts[j].flags); + _stream->skip(9); // Unknow } else if (_frames[i].parts[j].type == kPartTypeVideo) { + _frames[i].parts[j].left = _stream->readUint16LE(); _frames[i].parts[j].top = _stream->readUint16LE(); _frames[i].parts[j].right = _stream->readUint16LE(); _frames[i].parts[j].bottom = _stream->readUint16LE(); - uint16 Unknown4 = _stream->readByte(); + _stream->skip(1); // Unknown _frames[i].parts[j].flags = _stream->readByte(); - warning("%d.%d (%d): Video: %d (0x%X), %d+%d+%d+%d, %d (0x%X), %d (0x%X)", - i, j, _frames[i].parts[j].size, - Unknown3, Unknown3, _frames[i].parts[j].left, - _frames[i].parts[j].top, _frames[i].parts[j].right, - _frames[i].parts[j].bottom, Unknown4, Unknown4, - _frames[i].parts[j].flags, _frames[i].parts[j].flags); } else { - warning("VMD: Unknown frame part type found (%d.%d: %d, %d)", - i, j, _frames[i].parts[j].type, _frames[i].parts[j].size); + // Unknow type _stream->skip(10); -// unload(); -// return false; } + } } @@ -1060,13 +1010,18 @@ void Vmd::clear(bool del) { CoktelVideo::State Vmd::processFrame(uint16 frame) { State state; - int16 xBak = 0, yBak = 0, heightBak = 0, widthBak = 0; bool startSound = false; seekFrame(frame); state.flags |= kStateNoVideoData; - state.left = -1; + state.left = 0x7FFF; + state.right = 0x7FFF; + state.top = 0; + state.bottom = 0; + + if (!_vidMem) + setVideoMemory(); for (uint16 i = 0; i < _partsPerFrame; i++) { Part &part = _frames[frame].parts[i]; @@ -1092,9 +1047,7 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { } else if (part.flags == 2) { if (_soundEnabled) { - uint32 U = _stream->readUint32LE(); - - warning("Mask? %d (0x%X)", U, U); + _stream->skip(4); // Unknown soundBuf = new byte[part.size - 4]; assert(soundBuf); @@ -1128,24 +1081,7 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { } else if (part.type == kPartTypeVideo) { state.flags &= ~kStateNoVideoData; - if (state.left == -1) { - state.left = _x = part.left; - state.top = _y = part.top; - state.right = _width = part.right; - state.bottom = _height = part.bottom; - _width -= _x - 1; - _height -= _y - 1; - } else { - _x = part.left; - _y = part.top; - _width = part.right - (_x - 1); - _height = part.bottom - (_y - 1); - state.left = MIN(state.left, part.left); - state.top = MIN(state.top, part.top); - state.right = MAX(state.right, part.right); - state.bottom = MAX(state.bottom, part.bottom); - } - + // New palette if (part.flags & 2) { uint8 index = _stream->readByte(); uint8 count = _stream->readByte(); @@ -1157,10 +1093,20 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { } _stream->read(_frameData, part.size); - state.flags |= renderFrame(); - } else { - warning("Unknown frame part type %d, size %d (%d of %d)", part.type, part.size, i + 1, _partsPerFrame); + if (renderFrame(part.left, part.top, part.right, part.bottom)) { + // Rendering succeeded, merging areas + state.left = MIN(state.left, part.left); + state.top = MIN(state.top, part.top); + state.right = MAX(state.right, part.right); + state.bottom = MAX(state.bottom, part.bottom); + } + + } else if (part.type == 4) { + // Unknown _stream->skip(part.size); + } else { + // Unknow type +// warning("Unknown frame part type %d, size %d (%d of %d)", part.type, part.size, i + 1, _partsPerFrame); } } @@ -1171,11 +1117,6 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { _soundStage = 2; } - _x = xBak; - _y = yBak; - _width = widthBak; - _height = heightBak; - if ((_curFrame == (_framesCount - 1)) && (_soundStage == 2)) { _audioStream->finish(); _mixer->stopHandle(_audioHandle); @@ -1187,4 +1128,70 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { return state; } +uint32 Vmd::renderFrame(int16 left, int16 top, int16 right, int16 bottom) { + if (!_frameData || !_vidMem || (_width <= 0) || (_height <= 0)) + return 0; + + int16 width = right - left + 1; + int16 height = bottom - top + 1; + int16 sW = _vidMemWidth; + byte *dataPtr = _frameData; + byte *imdVidMem = _vidMem + sW * top + left; + byte *srcPtr; + uint8 type = *dataPtr++; + + srcPtr = dataPtr; + + if (type & 0x80) { // Frame data is compressed + srcPtr = _vidBuffer; + type &= 0x7F; + if ((type == 2) && (width == sW)) { + deLZ77(imdVidMem, dataPtr); + return 1; + } else + deLZ77(srcPtr, dataPtr); + } + + uint16 pixCount, pixWritten; + byte *imdVidMemBak; + + if (type == 1) { // Sparse block + imdVidMemBak = imdVidMem; + for (int i = 0; i < height; i++) { + pixWritten = 0; + while (pixWritten < width) { + pixCount = *srcPtr++; + if (pixCount & 0x80) { // data + pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten); + memcpy(imdVidMem, srcPtr, pixCount); + + pixWritten += pixCount; + imdVidMem += pixCount; + srcPtr += pixCount; + } else { // "hole" + pixCount = (pixCount + 1) % 256; + pixWritten += pixCount; + imdVidMem += pixCount; + } + } + imdVidMemBak += sW; + imdVidMem = imdVidMemBak; + } + } else if (type == 2) { // Whole block + for (int i = 0; i < height; i++) { + memcpy(imdVidMem, srcPtr, width); + srcPtr += width; + imdVidMem += sW; + } + } else if (type == 3) { // RLE block + warning("Frame render method 3: RLE block"); + return 0; + } else { + warning("Unkown frame rendering method %d (0x%X)", type, type); + return 0; + } + + return 1; +} + } // End of namespace Gob diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h index 678fde3967..39228c7bca 100644 --- a/engines/gob/coktelvideo.h +++ b/engines/gob/coktelvideo.h @@ -223,6 +223,7 @@ protected: uint32 _soundStartTime; uint32 _skipFrames; + uint16 _soundFlags; int16 _soundFreq; uint16 _soundSliceSize; int16 _soundSlicesCount; @@ -244,7 +245,7 @@ protected: void clear(bool del = true); State processFrame(uint16 frame); - uint32 renderFrame(); + uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom); void deLZ77(byte *dest, byte *src); }; @@ -291,6 +292,7 @@ protected: void clear(bool del = true); State processFrame(uint16 frame); + uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom); }; } // End of namespace Gob |