aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp18
-rw-r--r--engines/sci/console.h1
-rw-r--r--engines/sci/engine/kgraphics.cpp2
-rw-r--r--engines/sci/graphics/paint32.cpp10
-rw-r--r--engines/sci/graphics/paint32.h1
-rw-r--r--engines/sci/graphics/robot.cpp356
-rw-r--r--engines/sci/graphics/robot.h59
-rw-r--r--engines/sci/sound/audio.cpp13
-rw-r--r--engines/sci/sound/audio.h2
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);