diff options
author | Filippos Karapetis | 2011-02-04 17:51:59 +0000 |
---|---|---|
committer | Filippos Karapetis | 2011-02-04 17:51:59 +0000 |
commit | 512bcf8b907edd69ed7bed2c988f6aa0b8cdfe69 (patch) | |
tree | e16114ba871f957eff4cd0082c84de77c324fabb /engines | |
parent | 94b6d23d44ee9d48b4e4631f7d38d16c012bf56b (diff) | |
download | scummvm-rg350-512bcf8b907edd69ed7bed2c988f6aa0b8cdfe69.tar.gz scummvm-rg350-512bcf8b907edd69ed7bed2c988f6aa0b8cdfe69.tar.bz2 scummvm-rg350-512bcf8b907edd69ed7bed2c988f6aa0b8cdfe69.zip |
SCI: Rewrote the robot playing code in a way similar to other video decoders
- The code now streams videos instead of loading them in memory, without utilizing seeking
- Removed the sound-related robot code from the graphics classes
- Started implementing the code for the sound in robot videos (still not finished)
svn-id: r55772
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/console.cpp | 18 | ||||
-rw-r--r-- | engines/sci/console.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 2 | ||||
-rw-r--r-- | engines/sci/graphics/paint32.cpp | 10 | ||||
-rw-r--r-- | engines/sci/graphics/paint32.h | 1 | ||||
-rw-r--r-- | engines/sci/graphics/robot.cpp | 356 | ||||
-rw-r--r-- | engines/sci/graphics/robot.h | 59 | ||||
-rw-r--r-- | engines/sci/sound/audio.cpp | 13 | ||||
-rw-r--r-- | engines/sci/sound/audio.h | 2 |
9 files changed, 182 insertions, 280 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7d24b1f248..3bb6675ff7 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -121,7 +121,6 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), DCmd_Register("draw_cel", WRAP_METHOD(Console, cmdDrawCel)); #ifdef ENABLE_SCI32 DCmd_Register("draw_robot", WRAP_METHOD(Console, cmdDrawRobot)); - DCmd_Register("play_robot_audio", WRAP_METHOD(Console, cmdPlayRobotAudio)); #endif DCmd_Register("undither", WRAP_METHOD(Console, cmdUndither)); DCmd_Register("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize)); @@ -1529,23 +1528,6 @@ bool Console::cmdDrawRobot(int argc, const char **argv) { return true; } -bool Console::cmdPlayRobotAudio(int argc, const char **argv) { - if (argc < 2) { - DebugPrintf("Draws frames from a robot resource\n"); - DebugPrintf("Usage: %s <resourceId>\n", argv[0]); - DebugPrintf("where <resourceId> is the id of the robot resource to draw\n"); - return true; - } - - uint16 resourceId = atoi(argv[1]); - - if (_engine->_gfxPaint32) { - _engine->_gfxPaint32->debugPlayRobotAudio(resourceId); - } else { - DebugPrintf("command not available in non-sci32 games"); - } - return true; -} #endif bool Console::cmdUndither(int argc, const char **argv) { diff --git a/engines/sci/console.h b/engines/sci/console.h index 140b0883e0..670c89e672 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -93,7 +93,6 @@ private: bool cmdDrawCel(int argc, const char **argv); #ifdef ENABLE_SCI32 bool cmdDrawRobot(int argc, const char **argv); - bool cmdPlayRobotAudio(int argc, const char **argv); #endif bool cmdUndither(int argc, const char **argv); bool cmdPicVisualize(int argc, const char **argv); diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 5ec8b3f323..0c0e3bf720 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1423,7 +1423,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { warning("kRobot(%d)", subop); break; case 8: // sync - robot->drawNextFrame(); + robot->processNextFrame(); // Signal the engine scripts that the video is done if (robot->getCurFrame() == robot->getFrameCount()) writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG); diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index 974efd371a..2fb4b832e5 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -85,17 +85,9 @@ void GfxPaint32::debugDrawRobot(GuiResourceId robotId) { GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, _palette); test->init(robotId, 0, 0); while (test->getCurFrame() + 1 < test->getFrameCount()) { - test->drawNextFrame(); + test->processNextFrame(); } delete test; } -void GfxPaint32::debugPlayRobotAudio(GuiResourceId robotId) { - GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, _palette); - test->init(robotId, 0, 0); - test->playAudio(); - delete test; -} - - } // End of namespace Sci diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h index 7fbaf4594e..a048d7f307 100644 --- a/engines/sci/graphics/paint32.h +++ b/engines/sci/graphics/paint32.h @@ -49,7 +49,6 @@ public: void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); void debugDrawRobot(GuiResourceId robotId); - void debugPlayRobotAudio(GuiResourceId robotId); private: ResourceManager *_resMan; diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp index f45d3cb552..0d2142ebde 100644 --- a/engines/sci/graphics/robot.cpp +++ b/engines/sci/graphics/robot.cpp @@ -40,7 +40,8 @@ #include "common/file.h" #include "common/system.h" -#include "common/memstream.h" +#include "common/stream.h" +#include "common/substream.h" namespace Sci { @@ -60,9 +61,10 @@ namespace Sci { // around the screen and go behind other objects. (...) #ifdef ENABLE_SCI32 + GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette) - : _resMan(resMan), _screen(screen), _palette(palette), _resourceData(0), - _imageStart(0), _audioStart(0), _audioLen(0), _outputBuffer(0), _outputBufferSize(0) { + : _resMan(resMan), _screen(screen), _palette(palette), _outputBuffer(0), + _outputBufferSize(0), _audioStream(0) { _resourceId = -1; _x = _y = 0; } @@ -72,151 +74,91 @@ GfxRobot::~GfxRobot() { } void GfxRobot::init(GuiResourceId resourceId, uint16 x, uint16 y) { - char fileName[10]; - uint32 fileSize; - - // resourceId = 1305; // debug - _resourceId = resourceId; + //_resourceId = 1305; // debug _x = x; _y = y; _curFrame = 0; + + char fileName[10]; sprintf(fileName, "%d.rbt", _resourceId); - Common::File robotFile; - if (robotFile.open(fileName)) { - _resourceData = new byte[robotFile.size()]; - robotFile.read(_resourceData, robotFile.size()); - fileSize = robotFile.size(); - robotFile.close(); - } else { + if (!_robotFile.open(fileName)) { warning("Unable to open robot file %s", fileName); return; } + readHeaderChunk(); + // There are several versions of robot files, ranging from 3 to 6. // v3: no known examples // v4: PQ:SWAT // v5: SCI2.1 and SCI3 games // v6: SCI3 games - _version = _resourceData[6]; - - // Currently, we only support robot version 5. Robot version - _frameCount = READ_LE_UINT16(_resourceData + 14); - - // There is another value in the header, at offset 0x12, which - // equals this value plus 14 (audio header size) in the cases - // I've seen so far. Dunno which one to use, really. - _audioSize = READ_LE_UINT16(_resourceData + 60); - - //_frameSize = READ_LE_UINT32(_resourceData + 34); - _hasSound = (_resourceData[25] != 0); - - _palOffset = 60; - - // Some robot files have sound, which doesn't start from frame 0 - // (e.g. Phantasmagoria, robot 1305) - // Yes, strangely, the word at offset 10 is non-zero if it DOESN'T have a preload - // in that case, the word is equal to that value which would otherwise be stored - // in the audio header (i.e. _audioSize above) - if (_hasSound && READ_LE_UINT16(_resourceData + 10) == 0) - _palOffset += READ_LE_UINT32(_resourceData + 60) + 14; - - switch (_version) { - case 3: - // Unsupported, and there doesn't seem to be any game that actually - // uses this, thus error out so that we find out where this is used - error("Unknown robot version: %d", _version); - break; + switch (_header.version) { case 4: // used in PQ:SWAT // Unsupported - // TODO: Add support for this version warning("TODO: add support for v4 robot videos"); - _curFrame = _frameCount; // jump to the last frame + _curFrame = _header.frameCount; // jump to the last frame return; - case 5: // used in most SCI2.1 games + case 5: // used in most SCI2.1 games and in some SCI3 robots + case 6: // used in SCI3 games // Supported break; - case 6: // introduced in SCI3 - // Unsupported - // TODO: Add support for this version - warning("TODO: add support for v6 robot videos"); - break; default: // Unsupported, error out so that we find out where this is used - error("Unknown robot version: %d", _version); + error("Unknown robot version: %d", _header.version); } - getFrameOffsets(); - assert(_imageStart[_frameCount] == fileSize); + _frameTotalSize = new uint32[_header.frameCount]; +#if 0 + if (_header.hasSound) { + _audioStream = Audio::makeQueuingAudioStream(22050, true); + g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_audioHandle, _audioStream); + } +#endif - setPalette(); + readPaletteChunk(); + readFrameSizesChunk(); - debug("Robot %d, %d frames, sound: %s\n", resourceId, _frameCount, _hasSound ? "yes" : "no"); + debug("Robot %d, %d frames, sound: %s\n", resourceId, _header.frameCount, _header.hasSound ? "yes" : "no"); } -void GfxRobot::getFrameOffsets() { - int *audioEnd = new int[_frameCount]; - int *videoEnd = new int[_frameCount]; - uint32 frameDataOffset; +void GfxRobot::readHeaderChunk() { + // Header (60 bytes) + _robotFile.skip(6); + _header.version = _robotFile.readUint16LE(); + _robotFile.skip(2); + _header.audioSilenceSize = _robotFile.readUint16LE(); + _robotFile.skip(2); + _header.frameCount = _robotFile.readUint16LE(); + _header.paletteDataSize = _robotFile.readUint16LE(); + _robotFile.skip(7); + _header.hasSound = _robotFile.readByte(); + _robotFile.skip(34); - switch (_version) { - case 5: - for (int i = 0; i < _frameCount; ++i) { - videoEnd[i] = READ_LE_UINT16(_resourceData + _palOffset + 1200 + i * 2); - audioEnd[i] = READ_LE_UINT16(_resourceData + _palOffset + 1200 + _frameCount * 2 + i * 2); - } - frameDataOffset = _palOffset + 0x4b0 + 0x400 + 0x200 + _frameCount * 4; - break; - case 6: - for (int i = 0; i < _frameCount; ++i) { - videoEnd[i] = READ_LE_UINT32(_resourceData + _palOffset + 1200 + i * 4); - audioEnd[i] = READ_LE_UINT32(_resourceData + _palOffset + 1200 + _frameCount * 4 + i * 4); - } - frameDataOffset = _palOffset + 0x4b0 + 0x400 + 0x200 + _frameCount * 8; - break; - default: - error("Can't yet handle index table for robot version %d", _version); - return; + // Some robot files have sound, which doesn't start from frame 0 + // (e.g. Phantasmagoria, robot 1305). In this case, there won't + // be audio silence in the header, but there will be an extra audio + // preload chunk before the palette chunk. Skip past it and its + // 14-byte header. + if (_header.hasSound && !_header.audioSilenceSize) { + // The header is 14 bytes: the chunk size + 10 more + uint32 preloadChunkSize = _robotFile.readUint32LE(); + _robotFile.skip(preloadChunkSize + 10); } - - - // Pad to nearest 2 kilobytes - if (frameDataOffset & 0x7ff) - frameDataOffset = (frameDataOffset & ~0x7ff) + 0x800; - - _imageStart = new uint32[_frameCount + 1]; - _audioStart = new uint32[_frameCount]; - _audioLen = new uint32[_frameCount]; - - _imageStart[0] = frameDataOffset; - - // Plus one so we can assert on this in the calling routine - // The last one should point to end-of-file, unless I'm misunderstanding something - for (int i = 1; i < _frameCount + 1; ++i) - _imageStart[i] = _imageStart[i - 1] + audioEnd[i - 1]; - for (int i = 0; i < _frameCount; ++i) - _audioStart[i] = _imageStart[i] + videoEnd[i]; - for (int i = 0; i < _frameCount; ++i) - _audioLen[i] = _imageStart[i + 1] - _audioStart[i]; - - delete[] audioEnd; - delete[] videoEnd; } -void GfxRobot::setPalette() { - byte *paletteData = _resourceData + _palOffset; - uint16 paletteSize = READ_LE_UINT16(_resourceData + 16); - +void GfxRobot::readPaletteChunk() { + byte *paletteChunk = new byte[_header.paletteDataSize]; + _robotFile.read(paletteChunk, _header.paletteDataSize); + int startIndex = READ_LE_UINT16(paletteChunk + 25); + int colorCount = READ_LE_UINT16(paletteChunk + 29); Palette resourcePal; + _palette->createFromData(paletteChunk, _header.paletteDataSize, &resourcePal); + delete[] paletteChunk; byte robotPal[256 * 4]; - int startIndex = READ_LE_UINT16(paletteData + 25); - int colorCount = READ_LE_UINT16(paletteData + 29); - - warning("%d palette entries starting at %d", colorCount, startIndex); - - _palette->createFromData(paletteData, paletteSize, &resourcePal); for (int i = 0; i < 256; ++i) { _savedPal[i * 4 + 0] = _palette->_sysPalette.colors[i].r; @@ -238,134 +180,124 @@ void GfxRobot::setPalette() { g_system->setPalette(robotPal, 0, 256); } -void GfxRobot::drawNextFrame() { - uint16 width, height; - // Make sure that we haven't reached the end of the video already - if (_curFrame == _frameCount) - return; - - assembleVideoFrame(_curFrame); - getFrameDimensions(_curFrame, width, height); - - g_system->copyRectToScreen(_outputBuffer, width, _x, _y, width, height * getFrameScale(_curFrame) / 100); - g_system->updateScreen(); - g_system->delayMillis(100); +void GfxRobot::readFrameSizesChunk() { + switch (_header.version) { + case 5: // sizes are 16-bit integers + // Skip table with frame image sizes, as we don't need it + _robotFile.skip(_header.frameCount * 2); + for (int i = 0; i < _header.frameCount; ++i) + _frameTotalSize[i] = _robotFile.readUint16LE(); + break; + case 6: // sizes are 32-bit integers + // Skip table with frame image sizes, as we don't need it + _robotFile.skip(_header.frameCount * 4); + for (int i = 0; i < _header.frameCount; ++i) + _frameTotalSize[i] = _robotFile.readUint32LE(); + break; + default: + error("Can't yet handle index table for robot version %d", _header.version); + } - _curFrame++; + _robotFile.skip(1024 + 512); // Skip unknown tables 1 and 2 - if (_curFrame == _frameCount) { - // End of robot video, restore palette - g_system->setPalette(_savedPal, 0, 256); - _resourceId = -1; - freeData(); + // Pad to nearest 2 kilobytes + uint32 curPos = _robotFile.pos(); + if (curPos & 0x7ff) { + curPos = (curPos & ~0x7ff) + 2048; + _robotFile.seek(curPos); } } -void GfxRobot::assembleVideoFrame(uint16 frame) { - byte *videoData = _resourceData + _imageStart[frame]; - uint16 frameFragments = READ_LE_UINT16(videoData + 18); - - uint32 decompressedSize = 0; - - DecompressorLZS lzs; +void GfxRobot::processNextFrame() { + // Make sure that we haven't reached the end of the video already + if (_curFrame == _header.frameCount) + return; - videoData = _resourceData + _imageStart[frame] + 24; - - for (int i = 0; i < frameFragments; ++i) { - uint32 fragmentCompressed = READ_LE_UINT32(videoData); - uint32 fragmentUncompressed = READ_LE_UINT32(videoData + 4); + // Read frame header (24 bytes) + _robotFile.skip(3); + byte frameScale = _robotFile.readByte(); + uint16 frameWidth = _robotFile.readUint16LE(); + uint16 frameHeight = _robotFile.readUint16LE(); + _robotFile.skip(8); // x, y, width and height of the frame + uint16 compressedSize = _robotFile.readUint16LE(); + uint16 frameFragments = _robotFile.readUint16LE(); + _robotFile.skip(4); // unknown - decompressedSize += fragmentUncompressed; - videoData += 10 + fragmentCompressed; - } + uint32 decompressedSize = frameWidth * (frameHeight * frameScale / 100); - // Causes assertions in various places, such as Lighthouse/Demo 693.RBT - // uint16 frameWidth = READ_LE_UINT16(_resourceData + _imageStart[frame] + 4); - // uint16 frameHeight = READ_LE_UINT16(_resourceData + _imageStart[frame] + 6); - // assert(decompressedSize == (uint32)(frameWidth * frameHeight) * getFrameScale(frame) / 100); - - // Reallocate the output buffer, if its size has changed - if (decompressedSize != _outputBufferSize) { + // Reallocate the output buffer, if its size has increased + if (decompressedSize > _outputBufferSize) { delete[] _outputBuffer; _outputBuffer = new byte[decompressedSize]; } - + _outputBufferSize = decompressedSize; - uint32 assemblePtr = 0; - - videoData = _resourceData + _imageStart[frame] + 24; - - for (int i = 0; i < frameFragments; ++i) { - uint32 fragmentCompressed = READ_LE_UINT32(videoData); - uint32 fragmentUncompressed = READ_LE_UINT32(videoData + 4); - uint16 compressionType = READ_LE_UINT16(videoData + 8); - - switch (compressionType) { - case 0: { - Common::MemoryReadStream compressedFrame(videoData + 10, fragmentCompressed, DisposeAfterUse::NO); - - lzs.unpack(&compressedFrame, _outputBuffer + assemblePtr, fragmentCompressed, fragmentUncompressed); - assemblePtr += fragmentUncompressed; - break; - } - case 2: // Untested - memcpy(_outputBuffer + assemblePtr, videoData + 10, fragmentCompressed); - assemblePtr += fragmentUncompressed; - break; + DecompressorLZS lzs; + byte *outPtr = _outputBuffer; + + for (uint16 i = 0; i < frameFragments; ++i) { + uint32 compressedFragmentSize = _robotFile.readUint32LE(); + uint32 decompressedFragmentSize = _robotFile.readUint32LE(); + uint16 compressionType = _robotFile.readUint16LE(); + + if (compressionType == 0) { + Common::SeekableSubReadStream fragmentStream(&_robotFile, _robotFile.pos(), _robotFile.pos() + compressedFragmentSize); + lzs.unpack(&fragmentStream, outPtr, compressedFragmentSize, decompressedFragmentSize); + } else if (compressionType == 2) { // untested + _robotFile.read(outPtr, compressedFragmentSize); + } else { + error("Unknown frame compression found: %d", compressionType); } - - videoData += 10 + fragmentCompressed; - } - assert(assemblePtr == decompressedSize); - - // FILE *f = fopen("/tmp/flap", "w"); - // fwrite(_outputBuffer, 1, decompressedSize, f); - // fclose(f); - // exit(1); -} - -void GfxRobot::getFrameDimensions(uint16 frame, uint16 &width, uint16 &height) { - byte *videoData = _resourceData + _imageStart[frame]; + outPtr += decompressedFragmentSize; + } - width = READ_LE_UINT16(videoData + 4); - height = READ_LE_UINT16(videoData + 6); -} + uint32 audioChunkSize = _frameTotalSize[_curFrame] - (24 + compressedSize); + // TODO: Audio #if 0 -Common::Rect GfxRobot::getFrameRect(uint16 frame) { - byte *videoData = _resourceData + _imageStart[frame]; - - uint16 x = READ_LE_UINT16(videoData + 8); - uint16 y = READ_LE_UINT16(videoData + 10); - uint16 w = READ_LE_UINT16(videoData + 12); - uint16 h = READ_LE_UINT16(videoData + 14); + // Queue the next audio frame + if (_header.hasSound) { + uint16 decodedSize = _robotFile.readUint16LE(); + _robotFile.skip(2); // skip audio buffer position - return Common::Rect(x, y, x + w, y + h); -} + byte *audioFrame = g_sci->_audio->getDecodedRobotAudioFrame(&_robotFile, audioChunkSize - 4); + _audioStream->queueBuffer(audioFrame, decodedSize, DisposeAfterUse::NO, Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO); + } else { + _robotFile.skip(audioChunkSize); + } +#else + _robotFile.skip(audioChunkSize); #endif -byte GfxRobot::getFrameScale(uint16 frame) { - byte *videoData = _resourceData + _imageStart[frame]; - return videoData[3]; -} + // Show frame + g_system->copyRectToScreen(_outputBuffer, frameWidth, _x, _y, frameWidth, frameHeight * frameScale / 100); + g_system->updateScreen(); + g_system->delayMillis(100); + + _curFrame++; -void GfxRobot::playAudio() { - if (_hasSound) { - Audio::SoundHandle _audioHandle; - Audio::AudioStream *audioStream = g_sci->_audio->getRobotAudioStream(_resourceData); - g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); + if (_curFrame == _header.frameCount) { + // End of robot video, restore palette + g_system->setPalette(_savedPal, 0, 256); + _resourceId = -1; + freeData(); } } void GfxRobot::freeData() { - delete[] _resourceData; _resourceData = 0; - delete[] _imageStart; _imageStart = 0; - delete[] _audioStart; _audioStart = 0; - delete[] _audioLen; _audioLen = 0; +#if 0 + if (_header.hasSound) { + g_system->getMixer()->stopHandle(_audioHandle); + //delete _audioStream; _audioStream = 0; + } +#endif + delete[] _frameTotalSize; _frameTotalSize = 0; delete[] _outputBuffer; _outputBuffer = 0; + _outputBufferSize = 0; + _robotFile.close(); } #endif diff --git a/engines/sci/graphics/robot.h b/engines/sci/graphics/robot.h index f1b9324b6a..044f84eefe 100644 --- a/engines/sci/graphics/robot.h +++ b/engines/sci/graphics/robot.h @@ -26,34 +26,46 @@ #ifndef SCI_GRAPHICS_ROBOT_H #define SCI_GRAPHICS_ROBOT_H -namespace Sci { +#include "common/file.h" + +#include "sound/audiostream.h" +#include "sound/mixer.h" +#include "sound/decoders/raw.h" -#define ROBOT_FILE_STARTOFDATA 58 +namespace Sci { #ifdef ENABLE_SCI32 + +struct RobotHeader { + // 6 bytes, identifier bytes + uint16 version; + // 2 bytes, unknown + uint16 audioSilenceSize; + // 2 bytes, unknown + uint16 frameCount; + uint16 paletteDataSize; + // 6 bytes, unknown + byte hasSound; + // 35 bytes, unknown +}; + class GfxRobot { public: GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette); ~GfxRobot(); void init(GuiResourceId resourceId, uint16 x, uint16 y); - void drawNextFrame(); + void processNextFrame(); uint16 getCurFrame() { return _curFrame; } - uint16 getFrameCount() { return _frameCount; } + uint16 getFrameCount() { return _header.frameCount; } bool isPlaying() { return _resourceId != -1; } void playAudio(); private: - void initData(GuiResourceId resourceId); - void getFrameOffsets(); - void assembleVideoFrame(uint16 frame); - void getFrameDimensions(uint16 frame, uint16 &width, uint16 &height); -#if 0 - // Unused - Common::Rect getFrameRect(uint16 frame); -#endif - byte getFrameScale(uint16 frame); // Scale factor (multiplied by 100). More like custom height, but why use a percentage for it? - void setPalette(); + void readHeaderChunk(); + void readPaletteChunk(); + void readFrameSizesChunk(); + void freeData(); ResourceManager *_resMan; @@ -61,23 +73,18 @@ private: GfxPalette *_palette; GuiResourceId _resourceId; - byte *_resourceData; byte _savedPal[256 * 4]; - byte _version; // robot version + Common::File _robotFile; + Audio::QueuingAudioStream *_audioStream; + Audio::SoundHandle _audioHandle; + + RobotHeader _header; + uint16 _x; uint16 _y; - //uint16 _width; - //uint16 _height; - uint16 _frameCount; - uint32 _frameSize; // is width * height (pixelCount) - uint16 _audioSize; - bool _hasSound; - uint32 _palOffset; - uint32 *_imageStart; - uint32 *_audioStart; - uint32 *_audioLen; uint16 _curFrame; + uint32 *_frameTotalSize; byte *_outputBuffer; uint32 _outputBufferSize; diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 1d2d6e8655..4d0e52a2b8 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -243,18 +243,9 @@ static byte *readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, return buffer; } -// FIXME: This doesn't work correctly yet, perhaps there are differences in the -// way the audio in robot files is handled -Audio::RewindableAudioStream *AudioPlayer::getRobotAudioStream(byte *buffer) { - const uint16 rbtHeaderSize = 19; // TODO: is this right? - const uint16 rbtAudioRate = 22050; // Seems to be hardcoded for all Robot videos - byte audioFlags = *(buffer + 6); +byte *AudioPlayer::getDecodedRobotAudioFrame(Common::SeekableReadStream *str, uint32 encodedSize) { byte flags = 0; - uint32 audioSize = READ_LE_UINT16(buffer + 15) - rbtHeaderSize; - - Common::MemoryReadStream dataStream(buffer + rbtHeaderSize - 1, audioSize, DisposeAfterUse::NO); - byte *data = readSOLAudio(&dataStream, audioSize, audioFlags, flags); - return Audio::makeRawStream(data, audioSize, rbtAudioRate, flags); + return readSOLAudio(str, encodedSize, 0, flags); } Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 volume, int *sampleLen) { diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h index 1ad9acc58e..92d7b946f5 100644 --- a/engines/sci/sound/audio.h +++ b/engines/sci/sound/audio.h @@ -69,8 +69,8 @@ public: void setAudioRate(uint16 rate) { _audioRate = rate; } Audio::SoundHandle *getAudioHandle() { return &_audioHandle; } - Audio::RewindableAudioStream *getRobotAudioStream(byte *buffer); Audio::RewindableAudioStream *getAudioStream(uint32 number, uint32 volume, int *sampleLen); + byte *getDecodedRobotAudioFrame(Common::SeekableReadStream *str, uint32 encodedSize); int getAudioPosition(); int startAudio(uint16 module, uint32 tuple); int wPlayAudio(uint16 module, uint32 tuple); |