aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/cdrom.cpp17
-rw-r--r--engines/gob/coktelvideo.cpp1289
-rw-r--r--engines/gob/coktelvideo.h313
-rw-r--r--engines/gob/dataio.cpp151
-rw-r--r--engines/gob/dataio.h47
-rw-r--r--engines/gob/detection.cpp719
-rw-r--r--engines/gob/draw.cpp85
-rw-r--r--engines/gob/draw.h19
-rw-r--r--engines/gob/draw_v2.cpp39
-rw-r--r--engines/gob/game.cpp103
-rw-r--r--engines/gob/game.h8
-rw-r--r--engines/gob/game_v1.cpp3
-rw-r--r--engines/gob/game_v2.cpp61
-rw-r--r--engines/gob/global.cpp2
-rw-r--r--engines/gob/gob.cpp289
-rw-r--r--engines/gob/gob.h44
-rw-r--r--engines/gob/goblin.cpp3
-rw-r--r--engines/gob/goblin_v2.cpp3
-rw-r--r--engines/gob/goblin_v3.cpp3
-rw-r--r--engines/gob/imd.cpp1249
-rw-r--r--engines/gob/imd.h143
-rw-r--r--engines/gob/init.cpp27
-rw-r--r--engines/gob/inter.cpp2
-rw-r--r--engines/gob/inter.h42
-rw-r--r--engines/gob/inter_bargon.cpp42
-rw-r--r--engines/gob/inter_v1.cpp51
-rw-r--r--engines/gob/inter_v2.cpp197
-rw-r--r--engines/gob/inter_v3.cpp12
-rw-r--r--engines/gob/inter_v4.cpp786
-rw-r--r--engines/gob/map.cpp2
-rw-r--r--engines/gob/module.mk6
-rw-r--r--engines/gob/mult.h20
-rw-r--r--engines/gob/mult_v1.cpp12
-rw-r--r--engines/gob/mult_v2.cpp59
-rw-r--r--engines/gob/saveload.h9
-rw-r--r--engines/gob/saveload_v2.cpp4
-rw-r--r--engines/gob/saveload_v3.cpp39
-rw-r--r--engines/gob/scenery.cpp2
-rw-r--r--engines/gob/util.cpp17
-rw-r--r--engines/gob/video.cpp14
-rw-r--r--engines/gob/video.h1
-rw-r--r--engines/gob/videoplayer.cpp333
-rw-r--r--engines/gob/videoplayer.h86
43 files changed, 4464 insertions, 1889 deletions
diff --git a/engines/gob/cdrom.cpp b/engines/gob/cdrom.cpp
index 6b32720cff..2ee8595ad3 100644
--- a/engines/gob/cdrom.cpp
+++ b/engines/gob/cdrom.cpp
@@ -68,29 +68,30 @@ void CDROM::readLIC(const char *fname) {
_vm->_dataIO->getUnpackedData(tmp);
handle = _vm->_dataIO->openData(tmp);
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
- version = _vm->_dataIO->readUint16(handle);
- startChunk = _vm->_dataIO->readUint16(handle);
- _numTracks = _vm->_dataIO->readUint16(handle);
+ version = stream->readUint16LE();
+ startChunk = stream->readUint16LE();
+ _numTracks = stream->readUint16LE();
if (version != 3)
error("%s: Unknown version %d", fname, version);
- _vm->_dataIO->seekData(handle, 50, SEEK_SET);
+ stream->seek(50);
for (int i = 0; i < startChunk; i++) {
- pos = _vm->_dataIO->readUint16(handle);
+ pos = stream->readUint16LE();
if (!pos)
break;
- _vm->_dataIO->seekData(handle, pos, SEEK_CUR);
+ stream->skip(pos);
}
_LICbuffer = new byte[_numTracks * 22];
- _vm->_dataIO->readData(handle, _LICbuffer, _numTracks * 22);
+ stream->read(_LICbuffer, _numTracks * 22);
- _vm->_dataIO->closeData(handle);
+ delete stream;
}
void CDROM::freeLICbuffer() {
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
new file mode 100644
index 0000000000..16df54d85f
--- /dev/null
+++ b/engines/gob/coktelvideo.cpp
@@ -0,0 +1,1289 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/endian.h"
+#include "common/system.h"
+
+#include "gob/coktelvideo.h"
+
+namespace Gob {
+
+Imd::Imd() {
+ clear(false);
+}
+
+Imd::~Imd() {
+ clear();
+}
+
+bool Imd::load(Common::SeekableReadStream &stream) {
+ unload();
+
+ _stream = &stream;
+
+ // Version
+ uint16 handle = _stream->readUint16LE();
+ _version = _stream->readByte();
+
+ // Version checking
+ if ((handle != 0) || (_version < 2)) {
+ warning("IMD Version incorrect (%d,%X)", handle, _version);
+ unload();
+ return false;
+ }
+
+ // Rest header
+ _features = _stream->readByte();
+ _framesCount = _stream->readUint16LE();
+ _x = _stream->readSint16LE();
+ _y = _stream->readSint16LE();
+ _width = _stream->readSint16LE();
+ _height = _stream->readSint16LE();
+ _flags = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint16LE();
+
+ // IMDs always have video
+ _features |= kFeaturesVideo;
+
+ // Palette
+ _stream->read((byte *) _palette, 768);
+
+ // Standard coordinates
+ if (_version >= 3) {
+ _stdX = _stream->readUint16LE();
+ if (_stdX > 1) {
+ warning("IMD: More than one standard coordinate quad found (%d)", _stdX);
+ unload();
+ return false;
+ }
+ if (_stdX != 0) {
+ _stdX = _stream->readSint16LE();
+ _stdY = _stream->readSint16LE();
+ _stdWidth = _stream->readSint16LE();
+ _stdHeight = _stream->readSint16LE();
+ _features |= kFeaturesStdCoords;
+ } else
+ _stdX = -1;
+ } else
+ _stdX = -1;
+
+ // Offset to frame positions table
+ uint32 framesPosPos = 0;
+ if (_version >= 4) {
+ framesPosPos = _stream->readUint32LE();
+ if (framesPosPos != 0) {
+ _framesPos = new uint32[_framesCount];
+ assert(_framesPos);
+ _features |= kFeaturesFramesPos;
+ }
+ }
+
+ // Offset to frame coordinates
+ uint32 framesCoordsPos = 0;
+ if (_features & kFeaturesFrameCoords)
+ framesCoordsPos = _stream->readUint32LE();
+
+ // Sound
+ if (_features & kFeaturesSound) {
+ _soundFreq = _stream->readSint16LE();
+ _soundSliceSize = _stream->readSint16LE();
+ _soundSlicesCount = _stream->readSint16LE();
+
+ if (_soundFreq < 0)
+ _soundFreq = -_soundFreq;
+
+ if (_soundSlicesCount < 0)
+ _soundSlicesCount = -_soundSlicesCount - 1;
+
+ if (_soundSlicesCount > 40) {
+ warning("IMD: More than 40 sound slices found (%d)", _soundSlicesCount);
+ unload();
+ return false;
+ }
+
+ _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
+ _frameLength = _soundSliceLength;
+
+ _soundStage = 1;
+ _hasSound = true;
+
+ _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
+ } else
+ _frameLength = 1000 / 12; // 12 FPS for a video without sound
+
+ // Sizes of the frame data and extra video buffer
+ if (_features & kFeaturesDataSize) {
+ _frameDataSize = _stream->readUint16LE();
+ if (_frameDataSize == 0) {
+ _frameDataSize = _stream->readUint32LE();
+ _vidBufferSize = _stream->readUint32LE();
+ } else
+ _vidBufferSize = _stream->readUint16LE();
+ } else {
+ _frameDataSize = _width * _height + 500;
+ if (!(_flags & 0x100) || (_flags & 0x1000))
+ _vidBufferSize = _frameDataSize;
+ }
+
+ // Frame positions table
+ if (_framesPos) {
+ _stream->seek(framesPosPos, SEEK_SET);
+ for (int i = 0; i < _framesCount; i++)
+ _framesPos[i] = _stream->readUint32LE();
+ }
+
+ // Frame coordinates table
+ if (_features & kFeaturesFrameCoords) {
+ _stream->seek(framesCoordsPos, SEEK_SET);
+ _frameCoords = new Coord[_framesCount];
+ assert(_frameCoords);
+ for (int i = 0; i < _framesCount; i++) {
+ _frameCoords[i].left = _stream->readSint16LE();
+ _frameCoords[i].top = _stream->readSint16LE();
+ _frameCoords[i].right = _stream->readSint16LE();
+ _frameCoords[i].bottom = _stream->readSint16LE();
+ }
+ }
+
+ // Seek to the first frame
+ _stream->seek(_firstFramePos, SEEK_SET);
+
+ // Allocating working memory
+ _frameData = new byte[_frameDataSize + 500];
+ assert(_frameData);
+ memset(_frameData, 0, _frameDataSize + 500);
+ _vidBuffer = new byte[_vidBufferSize + 500];
+ assert(_vidBuffer);
+ memset(_vidBuffer, 0, _vidBufferSize + 500);
+
+ return true;
+}
+
+void Imd::unload() {
+ clear();
+}
+
+void Imd::setXY(int16 x, int16 y) {
+ // Adjusting the standard coordinates
+ if (_stdX != -1) {
+ if (x >= 0)
+ _stdX = _stdX - _x + x;
+ if (y >= 0)
+ _stdY = _stdY - _y + y;
+ }
+
+ // Going through the coordinate table as well
+ if (_frameCoords) {
+ for (int i = 0; i < _framesCount; i++) {
+ if (_frameCoords[i].left != -1) {
+ if (x >= 0) {
+ _frameCoords[i].left = _frameCoords[i].left - _x + x;
+ _frameCoords[i].right = _frameCoords[i].right - _x + x;
+ }
+ if (y >= 0) {
+ _frameCoords[i].top = _frameCoords[i].top - _y + y;
+ _frameCoords[i].bottom = _frameCoords[i].bottom - _y + y;
+ }
+ }
+ }
+ }
+
+ if (x >= 0)
+ _x = x;
+ if (y >= 0)
+ _y = y;
+}
+
+void Imd::setVideoMemory(byte *vidMem, uint16 width, uint16 height) {
+ deleteVidMem();
+
+ _hasOwnVidMem = false;
+ _vidMem = vidMem;
+ _vidMemWidth = width;
+ _vidMemHeight = height;
+}
+
+void Imd::setVideoMemory() {
+ deleteVidMem();
+
+ if ((_width > 0) && (_height > 0)) {
+ setXY(0, 0);
+ _hasOwnVidMem = true;
+ _vidMem = new byte[_width * _height];
+ _vidMemWidth = _width;
+ _vidMemHeight = _height;
+ }
+}
+
+void Imd::enableSound(Audio::Mixer &mixer) {
+ // Only possible on the first frame
+ if (_curFrame > 0)
+ return;
+
+ _mixer = &mixer;
+ _soundEnabled = true;
+}
+
+void Imd::disableSound() {
+ if (_audioStream) {
+
+ if (_soundStage == 2) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ } else
+ delete _audioStream;
+
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+ _soundEnabled = false;
+ _mixer = 0;
+}
+
+void Imd::seekFrame(int32 frame, int16 whence, bool restart) {
+ if (!_stream)
+ // Nothing to do
+ return;
+
+ // Find the frame to which to seek
+ if (whence == SEEK_CUR)
+ frame += _curFrame;
+ else if (whence == SEEK_END)
+ frame = _framesCount - frame - 1;
+ else if (whence != SEEK_SET)
+ return;
+
+ if ((frame < 0) || (frame >= _framesCount) || (frame == _curFrame))
+ // Nothing to do
+ return;
+
+ // Try every possible way to find a file offset to that frame
+ uint32 framePos = 0;
+ if (frame == 0) {
+ framePos = _firstFramePos;
+ } else if (frame == 1) {
+ framePos = _firstFramePos;
+ _stream->seek(framePos, SEEK_SET);
+ framePos += _stream->readUint16LE() + 4;
+ } else if (_framesPos) {
+ framePos = _framesPos[frame];
+ } else if (restart && (_soundStage == 0)) {
+ for (int i = ((frame > _curFrame) ? _curFrame : 0); i <= frame; i++)
+ processFrame(i);
+ } else
+ error("Frame %d is not directly accessible", frame);
+
+ // Seek
+ _stream->seek(framePos);
+ _curFrame = frame;
+}
+
+CoktelVideo::State Imd::nextFrame() {
+ return processFrame(_curFrame);
+}
+
+void Imd::waitEndFrame() {
+ if (_soundEnabled && _hasSound) {
+ if (_soundStage != 2)
+ return;
+
+ if (_skipFrames == 0) {
+ int32 waitTime = (_curFrame * _soundSliceLength) -
+ (g_system->getMillis() - _soundStartTime);
+
+ if (waitTime < 0) {
+ _skipFrames = -waitTime / _soundSliceLength;
+ warning("Video A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
+ } else if (waitTime > 0)
+ g_system->delayMillis(waitTime);
+
+ } else
+ _skipFrames--;
+ } else
+ g_system->delayMillis(_frameLength);
+}
+
+void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp) {
+ if (!_vidMem)
+ return;
+
+ dest += width * y;
+
+ uint16 copyWidth = MIN<int16>(width - x, _width);
+ uint16 destPitch = width - x;
+ byte *vidMem = _vidMem;
+
+ if (transp < 0) {
+ // No transparency
+ if ((x > 0) || (_width != width)) {
+ // Copy row-by-row
+ for (int i = 0; i < _height; i++) {
+ dest += x;
+ memcpy(dest, vidMem, copyWidth);
+ dest += destPitch;
+ vidMem += _width;
+ }
+
+ } else
+ // Dimensions fit, copy everything at once
+ memcpy(dest, _vidMem, _width * _height);
+
+ return;
+ }
+
+ // Transparency, copy per pixel
+ for (int i = 0; i < _height; i++) {
+ byte *s = vidMem;
+ byte *d = dest;
+
+ d += x;
+ for (int j = 0; j < _width; j++) {
+ if (*s != transp)
+ *d = *s;
+
+ s++;
+ d++;
+ }
+
+ dest += width;;
+ vidMem += _width;
+ }
+}
+
+void Imd::deleteVidMem(bool del) {
+ if (del) {
+ if (_hasOwnVidMem)
+ delete[] _vidMem;
+ }
+
+ _hasOwnVidMem = false;
+ _vidMem = 0;
+ _vidMemWidth = _vidMemHeight = 0;
+}
+
+void Imd::clear(bool del) {
+ if (del) {
+ delete[] _framesPos;
+ delete[] _frameCoords;
+ delete[] _frameData;
+ delete[] _vidBuffer;
+
+ disableSound();
+ }
+
+ _stream = 0;
+
+ _version = 0;
+ _features = 0;
+ _flags = 0;
+ _x = _y = _width = _height = 0;
+ _stdX = _stdY = _stdWidth = _stdHeight = 0;
+ _framesCount = _curFrame = 0;
+ _framesPos = 0;
+ _firstFramePos = 0;
+ _frameCoords = 0;
+
+ _frameDataSize = _vidBufferSize = 0;
+ _frameData = _vidBuffer = 0;
+
+ memset(_palette, 0, 768);
+
+ deleteVidMem(del);
+
+ _hasSound = false;
+ _soundEnabled = false;
+ _soundStage = 0;
+ _soundStartTime = 0;
+ _skipFrames = 0;
+
+ _soundFlags = 0;
+ _soundFreq = 0;
+ _soundSliceSize = 0;
+ _soundSlicesCount = 0;
+ _soundSliceLength = 0;
+
+ _audioStream = 0;
+
+ _frameLength = 0;
+ _lastFrameTime = 0;
+}
+
+CoktelVideo::State Imd::processFrame(uint16 frame) {
+ State state;
+ uint32 cmd = 0;
+ bool hasNextCmd = false;
+ bool startSound = false;
+
+ if (!_stream || (frame >= _framesCount)) {
+ state.flags = kStateBreak;
+ return state;
+ }
+
+ if (frame != _curFrame) {
+ state.flags |= kStateSeeked;
+ seekFrame(frame);
+ }
+
+ 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 = _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 = _frameCoords[frame].left;
+ state.top = _frameCoords[frame].top;
+ state.right = _frameCoords[frame].right;
+ state.bottom = _frameCoords[frame].bottom;
+ state.flags |= kStateFrameCoords;
+ }
+ }
+
+ cmd = _stream->readUint16LE();
+
+ if ((cmd & 0xFFF8) == 0xFFF0) {
+ if (cmd == 0xFFF0) {
+ _stream->seek(2, SEEK_CUR);
+ cmd = _stream->readUint16LE();
+ }
+
+ if (cmd == 0xFFF1) {
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF2) { // Skip (16 bit)
+ cmd = _stream->readUint16LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF3) { // Skip (32 bit)
+ cmd = _stream->readUint32LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ }
+ }
+
+ if (_soundStage != 0) {
+ byte *soundBuf;
+
+ // Next sound slice data
+ if (cmd == 0xFF00) {
+
+ if (!hasNextCmd && _soundEnabled) {
+ soundBuf = new byte[_soundSliceSize];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, _soundSliceSize);
+ unsignedToSigned(soundBuf, _soundSliceSize);
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize);
+ } else
+ _stream->seek(_soundSliceSize, SEEK_CUR);
+
+ cmd = _stream->readUint16LE();
+
+ // Initial sound data (all slices)
+ } else if (cmd == 0xFF01) {
+ int dataLength = _soundSliceSize * _soundSlicesCount;
+
+ if (!hasNextCmd && _soundEnabled) {
+ soundBuf = new byte[dataLength];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, dataLength);
+ unsignedToSigned(soundBuf, dataLength);
+
+ if (_soundStage == 1)
+ startSound = true;
+
+ _audioStream->queueBuffer(soundBuf, dataLength);
+ } else
+ _stream->seek(dataLength, SEEK_CUR);
+
+ cmd = _stream->readUint16LE();
+
+ // Empty sound slice
+ } else if (!hasNextCmd && (_soundEnabled)) {
+ soundBuf = new byte[_soundSliceSize];
+ assert(soundBuf);
+
+ memset(soundBuf, 0, _soundSliceSize);
+
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize);
+ }
+ }
+
+ // Set palette
+ if (cmd == 0xFFF4) {
+ _stream->seek(2, SEEK_CUR);
+ state.flags |= kStatePalette;
+ _stream->read(_palette, 768);
+ cmd = _stream->readUint16LE();
+ }
+
+ hasNextCmd = false;
+
+ // Jump to frame
+ if (cmd == 0xFFFD) {
+
+ frame = _stream->readSint16LE();
+ if (_framesPos) {
+ _curFrame = frame;
+ _stream->seek(_framesPos[frame], SEEK_SET);
+
+ hasNextCmd = true;
+ state.flags |= kStateJump;
+ }
+
+ } else if (cmd == 0xFFFC) {
+
+ state.flags |= 1;
+ cmd = _stream->readUint32LE();
+ _stream->read(_frameData, cmd + 2);
+
+ if (_vidMemWidth <= state.right) {
+ state.left = 0;
+ state.right -= state.left;
+ }
+ if (_vidMemWidth <= state.right)
+ state.right = _vidMemWidth - 1;
+ if (_vidMemHeight <= state.bottom) {
+ state.top = 0;
+ state.bottom -= state.top;
+ }
+ if (_vidMemHeight <= state.bottom)
+ state.bottom = _vidMemHeight -1;
+
+ state.flags |= renderFrame(state.left, state.top, state.right, state.bottom);
+ state.flags |= _frameData[0];
+
+ // Frame video data
+ } else if (cmd != 0) {
+
+ _stream->read(_frameData, cmd + 2);
+
+ state.flags |= renderFrame(state.left, state.top, state.right, state.bottom);
+ state.flags |= _frameData[0];
+
+ } else
+ state.flags |= kStateNoVideoData;
+
+ } while (hasNextCmd);
+
+ if (startSound && _soundEnabled) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
+ _soundStartTime = g_system->getMillis();
+ _skipFrames = 0;
+ _soundStage = 2;
+ }
+
+ _curFrame++;
+ if ((_curFrame == _framesCount) && (_soundStage == 2)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+
+ _lastFrameTime = g_system->getMillis();
+ return state;
+}
+
+uint32 Imd::renderFrame(int16 left, int16 top, int16 right, int16 bottom) {
+ if (!_frameData || !_vidMem || (_width <= 0) || (_height <= 0))
+ return 0;
+
+ uint32 retVal = 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++;
+
+ if (type & 0x10) { // Palette data
+ // One byte index
+ int index = *dataPtr++;
+ // 16 entries with each 3 bytes (RGB)
+ memcpy(_palette + index * 3, dataPtr, MIN((255 - index) * 3, 48));
+
+ retVal = kStatePalette;
+ dataPtr += 48;
+ type ^= 0x10;
+ }
+
+ srcPtr = dataPtr;
+
+ if (type & 0x80) { // Frame data is compressed
+ srcPtr = _vidBuffer;
+ type &= 0x7F;
+ if ((type == 2) && (width == sW)) {
+ deLZ77(imdVidMem, dataPtr);
+ return retVal;
+ } else
+ deLZ77(srcPtr, dataPtr);
+ }
+
+ uint16 pixCount, pixWritten;
+ byte *imdVidMemBak;
+
+ if (type == 2) { // Whole block
+ 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 < 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 == 0x42) { // Whole quarter-wide block
+ for (int i = 0; i < height; i++) {
+ imdVidMemBak = imdVidMem;
+
+ 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 (; height > 1; height -= 2, imdVidMem += sW + sW, srcPtr += width) {
+ memcpy(imdVidMem, srcPtr, width);
+ memcpy(imdVidMem + sW, srcPtr, width);
+ }
+ if (height == -1)
+ memcpy(imdVidMem, srcPtr, width);
+ } else { // Sparse half-high block
+ imdVidMemBak = imdVidMem;
+ for (int i = 0; i < height; i += 2) {
+ pixWritten = 0;
+ while (pixWritten < width) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) { // data
+ pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten);
+ memcpy(imdVidMem, srcPtr, pixCount);
+ memcpy(imdVidMem + sW, srcPtr, pixCount);
+
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else { // "hole"
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW + sW;
+ imdVidMem = imdVidMemBak;
+ }
+ }
+
+ return retVal;
+}
+
+void Imd::deLZ77(byte *dest, byte *src) {
+ int i;
+ byte buf[4370];
+ uint16 chunkLength;
+ uint16 frameLength;
+ uint16 bufPos1;
+ uint16 bufPos2;
+ uint16 tmp;
+ uint8 chunkBitField;
+ uint8 chunkCount;
+ bool mode;
+
+ frameLength = READ_LE_UINT32(src);
+ src += 4;
+
+ if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
+ src += 4;
+ bufPos1 = 273;
+ mode = 1; // 123Ch (cmp al, 12h)
+ } else {
+ bufPos1 = 4078;
+ mode = 0; // 275h (jnz +2)
+ }
+
+ memset(buf, 32, bufPos1);
+ chunkCount = 1;
+ chunkBitField = 0;
+
+ while (frameLength > 0) {
+ chunkCount--;
+ if (chunkCount == 0) {
+ tmp = *src++;
+ chunkCount = 8;
+ chunkBitField = tmp;
+ }
+ if (chunkBitField % 2) {
+ chunkBitField >>= 1;
+ buf[bufPos1] = *src;
+ *dest++ = *src++;
+ bufPos1 = (bufPos1 + 1) % 4096;
+ frameLength--;
+ continue;
+ }
+ chunkBitField >>= 1;
+
+ tmp = READ_LE_UINT16(src);
+ src += 2;
+ chunkLength = ((tmp & 0xF00) >> 8) + 3;
+
+ if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
+ (!mode && (chunkLength == 0)))
+ chunkLength = *src++ + 0x12;
+
+ bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
+ if (((tmp + chunkLength) >= 4096) ||
+ ((chunkLength + bufPos1) >= 4096)) {
+
+ for (i = 0; i < chunkLength; i++, dest++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ bufPos1 = (bufPos1 + 1) % 4096;
+ bufPos2 = (bufPos2 + 1) % 4096;
+ }
+
+ } else if (((tmp + chunkLength) < bufPos1) ||
+ ((chunkLength + bufPos1) < bufPos2)) {
+
+ memcpy(dest, buf + bufPos2, chunkLength);
+ memmove(buf + bufPos1, buf + bufPos2, chunkLength);
+
+ dest += chunkLength;
+ bufPos1 += chunkLength;
+ bufPos2 += chunkLength;
+
+ } else {
+
+ for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ }
+
+ }
+ frameLength -= chunkLength;
+
+ }
+}
+
+const uint16 Vmd::_tableDPCM[128] = {
+ 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
+ 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
+ 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
+ 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
+ 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
+ 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
+ 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
+ 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
+ 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
+ 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
+ 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
+ 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
+ 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
+};
+
+Vmd::Vmd() {
+ clear(false);
+}
+
+Vmd::~Vmd() {
+ clear();
+}
+
+bool Vmd::load(Common::SeekableReadStream &stream) {
+ unload();
+
+ _stream = &stream;
+
+ uint16 headerLength = _stream->readUint16LE();
+ uint16 handle = _stream->readUint16LE();
+ _version = _stream->readUint16LE();
+
+ // Version checking
+ if ((headerLength != 814) || (handle != 0) || (_version != 1)) {
+ warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version);
+ unload();
+ return false;
+ }
+
+ _framesCount = _stream->readUint16LE();
+
+ _x = _stream->readSint16LE();
+ _y = _stream->readSint16LE();
+ _width = _stream->readSint16LE();
+ _height = _stream->readSint16LE();
+ if ((_width != 0) && (_height != 0)) {
+ _hasVideo = true;
+ _features |= kFeaturesVideo;
+ } else
+ _hasVideo = false;
+
+ _flags = _stream->readUint16LE();
+ _partsPerFrame = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint32LE();
+ _stream->skip(4); // Unknown
+
+ _stream->read((byte *) _palette, 768);
+
+ _frameDataSize = _stream->readUint32LE();
+ _vidBufferSize = _stream->readUint32LE();
+
+ if (_hasVideo) {
+ if (_frameDataSize == 0)
+ _frameDataSize = _width * _height + 500;
+ if (_vidBufferSize == 0)
+ _vidBufferSize = _frameDataSize;
+
+ _frameData = new byte[_frameDataSize];
+ assert(_frameData);
+ memset(_frameData, 0, _frameDataSize);
+ _vidBuffer = new byte[_vidBufferSize];
+ assert(_vidBuffer);
+ memset(_vidBuffer, 0, _vidBufferSize);
+ }
+
+ _soundFreq = _stream->readSint16LE();
+ _soundSliceSize = _stream->readSint16LE();
+ _soundSlicesCount = _stream->readSint16LE();
+ _soundFlags = _stream->readUint16LE();
+ _hasSound = (_soundFreq != 0);
+
+ if (_hasSound) {
+ _features |= kFeaturesSound;
+
+ _soundStereo = (_soundFlags & 0x8000) ? 1 : ((_soundFlags & 0x200) ? 2 : 0);
+ if (_soundStereo > 0) {
+ warning("TODO: VMD stereo");
+ unload();
+ return false;
+ }
+
+ if (_soundSliceSize < 0) {
+ _soundBytesPerSample = 2;
+ _soundSliceSize = -_soundSliceSize;
+ }
+
+ _soundSliceLength = (uint16) (1000.0 /
+ ((double) _soundFreq / (double) _soundSliceSize));
+
+ _frameLength = _soundSliceLength;
+
+ _soundStage = 1;
+ _audioStream = Audio::makeAppendableAudioStream(_soundFreq,
+ (_soundBytesPerSample == 2) ? Audio::Mixer::FLAG_16BITS : 0);
+ } else
+ _frameLength = 1000 / 12; // 12 FPS for a video without sound
+
+ uint32 frameInfoOffset = _stream->readUint32LE();
+
+ _stream->seek(frameInfoOffset);
+ _frames = new Frame[_framesCount];
+ for (uint16 i = 0; i < _framesCount; i++) {
+ _frames[i].parts = new Part[_partsPerFrame];
+ _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();
+ _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); // 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();
+ _stream->skip(1); // Unknown
+ _frames[i].parts[j].flags = _stream->readByte();
+
+ } else {
+ // Unknow type
+ _stream->skip(10);
+ }
+
+ }
+ }
+
+ return true;
+}
+
+void Vmd::unload() {
+ clear();
+}
+
+void Vmd::setXY(int16 x, int16 y) {
+
+ for (int i = 0; i < _framesCount; i++) {
+ for (int j = 0; j < _partsPerFrame; j++) {
+
+ if (_frames[i].parts[j].type == kPartTypeVideo) {
+ if (x >= 0) {
+ _frames[i].parts[j].left = _frames[i].parts[j].left - _x + x;
+ _frames[i].parts[j].right = _frames[i].parts[j].right - _x + x;
+ }
+ if (y >= 0) {
+ _frames[i].parts[j].top = _frames[i].parts[j].top - _y + y;
+ _frames[i].parts[j].bottom = _frames[i].parts[j].bottom - _y + y;
+ }
+ }
+
+ }
+ }
+
+ if (x >= 0)
+ _x = x;
+ if (y >= 0)
+ _y = y;
+}
+
+void Vmd::seekFrame(int32 frame, int16 whence, bool restart) {
+ if (!_stream)
+ // Nothing to do
+ return;
+
+ // Find the frame to which to seek
+ if (whence == SEEK_CUR)
+ frame += _curFrame;
+ else if (whence == SEEK_END)
+ frame = _framesCount - frame - 1;
+ else if (whence != SEEK_SET)
+ return;
+
+ if ((frame < 0) || (frame >= _framesCount))
+ // Nothing to do
+ return;
+
+ // Seek
+ _stream->seek(_frames[frame].offset);
+ _curFrame = frame;
+}
+
+CoktelVideo::State Vmd::nextFrame() {
+ State state;
+
+ state = processFrame(_curFrame);
+ _curFrame++;
+ return state;
+}
+
+void Vmd::clear(bool del) {
+ Imd::clear(del);
+
+ if (del) {
+ delete[] _frames;
+ }
+
+ _hasVideo = true;
+
+ _partsPerFrame = 0;
+ _frames = 0;
+
+ _soundBytesPerSample = 1;
+ _soundStereo = 0;
+}
+
+CoktelVideo::State Vmd::processFrame(uint16 frame) {
+ State state;
+ bool startSound = false;
+
+ seekFrame(frame);
+
+ state.flags |= kStateNoVideoData;
+ 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];
+
+ if (part.type == kPartTypeAudio) {
+ // Next sound slice data
+ if (part.flags == 1) {
+
+ if (_soundEnabled)
+ filledSoundSlice(part.size);
+ else
+ _stream->skip(part.size);
+
+ // Initial sound data (all slices)
+ } else if (part.flags == 2) {
+
+ if (_soundEnabled) {
+ uint32 mask = _stream->readUint32LE();
+ filledSoundSlices(part.size - 4, mask);
+
+ if (_soundStage == 1)
+ startSound = true;
+
+ } else
+ _stream->skip(part.size);
+
+ // Empty sound slice
+ } else if (part.flags == 3) {
+
+ if (_soundEnabled && (part.size > 0))
+ emptySoundSlice(part.size);
+ else
+ _stream->skip(part.size);
+
+ }
+
+ } else if (part.type == kPartTypeVideo) {
+ state.flags &= ~kStateNoVideoData;
+
+ // New palette
+ if (part.flags & 2) {
+ uint8 index = _stream->readByte();
+ uint8 count = _stream->readByte();
+
+ _stream->read(_palette + index * 3, (count + 1) * 3);
+ _stream->skip((255 - count) * 3);
+
+ state.flags |= kStatePalette;
+ }
+
+ _stream->read(_frameData, part.size);
+ 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);
+ }
+ }
+
+ if (startSound && _soundEnabled) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
+ _soundStartTime = g_system->getMillis();
+ _skipFrames = 0;
+ _soundStage = 2;
+ }
+
+ if ((_curFrame == (_framesCount - 1)) && (_soundStage == 2)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+
+ _lastFrameTime = g_system->getMillis();
+ 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;
+}
+
+void Vmd::emptySoundSlice(uint32 size) {
+ byte *soundBuf = new byte[size];
+ assert(soundBuf);
+
+ memset(soundBuf, 0, size);
+
+ _audioStream->queueBuffer(soundBuf, size);
+}
+
+void Vmd::soundSlice8bit(uint32 size) {
+ byte *soundBuf = new byte[size];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, size);
+ unsignedToSigned(soundBuf, size);
+
+ _audioStream->queueBuffer(soundBuf, size);
+}
+
+void Vmd::soundSlice16bit(uint32 size, int16 &init) {
+ byte *dataBuf = new byte[size];
+ byte *soundBuf = new byte[size * 2];
+
+ _stream->read(dataBuf, size);
+ deDPCM(soundBuf, dataBuf, init, size);
+ _audioStream->queueBuffer(soundBuf, size * 2);
+
+ delete[] dataBuf;
+}
+
+void Vmd::filledSoundSlice(uint32 size) {
+ if (_soundBytesPerSample == 1) {
+ soundSlice8bit(size);
+ } else if (_soundBytesPerSample == 2) {
+ int16 init = _stream->readSint16LE();
+ soundSlice16bit(size - 1, init);
+ }
+}
+
+void Vmd::filledSoundSlices(uint32 size, uint32 mask) {
+ if (_soundBytesPerSample == 1) {
+ soundSlice8bit(size);
+ return;
+ }
+
+ for (int i = 0; i < (_soundSlicesCount - 1); i++) {
+
+ if (mask & 1)
+ emptySoundSlice(_soundSliceSize * 2);
+ else {
+ int16 init = _stream->readSint16LE();
+ soundSlice16bit(_soundSliceSize, init);
+ }
+
+ mask >>= 1;
+ }
+
+}
+
+void Vmd::deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n) {
+ int16 *out = (int16 *) soundBuf;
+
+ int32 s = init;
+ for (uint32 i = 0; i < n; i++) {
+ if(dataBuf[i] & 0x80)
+ s -= _tableDPCM[dataBuf[i] & 0x7F];
+ else
+ s += _tableDPCM[dataBuf[i]];
+
+ s = CLIP<int32>(s, -32768, 32767);
+ *out++ = TO_BE_16(s);
+ }
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h
new file mode 100644
index 0000000000..a4e5452cce
--- /dev/null
+++ b/engines/gob/coktelvideo.h
@@ -0,0 +1,313 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_COKTELVIDEO_H
+#define GOB_COKTELVIDEO_H
+
+#include "common/stream.h"
+#include "sound/mixer.h"
+#include "sound/audiostream.h"
+
+namespace Gob {
+
+/** Common interface for handling Coktel Vision videos and derivated formats. */
+class CoktelVideo {
+public:
+ enum Features {
+ kFeaturesNone = 0,
+ /** Has an own palette. */
+ kFeaturesPalette = 8,
+ /** Suggests a data size. */
+ kFeaturesDataSize = 0x20,
+ /** Has sound. */
+ kFeaturesSound = 0x40,
+ /** Has specific frame coordinates. */
+ kFeaturesFrameCoords = 0x80,
+ /** Has general standard coordinates. */
+ kFeaturesStdCoords = 0x100,
+ /** Has a frame positions table. */
+ kFeaturesFramesPos = 0x200,
+ /** Has video. */
+ kFeaturesVideo = 0x400
+ };
+
+ enum StateFlags {
+ kStateNone = 0,
+ /** Changed the palette. */
+ kStatePalette = 0x10,
+ /** Performed a jump to another frame. */
+ kStateJump = 0x200,
+ /** Updated according to the specific frame coordinates. */
+ kStateFrameCoords = 0x400,
+ /** Got no frame data. */
+ kStateNoVideoData = 0x800,
+ /** Updated according to the general standard coordinates. */
+ kStateStdCoords = 0x1000,
+ /** Had to explicitely seek to the frame. */
+ kStateSeeked = 0x2000,
+ /** Reached a break-point. */
+ kStateBreak = 0x8000
+ };
+
+ struct State {
+ /** Left-most value of the updated rectangle. */
+ int16 left;
+ /** Top-most value of the updated rectangle. */
+ int16 top;
+ /** Right-most value of the updated rectangle. */
+ int16 right;
+ /** Bottom-most value of the updated rectangle. */
+ int16 bottom;
+ /** Set accordingly to what was done. */
+ uint32 flags;
+
+ State() : left(0), top(0), right(0), bottom(0), flags(0) { }
+ };
+
+ virtual ~CoktelVideo() { }
+
+ /** Returns the features the loaded video possesses. */
+ virtual uint16 getFeatures() const = 0;
+ /** Returns the x coordinate of the video. */
+ virtual int16 getX() const = 0;
+ /** Returns the y coordinate of the video. */
+ virtual int16 getY() const = 0;
+ /** Returns the width of the video. */
+ virtual int16 getWidth() const = 0;
+ /** Returns the height of the video. */
+ virtual int16 getHeight() const = 0;
+ /** Returns the number of frames the loaded video has. */
+ virtual uint16 getFramesCount() const = 0;
+ /** Returns the current frame number.
+ *
+ * This is the current frame after the last nextFrame()-call,
+ * i.e. it's 0 after loading, 1 after the first nextFrame()-call, etc..
+ */
+ virtual uint16 getCurrentFrame() const = 0;
+ /** Returns the frame rate. */
+ virtual int16 getFrameRate() const = 0;
+ /** Returns the number of frames the video lags behind the audio. */
+ virtual uint32 getSyncLag() const = 0;
+ /** Returns the current frame's palette. */
+ virtual const byte *getPalette() const = 0;
+
+ /** Load a video out of a stream. */
+ virtual bool load(Common::SeekableReadStream &stream) = 0;
+ /** Unload the currently loaded video. */
+ virtual void unload() = 0;
+
+ /** Set the coordinations where to draw the video. */
+ virtual void setXY(int16 x, int16 y) = 0;
+ /** Use a specific memory block as video memory. */
+ virtual void setVideoMemory(byte *vidMem, uint16 width, uint16 height) = 0;
+ /** Use an own memory block as video memory. */
+ virtual void setVideoMemory() = 0;
+
+ /** Play sound (if the IMD has sound). */
+ virtual void enableSound(Audio::Mixer &mixer) = 0;
+ /** Don't play sound or stop currently playing sound. */
+ virtual void disableSound() = 0;
+
+ /** Seek to a specific frame.
+ *
+ * @param frame The frame to which to seek.
+ * @param whence The offset from whence the frame is given.
+ * @param restart Restart the video to reach an otherwise inaccessible frame?
+ */
+ virtual void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false) = 0;
+
+ /** Render the next frame. */
+ virtual State nextFrame() = 0;
+ /** Wait for the frame to end. */
+ virtual void waitEndFrame() = 0;
+
+ /** Copy the current frame.
+ *
+ * @param dest The memory to which to copy the current frame
+ * @param x The x position to where to copy.
+ * @param y The y position to where to copy.
+ * @param pitch The buffer's width.
+ * @param transp Which color should be seen as transparent?
+ */
+ virtual void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1) = 0;
+};
+
+/** Coktel Vision's IMD files.
+ */
+class Imd : public CoktelVideo {
+public:
+ Imd();
+ ~Imd();
+
+ uint16 getFeatures() const { return _features; }
+ int16 getX() const { return _x; }
+ int16 getY() const { return _y; }
+ int16 getWidth() const { return _width; }
+ int16 getHeight() const { return _height; }
+ uint16 getFramesCount() const { return _framesCount; }
+ uint16 getCurrentFrame() const { return _curFrame; }
+ int16 getFrameRate() const { if (_hasSound) return 1000 / _soundSliceLength; return 12; }
+ uint32 getSyncLag() const { return _skipFrames; }
+ const byte *getPalette() const { return _palette; }
+
+ bool load(Common::SeekableReadStream &stream);
+ void unload();
+
+ void setXY(int16 x, int16 y);
+ void setVideoMemory(byte *vidMem, uint16 width, uint16 height);
+ void setVideoMemory();
+
+ void enableSound(Audio::Mixer &mixer);
+ void disableSound();
+
+ void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false);
+
+ State nextFrame();
+ void waitEndFrame();
+
+ void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1);
+
+protected:
+ struct Coord {
+ int16 left;
+ int16 top;
+ int16 right;
+ int16 bottom;
+ } PACKED_STRUCT;
+
+ Common::SeekableReadStream *_stream;
+ uint16 _version;
+ uint16 _features;
+ uint16 _flags;
+ int16 _x, _y, _width, _height;
+ int16 _stdX, _stdY, _stdWidth, _stdHeight;
+ uint16 _framesCount, _curFrame;
+ uint32 *_framesPos;
+ uint32 _firstFramePos;
+ Coord *_frameCoords;
+
+ uint32 _frameDataSize, _vidBufferSize;
+ byte *_frameData, *_vidBuffer;
+
+ byte _palette[768];
+
+ bool _hasOwnVidMem;
+ byte *_vidMem;
+ uint16 _vidMemWidth, _vidMemHeight;
+
+ bool _hasSound;
+ bool _soundEnabled;
+ uint8 _soundStage; // (0: no sound, 1: loaded, 2: playing)
+ uint32 _soundStartTime;
+ uint32 _skipFrames;
+
+ uint16 _soundFlags;
+ int16 _soundFreq;
+ int16 _soundSliceSize;
+ int16 _soundSlicesCount;
+ uint16 _soundSliceLength;
+
+ Audio::AppendableAudioStream *_audioStream;
+ Audio::SoundHandle _audioHandle;
+
+ uint32 _frameLength;
+ uint32 _lastFrameTime;
+
+ Audio::Mixer *_mixer;
+
+ void unsignedToSigned(byte *buffer, int length) {
+ while (length-- > 0) *buffer++ ^= 0x80;
+ }
+
+ void deleteVidMem(bool del = true);
+ void clear(bool del = true);
+
+ State processFrame(uint16 frame);
+ uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom);
+ void deLZ77(byte *dest, byte *src);
+};
+
+class Vmd : public Imd {
+public:
+ Vmd();
+ ~Vmd();
+
+ bool load(Common::SeekableReadStream &stream);
+ void unload();
+
+ void setXY(int16 x, int16 y);
+
+ void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false);
+
+ State nextFrame();
+
+protected:
+ enum PartType {
+ kPartTypeAudio = 1,
+ kPartTypeVideo = 2
+ };
+ struct Part {
+ PartType type;
+ uint32 size;
+ int16 left;
+ int16 top;
+ int16 right;
+ int16 bottom;
+ byte flags;
+ } PACKED_STRUCT;
+ struct Frame {
+ uint32 offset;
+ Part *parts;
+
+ Frame() : parts(0) { }
+ ~Frame() { delete[] parts; }
+ } PACKED_STRUCT;
+
+ static const uint16 _tableDPCM[128];
+
+ bool _hasVideo;
+
+ uint16 _partsPerFrame;
+ Frame *_frames;
+
+ byte _soundBytesPerSample;
+ byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
+
+ void clear(bool del = true);
+
+ State processFrame(uint16 frame);
+ uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom);
+
+ void emptySoundSlice(uint32 size);
+ void soundSlice8bit(uint32 size);
+ void soundSlice16bit(uint32 size, int16 &init);
+ void filledSoundSlice(uint32 size);
+ void filledSoundSlices(uint32 size, uint32 mask);
+ void deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_COKTELVIDEO_H
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index 7ded953427..361627caf4 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -33,6 +33,92 @@
namespace Gob {
+DataStream::DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose) {
+ _io = &io;
+ _handle = handle;
+ _size = dSize;
+ _dispose = dispose;
+
+ _data = 0;
+ _stream = 0;
+}
+
+DataStream::DataStream(byte *buf, uint32 dSize, bool dispose) {
+ _data = buf;
+ _size = dSize;
+ _stream = new Common::MemoryReadStream(_data, _size);
+ _dispose = dispose;
+
+ _io = 0;
+ _handle = -1;
+}
+
+DataStream::~DataStream() {
+ delete _stream;
+
+ if (_dispose) {
+ delete[] _data;
+ if ((_handle >= 0) && _io)
+ _io->closeData(_handle);
+ }
+}
+
+uint32 DataStream::pos() const {
+ if (_stream)
+ return _stream->pos();
+
+ uint32 resPos = _io->getChunkPos(_handle);
+ if (resPos != 0xFFFFFFFF)
+ return resPos;
+
+ return _io->file_getHandle(_handle)->pos();
+}
+
+uint32 DataStream::size() const {
+ if (_stream)
+ return _stream->size();
+
+ return _size;
+}
+
+void DataStream::seek(int32 offset, int whence) {
+ if (_stream)
+ _stream->seek(offset, whence);
+
+ int32 resPos = _io->seekChunk(_handle, offset, whence);
+ if (resPos != -1)
+ return;
+
+ _io->file_getHandle(_handle)->seek(offset, whence);
+}
+
+bool DataStream::eos() const {
+ if (_stream)
+ return _stream->eos();
+
+ return pos() >= size();
+}
+
+uint32 DataStream::read(void *dataPtr, uint32 dataSize) {
+ if (_stream)
+ return _stream->read(dataPtr, dataSize);
+
+ if ((_handle < 50) || (_handle >= 128))
+ return _io->file_getHandle(_handle)->read((byte *) dataPtr, dataSize);
+
+ byte *data = (byte *) dataPtr;
+ uint32 haveRead = 0;
+ while (dataSize > 0x3FFF) {
+ _io->readChunk(_handle, (byte *) data, 0x3FFF);
+ dataSize -= 0x3FFF;
+ data += 0x3FFF;
+ haveRead += 0x3FFF;
+ }
+ _io->readChunk(_handle, (byte *) data, dataSize);
+
+ return haveRead + dataSize;
+}
+
DataIO::DataIO(GobEngine *vm) : _vm(vm) {
for (int i = 0; i < MAX_DATA_FILES; i++) {
_dataFiles[i] = 0;
@@ -115,6 +201,10 @@ Common::File *DataIO::file_getHandle(int16 handle) {
return &_filesHandles[handle];
}
+const Common::File *DataIO::file_getHandle(int16 handle) const {
+ return &_filesHandles[handle];
+}
+
int16 DataIO::file_open(const char *path, Common::File::AccessMode mode) {
int16 i;
@@ -226,7 +316,7 @@ int16 DataIO::seekChunk(int16 handle, int32 pos, int16 from) {
return _chunkPos[file * MAX_SLOT_COUNT + slot];
}
-uint32 DataIO::getChunkPos(int16 handle) {
+uint32 DataIO::getChunkPos(int16 handle) const {
int16 file;
int16 slot;
@@ -390,39 +480,23 @@ int16 DataIO::openData(const char *path, Common::File::AccessMode mode) {
return file_open(path, mode);
}
-int32 DataIO::readData(int16 handle, byte *buf, uint16 size) {
- int32 res;
-
- res = readChunk(handle, buf, size);
- if (res >= 0)
- return res;
-
- return file_getHandle(handle)->read(buf, size);
-}
+DataStream *DataIO::openAsStream(int16 handle, bool dispose) {
+ uint32 curPos = getPos(handle);
+ seekData(handle, 0, SEEK_END);
+ uint32 size = getPos(handle);
+ seekData(handle, curPos, SEEK_SET);
-byte DataIO::readByte(int16 handle) {
- byte buf;
-
- readData(handle, &buf, 1);
- return ((byte) buf);
+ return new DataStream(*this, handle, size, dispose);
}
-uint16 DataIO::readUint16(int16 handle) {
- byte buf[2];
-
- readData(handle, buf, 2);
- return READ_LE_UINT16(buf);
-}
-
-uint32 DataIO::readUint32(int16 handle) {
- byte buf[4];
+uint32 DataIO::getPos(int16 handle) {
+ uint32 resPos;
- readData(handle, buf, 4);
- return READ_LE_UINT32(buf);
-}
+ resPos = getChunkPos(handle);
+ if (resPos != 0xFFFFFFFF)
+ return resPos;
-int32 DataIO::writeData(int16 handle, byte *buf, uint16 size) {
- return file_getHandle(handle)->write(buf, size);
+ return file_getHandle(handle)->pos();
}
void DataIO::seekData(int16 handle, int32 pos, int16 from) {
@@ -435,14 +509,14 @@ void DataIO::seekData(int16 handle, int32 pos, int16 from) {
file_getHandle(handle)->seek(pos, from);
}
-uint32 DataIO::getPos(int16 handle) {
- uint32 resPos;
+int32 DataIO::readData(int16 handle, byte *buf, uint16 size) {
+ int32 res;
- resPos = getChunkPos(handle);
- if (resPos != 0xFFFFFFFF)
- return resPos;
+ res = readChunk(handle, buf, size);
+ if (res >= 0)
+ return res;
- return file_getHandle(handle)->pos();
+ return file_getHandle(handle)->read(buf, size);
}
int32 DataIO::getDataSize(const char *name) {
@@ -492,4 +566,11 @@ byte *DataIO::getData(const char *path) {
return data;
}
+DataStream *DataIO::getDataStream(const char *path) {
+ uint32 size = getDataSize(path);
+ byte *data = getData(path);
+
+ return new DataStream(data, size);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index 3ea29c0efe..b30a389865 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -35,7 +35,33 @@ namespace Gob {
#define MAX_FILES 30
#define MAX_DATA_FILES 8
-#define MAX_SLOT_COUNT 4
+#define MAX_SLOT_COUNT 8
+
+class DataIO;
+
+class DataStream : public Common::SeekableReadStream {
+public:
+ DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose = false);
+ DataStream(byte *buf, uint32 dSize, bool dispose = true);
+ virtual ~DataStream();
+
+ virtual uint32 pos() const;
+ virtual uint32 size() const;
+
+ virtual void seek(int32 offset, int whence = SEEK_SET);
+
+ virtual bool eos() const;
+
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+
+private:
+ DataIO *_io;
+ int16 _handle;
+ uint32 _size;
+ byte *_data;
+ Common::MemoryReadStream *_stream;
+ bool _dispose;
+};
class DataIO {
public:
@@ -55,15 +81,11 @@ public:
void closeData(int16 handle);
int16 openData(const char *path,
Common::File::AccessMode mode = Common::File::kFileReadMode);
- int32 readData(int16 handle, byte *buf, uint16 size);
- byte readByte(int16 handle);
- uint16 readUint16(int16 handle);
- uint32 readUint32(int16 handle);
- int32 writeData(int16 handle, byte *buf, uint16 size);
- void seekData(int16 handle, int32 pos, int16 from);
- uint32 getPos(int16 handle);
+ DataStream *openAsStream(int16 handle, bool dispose = false);
+
int32 getDataSize(const char *name);
byte *getData(const char *path);
+ DataStream *getDataStream(const char *path);
DataIO(class GobEngine *vm);
~DataIO();
@@ -85,13 +107,20 @@ protected:
int16 file_open(const char *path,
Common::File::AccessMode mode = Common::File::kFileReadMode);
Common::File *file_getHandle(int16 handle);
+ const Common::File *file_getHandle(int16 handle) const;
int16 getChunk(const char *chunkName);
char freeChunk(int16 handle);
int32 readChunk(int16 handle, byte *buf, uint16 size);
int16 seekChunk(int16 handle, int32 pos, int16 from);
- uint32 getChunkPos(int16 handle);
+ uint32 getChunkPos(int16 handle) const;
int32 getChunkSize(const char *chunkName);
+
+ uint32 getPos(int16 handle);
+ void seekData(int16 handle, int32 pos, int16 from);
+ int32 readData(int16 handle, byte *buf, uint16 size);
+
+friend class DataStream;
};
} // End of namespace Gob
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 1c275185ca..7faef57cc1 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -34,7 +34,8 @@ namespace Gob {
struct GOBGameDescription {
Common::ADGameDescription desc;
- uint32 features;
+ GameType gameType;
+ int32 features;
const char *startTotBase;
};
@@ -48,11 +49,15 @@ static const PlainGameDescriptor gobGames[] = {
{"gob1cd", "Gobliiins CD"},
{"gob2", "Gobliins 2"},
{"gob2cd", "Gobliins 2 CD"},
+ {"ween", "Ween: The Prophecy"},
+ {"bargon", "Bargon Attack"},
+ {"ajworld", "A.J's World of Discovery"},
{"gob3", "Goblins Quest 3"},
{"gob3cd", "Goblins Quest 3 CD"},
- {"bargon", "Bargon Attack"},
- {"ween", "Ween: The Prophecy"},
+ {"lostintime", "Lost in Time"},
+ {"inca2", "Inca II: Wiracocha"},
{"woodruff", "The Bizarre Adventures of Woodruff and the Schnibble"},
+// {"dynasty", "The Last Dynasty"},
{0, 0}
};
@@ -74,7 +79,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_EGA,
+ kGameTypeGob1,
+ kFeaturesEGA,
"intro"
},
{
@@ -86,7 +92,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_EGA,
+ kGameTypeGob1,
+ kFeaturesEGA,
"intro"
},
{ // Supplied by Theruler76 in bug report #1201233
@@ -98,7 +105,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{ // CD 1.000 version.
@@ -110,7 +118,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -122,7 +131,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -134,7 +144,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -146,7 +157,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -158,7 +170,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -170,7 +183,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -182,7 +196,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -194,7 +209,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -206,7 +222,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -218,7 +235,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{
@@ -230,7 +248,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_DEMO
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{
@@ -242,7 +261,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -254,7 +274,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -266,7 +287,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -278,7 +300,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -290,7 +313,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -302,7 +326,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{
@@ -314,7 +339,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by arcepi in bug report #1659884
@@ -326,7 +352,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -338,7 +365,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by fac76 in bug report #1673397
@@ -354,7 +382,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -366,7 +395,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -378,7 +408,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -390,7 +421,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -402,7 +434,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesNone,
"intro"
},
{ // Supplied by blackwhiteeagle in bug report #1605235
@@ -414,7 +447,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by bgk in bug report #1706861
@@ -426,7 +460,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAtariST,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesNone,
"intro"
},
{
@@ -438,7 +473,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -450,7 +486,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -462,7 +499,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -474,7 +512,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -486,7 +525,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -498,7 +538,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -510,7 +551,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"usa"
},
{
@@ -522,7 +564,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -534,7 +577,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -546,7 +590,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{
@@ -558,7 +603,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by cybot_tmin in bug report #1667743
@@ -570,19 +616,42 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
{
"ween",
"",
- AD_ENTRY1s("intro.stk", "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570),
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
+ {NULL, 0, NULL, 0}
+ },
EN_GRB,
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
+ "intro"
+ },
+ { // Supplied by pwigren in bug report #1764174
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446},
+ {NULL, 0, NULL, 0}
+ },
+ EN_GRB,
+ kPlatformAtariST,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
@@ -594,7 +663,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
@@ -606,7 +676,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
@@ -618,7 +689,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{
@@ -630,7 +702,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAtariST,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{
@@ -642,7 +715,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by cartman_ on #scummvm
@@ -654,7 +728,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by glorfindel in bugreport #1722142
@@ -666,7 +741,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{
@@ -678,7 +754,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"show"
},
{
@@ -690,7 +767,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"show"
},
{
@@ -702,7 +780,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by Trekky in the forums
@@ -714,7 +793,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAtariST,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by cesardark in bug #1681649
@@ -726,7 +806,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by paul66 in bug #1692667
@@ -738,7 +819,21 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
+ "intro"
+ },
+ { // Supplied by pwigren in bugreport #1764174
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825),
+ EN_ANY,
+ kPlatformAmiga,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by glorfindel in bugreport #1722142
@@ -750,7 +845,112 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
+ "intro"
+ },
+ {
+ {
+ "ajworld",
+ "",
+ AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628),
+ EN_ANY,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob2,
+ kFeaturesAdlib,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdlib,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
"intro"
},
{
@@ -762,7 +962,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by fac76 in bug report #1742716
@@ -778,7 +979,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -790,7 +992,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -802,7 +1005,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -814,7 +1018,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by Paranoimia on #scummvm
@@ -826,7 +1031,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -838,7 +1044,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -850,7 +1057,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -862,7 +1070,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesNone,
"menu"
},
{
@@ -874,7 +1083,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesNone,
"menu"
},
{
@@ -886,7 +1096,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -898,7 +1109,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -910,7 +1122,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -922,7 +1135,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -934,7 +1148,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -946,7 +1161,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{
@@ -958,7 +1174,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -970,7 +1187,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -982,7 +1200,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -994,7 +1213,73 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{
@@ -1002,11 +1287,64 @@ static const GOBGameDescription gameDescriptions[] = {
"woodruff",
"",
AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- UNK_LANG,
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ DE_DEU,
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_WOODRUFF,
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
{
@@ -1014,11 +1352,64 @@ static const GOBGameDescription gameDescriptions[] = {
"woodruff",
"",
AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- EN_USA,
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ IT_ITA,
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_WOODRUFF,
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
{
@@ -1030,10 +1421,128 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_WOODRUFF,
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
- { AD_TABLE_END_MARKER, 0, NULL }
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ /*{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },*/
+ { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, NULL }
};
static const GOBGameDescription fallbackDescs[] = {
@@ -1046,7 +1555,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{
@@ -1058,7 +1568,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{
@@ -1070,7 +1581,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -1082,7 +1594,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -1094,7 +1607,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{
@@ -1106,7 +1620,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -1118,7 +1633,21 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
};
@@ -1132,6 +1661,7 @@ static const ADFileBasedFallback fileBased[] = {
{ &fallbackDescs[4], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } },
{ &fallbackDescs[5], { "intro.stk", "imd.itk", 0 } },
{ &fallbackDescs[6], { "intro.stk", "mus_gob3.lic", 0 } },
+ { &fallbackDescs[7], { "intro.stk", "woodruff.itk", 0 } },
{ 0, { 0 } }
};
@@ -1186,6 +1716,7 @@ bool GobEngine::detectGame() {
strcat(_startTot0, "0.tot");
}
+ _gameType = gd->gameType;
_features = gd->features;
_language = gd->desc.language;
_platform = gd->desc.platform;
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index bc5b205bd1..acf4d5765b 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -33,6 +33,7 @@
#include "gob/game.h"
#include "gob/inter.h"
#include "gob/video.h"
+#include "gob/palanim.h"
namespace Gob {
@@ -411,4 +412,88 @@ void Draw::forceBlit(bool backwards) {
0, 0, 0);
}
+const int16 Draw::_wobbleTable[360] = {
+ 0x0000, 0x011D, 0x023B, 0x0359, 0x0476, 0x0593, 0x06B0, 0x07CC, 0x08E8,
+ 0x0A03, 0x0B1D, 0x0C36, 0x0D4E, 0x0E65, 0x0F7B, 0x1090, 0x11A4, 0x12B6,
+ 0x13C6, 0x14D6, 0x15E3, 0x16EF, 0x17F9, 0x1901, 0x1A07, 0x1B0C, 0x1C0E,
+ 0x1D0E, 0x1E0B, 0x1F07, 0x2000, 0x20F6, 0x21EA, 0x22DB, 0x23C9, 0x24B5,
+ 0x259E, 0x2684, 0x2766, 0x2846, 0x2923, 0x29FC, 0x2AD3, 0x2BA5, 0x2C75,
+ 0x2D41, 0x2E09, 0x2ECE, 0x2F8F, 0x304D, 0x3106, 0x31BC, 0x326E, 0x331C,
+ 0x33C6, 0x346C, 0x350E, 0x35AC, 0x3646, 0x36DB, 0x376C, 0x37F9, 0x3882,
+ 0x3906, 0x3985, 0x3A00, 0x3A77, 0x3AE9, 0x3B56, 0x3BBF, 0x3C23, 0x3C83,
+ 0x3CDE, 0x3D34, 0x3D85, 0x3DD1, 0x3E19, 0x3E5C, 0x3E99, 0x3ED2, 0x3F07,
+ 0x3F36, 0x3F60, 0x3F85, 0x3FA6, 0x3FC1, 0x3FD8, 0x3FE9, 0x3FF6, 0x3FFD,
+ 0x4000, 0x3FFD, 0x3FF6, 0x3FE9, 0x3FD8, 0x3FC1, 0x3FA6, 0x3F85, 0x3F60,
+ 0x3F36, 0x3F07, 0x3ED2, 0x3E99, 0x3E5C, 0x3E19, 0x3DD1, 0x3D85, 0x3D34,
+ 0x3CDE, 0x3C83, 0x3C23, 0x3BBF, 0x3B56, 0x3AE9, 0x3A77, 0x3A00, 0x3985,
+ 0x3906, 0x3882, 0x37F9, 0x376C, 0x36DB, 0x3646, 0x35AC, 0x350E, 0x346C,
+ 0x33C6, 0x331C, 0x326E, 0x31BC, 0x3106, 0x304D, 0x2F8F, 0x2ECE, 0x2E09,
+ 0x2D41, 0x2C75, 0x2BA5, 0x2AD3, 0x29FC, 0x2923, 0x2846, 0x2766, 0x2684,
+ 0x259E, 0x24B5, 0x23C9, 0x22DB, 0x21EA, 0x20F6, 0x1FFF, 0x1F07, 0x1E0B,
+ 0x1D0E, 0x1C0E, 0x1B0C, 0x1A07, 0x1901, 0x17F9, 0x16EF, 0x15E3, 0x14D6,
+ 0x13C6, 0x12B6, 0x11A4, 0x1090, 0x0F7B, 0x0E65, 0x0D4E, 0x0C36, 0x0B1D,
+ 0x0A03, 0x08E8, 0x07CC, 0x06B0, 0x0593, 0x0476, 0x0359, 0x023B, 0x011D
+ -0x0000, -0x011D, -0x023B, -0x0359, -0x0476, -0x0593, -0x06B0, -0x07CC, -0x08E8,
+ -0x0A03, -0x0B1D, -0x0C36, -0x0D4E, -0x0E65, -0x0F7B, -0x1090, -0x11A4, -0x12B6,
+ -0x13C6, -0x14D6, -0x15E3, -0x16EF, -0x17F9, -0x1901, -0x1A07, -0x1B0C, -0x1C0E,
+ -0x1D0E, -0x1E0B, -0x1F07, -0x2000, -0x20F6, -0x21EA, -0x22DB, -0x23C9, -0x24B5,
+ -0x259E, -0x2684, -0x2766, -0x2846, -0x2923, -0x29FC, -0x2AD3, -0x2BA5, -0x2C75,
+ -0x2D41, -0x2E09, -0x2ECE, -0x2F8F, -0x304D, -0x3106, -0x31BC, -0x326E, -0x331C,
+ -0x33C6, -0x346C, -0x350E, -0x35AC, -0x3646, -0x36DB, -0x376C, -0x37F9, -0x3882,
+ -0x3906, -0x3985, -0x3A00, -0x3A77, -0x3AE9, -0x3B56, -0x3BBF, -0x3C23, -0x3C83,
+ -0x3CDE, -0x3D34, -0x3D85, -0x3DD1, -0x3E19, -0x3E5C, -0x3E99, -0x3ED2, -0x3F07,
+ -0x3F36, -0x3F60, -0x3F85, -0x3FA6, -0x3FC1, -0x3FD8, -0x3FE9, -0x3FF6, -0x3FFD,
+ -0x4000, -0x3FFD, -0x3FF6, -0x3FE9, -0x3FD8, -0x3FC1, -0x3FA6, -0x3F85, -0x3F60,
+ -0x3F36, -0x3F07, -0x3ED2, -0x3E99, -0x3E5C, -0x3E19, -0x3DD1, -0x3D85, -0x3D34,
+ -0x3CDE, -0x3C83, -0x3C23, -0x3BBF, -0x3B56, -0x3AE9, -0x3A77, -0x3A00, -0x3985,
+ -0x3906, -0x3882, -0x37F9, -0x376C, -0x36DB, -0x3646, -0x35AC, -0x350E, -0x346C,
+ -0x33C6, -0x331C, -0x326E, -0x31BC, -0x3106, -0x304D, -0x2F8F, -0x2ECE, -0x2E09,
+ -0x2D41, -0x2C75, -0x2BA5, -0x2AD3, -0x29FC, -0x2923, -0x2846, -0x2766, -0x2684,
+ -0x259E, -0x24B5, -0x23C9, -0x22DB, -0x21EA, -0x20F6, -0x1FFF, -0x1F07, -0x1E0B,
+ -0x1D0E, -0x1C0E, -0x1B0C, -0x1A07, -0x1901, -0x17F9, -0x16EF, -0x15E3, -0x14D6,
+ -0x13C6, -0x12B6, -0x11A4, -0x1090, -0x0F7B, -0x0E65, -0x0D4E, -0x0C36, -0x0B1D,
+ -0x0A03, -0x08E8, -0x07CC, -0x06B0, -0x0593, -0x0476, -0x0359, -0x023B, -0x011D
+};
+
+void Draw::wobble(SurfaceDesc *surfDesc) {
+ int16 amplitude = 32;
+ uint16 curFrame = 0;
+ uint16 frameWobble = 0;
+ uint16 rowWobble = 0;
+ int8 *offsets = new int8[_vm->_height];
+
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, -1);
+
+ while (amplitude > 0) {
+ rowWobble = frameWobble;
+ frameWobble = (frameWobble + 20) % 360;
+
+ for (uint16 y = 0; y < _vm->_height; y++) {
+ offsets[y] = amplitude +
+ ((_wobbleTable[rowWobble] * amplitude) / 0x4000);
+
+ rowWobble = (rowWobble + 20) % 360;
+ }
+
+ if (curFrame++ & 16)
+ amplitude--;
+
+ for (uint16 y = 0; y < _vm->_height; y++)
+ _vm->_video->drawSprite(surfDesc, _frontSurface,
+ 0, y, _vm->_width - 1, y, offsets[y], y, 0);
+
+ _vm->_palAnim->fadeStep(0);
+ _vm->_video->waitRetrace();
+ }
+
+ _vm->_video->drawSprite(surfDesc, _frontSurface,
+ 0, 0, _vm->_width - 1, _vm->_height - 1, 0, 0, 0);
+
+ _applyPal = false;
+ _invalidatedCount = 0;
+ _noInvalidated = true;
+
+ delete[] offsets;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/draw.h b/engines/gob/draw.h
index e37ecda334..4bf59856be 100644
--- a/engines/gob/draw.h
+++ b/engines/gob/draw.h
@@ -32,13 +32,15 @@ namespace Gob {
#define SPRITES_COUNT 50
-#define RENDERFLAG_NOINVALIDATE 0x001
-#define RENDERFLAG_CAPTUREPUSH 0x002
-#define RENDERFLAG_COLLISIONS 0x004
-#define RENDERFLAG_CAPTUREPOP 0x008
-#define RENDERFLAG_USEDELTAS 0x010
-#define RENDERFLAG_NOBLITINVALIDATED 0x200
-#define RENDERFLAG_SKIPOPTIONALTEXT 0x400
+#define RENDERFLAG_NOINVALIDATE 0x0001
+#define RENDERFLAG_CAPTUREPUSH 0x0002
+#define RENDERFLAG_COLLISIONS 0x0004
+#define RENDERFLAG_CAPTUREPOP 0x0008
+#define RENDERFLAG_USEDELTAS 0x0010
+#define RENDERFLAG_NOBLITINVALIDATED 0x0200
+#define RENDERFLAG_SKIPOPTIONALTEXT 0x0400
+#define RENDERFLAG_FROMSPLIT 0x0800
+#define RENDERFLAG_DOUBLECOORDS 0x1000
class Draw {
public:
@@ -151,6 +153,9 @@ public:
int32 getSpriteRectSize(int16 index);
void forceBlit(bool backwards = false);
+ static const int16 _wobbleTable[360];
+ void wobble(SurfaceDesc *surfDesc);
+
virtual void initScreen() = 0;
virtual void closeScreen() = 0;
virtual void blitCursor() = 0;
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index c45bd0de27..55585f5619 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -197,7 +197,12 @@ void Draw_v2::printTotText(int16 id) {
int16 rectLeft, rectTop, rectRight, rectBottom;
int16 size;
- if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr)
+ id &= 0xFFF;
+
+ if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr ||
+ (id >= _vm->_game->_totTextData->itemsCount) ||
+ (_vm->_game->_totTextData->items[id].offset == -1) ||
+ (_vm->_game->_totTextData->items[id].size == 0))
return;
_vm->validateLanguage();
@@ -210,10 +215,34 @@ void Draw_v2::printTotText(int16 id) {
if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80))
return;
- destX = READ_LE_UINT16(ptr) & 0x7FFF;
- destY = READ_LE_UINT16(ptr + 2);
- spriteRight = READ_LE_UINT16(ptr + 4);
- spriteBottom = READ_LE_UINT16(ptr + 6);
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
+ destX = (READ_LE_UINT16(ptr) & 0x7FFF) * 2;
+ spriteRight = READ_LE_UINT16(ptr + 4) * 2 + 1;
+ } else {
+ destX = READ_LE_UINT16(ptr) & 0x7FFF;
+ spriteRight = READ_LE_UINT16(ptr + 4);
+ }
+
+ if (_renderFlags & RENDERFLAG_FROMSPLIT) {
+ destY = _vm->_video->_splitHeight1;
+ spriteBottom = READ_LE_UINT16(ptr + 6) - READ_LE_UINT16(ptr + 2);
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS)
+ spriteBottom *= 3;
+ spriteBottom += _vm->_video->_splitHeight1;
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
+ spriteBottom += _backDeltaX;
+ destY += _backDeltaX;
+ }
+ } else {
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
+ destY = READ_LE_UINT16(ptr + 2) * 2;
+ spriteBottom = READ_LE_UINT16(ptr + 6) * 2;
+ } else {
+ destY = READ_LE_UINT16(ptr + 2);
+ spriteBottom = READ_LE_UINT16(ptr + 6);
+ }
+ }
+
ptr += 8;
if (_renderFlags & RENDERFLAG_CAPTUREPUSH) {
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 795484ef0e..37817c12a3 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -140,8 +140,18 @@ byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
size = item->size;
isPacked = (item->width & 0x8000) != 0;
- if (pResWidth != 0) {
+ if ((pResWidth != 0) && (pResHeight != 0)) {
*pResWidth = item->width & 0x7FFF;
+
+ if (*pResWidth & 0x4000)
+ size += 1 << 16;
+ if (*pResWidth & 0x2000)
+ size += 2 << 16;
+ if (*pResWidth & 0x1000)
+ size += 4 << 16;
+
+ *pResWidth &= 0xFFF;
+
*pResHeight = item->height;
debugC(7, kDebugFileIO, "loadExtData(%d, %d, %d)",
itemId, *pResWidth, *pResHeight);
@@ -164,8 +174,10 @@ byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
} else
handle = _extHandle;
+ DataStream *stream = _vm->_dataIO->openAsStream(handle);
+
debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize);
- _vm->_dataIO->seekData(handle, offset + tableSize, SEEK_SET);
+ stream->seek(offset + tableSize);
realSize = size;
if (isPacked)
dataBuf = new byte[size + 2];
@@ -175,11 +187,13 @@ byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
dataPtr = dataBuf;
while (size > 32000) {
// BUG: huge->far conversion. Need normalization?
- _vm->_dataIO->readData(handle, dataPtr, 32000);
+ stream->read(dataPtr, 32000);
size -= 32000;
dataPtr += 32000;
}
- _vm->_dataIO->readData(handle, dataPtr, size);
+ stream->read(dataPtr, size);
+
+ delete stream;
if (commonHandle != -1) {
_vm->_dataIO->closeData(commonHandle);
_extHandle = _vm->_dataIO->openData(_curExtFile);
@@ -315,11 +329,12 @@ void Game::evaluateScroll(int16 x, int16 y) {
}
int16 cursorRight = x + _vm->_draw->_cursorWidth;
- int16 screenRight = _vm->_draw->_scrollOffsetX + 320;
+ int16 screenRight = _vm->_draw->_scrollOffsetX + _vm->_width;
int16 cursorBottom = y + _vm->_draw->_cursorHeight;
- int16 screenBottom = _vm->_draw->_scrollOffsetY + 200;
+ int16 screenBottom = _vm->_draw->_scrollOffsetY + _vm->_height;
- if ((cursorRight >= 320) && (screenRight < _vm->_video->_surfWidth)) {
+ if ((cursorRight >= _vm->_width) &&
+ (screenRight < _vm->_video->_surfWidth)) {
uint16 off;
off = MIN(_vm->_draw->_cursorWidth,
@@ -328,8 +343,8 @@ void Game::evaluateScroll(int16 x, int16 y) {
_vm->_draw->_scrollOffsetX += off;
- _vm->_util->setMousePos(320 - _vm->_draw->_cursorWidth, y);
- } else if ((cursorBottom >= (200 - _vm->_video->_splitHeight2)) &&
+ _vm->_util->setMousePos(_vm->_width - _vm->_draw->_cursorWidth, y);
+ } else if ((cursorBottom >= (_vm->_height - _vm->_video->_splitHeight2)) &&
(screenBottom < _vm->_video->_surfHeight)) {
uint16 off;
@@ -339,7 +354,7 @@ void Game::evaluateScroll(int16 x, int16 y) {
_vm->_draw->_scrollOffsetY += off;
- _vm->_util->setMousePos(x, 200 - _vm->_video->_splitHeight2 -
+ _vm->_util->setMousePos(x, _vm->_height - _vm->_video->_splitHeight2 -
_vm->_draw->_cursorHeight);
}
@@ -368,10 +383,12 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
_vm->_inter->_soundEndTimeKey = 0;
}
- _vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
+ if (pMouseX && pMouseY && pButtons) {
+ _vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
- if (*pButtons == 3)
- *pButtons = 0;
+ if (*pButtons == 3)
+ *pButtons = 0;
+ }
return _vm->_util->checkKey();
}
@@ -408,23 +425,26 @@ void Game::loadExtTable(void) {
if (_extHandle < 0)
return;
- count = _vm->_dataIO->readUint16(_extHandle);
+ DataStream *stream = _vm->_dataIO->openAsStream(_extHandle);
+ count = stream->readUint16LE();
- _vm->_dataIO->seekData(_extHandle, 0, SEEK_SET);
+ stream->seek(0);
_extTable = new ExtTable;
_extTable->items = 0;
if (count)
_extTable->items = new ExtItem[count];
- _extTable->itemsCount = _vm->_dataIO->readUint16(_extHandle);
- _extTable->unknown = _vm->_dataIO->readByte(_extHandle);
+ _extTable->itemsCount = stream->readUint16LE();
+ _extTable->unknown = stream->readByte();
for (int i = 0; i < count; i++) {
- _extTable->items[i].offset = _vm->_dataIO->readUint32(_extHandle);
- _extTable->items[i].size = _vm->_dataIO->readUint16(_extHandle);
- _extTable->items[i].width = _vm->_dataIO->readUint16(_extHandle);
- _extTable->items[i].height = _vm->_dataIO->readUint16(_extHandle);
+ _extTable->items[i].offset = stream->readUint32LE();
+ _extTable->items[i].size = stream->readUint16LE();
+ _extTable->items[i].width = stream->readUint16LE();
+ _extTable->items[i].height = stream->readUint16LE();
}
+
+ delete stream;
}
void Game::loadImFile(void) {
@@ -544,7 +564,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) {
int16 newPos = _curBackupPos - index - ((index >= 0) ? 1 : 0);
// WORKAROUND: Some versions don't make the MOVEMENT menu item unselectable
// in the dreamland screen, resulting in a crash when it's clicked.
- if ((_vm->_features & GF_GOB2) && (index == -1) && (skipPlay == 7) &&
+ if ((_vm->getGameType() == kGameTypeGob2) && (index == -1) && (skipPlay == 7) &&
!scumm_stricmp(_curTotFileArray[newPos], "gob06.tot"))
return;
@@ -652,7 +672,7 @@ int16 Game::openLocTextFile(char *locTextFile, int language) {
return _vm->_dataIO->openData(locTextFile);
}
-byte *Game::loadLocTexts(void) {
+byte *Game::loadLocTexts(int32 *dataSize) {
char locTextFile[20];
int16 handle;
int i;
@@ -661,23 +681,48 @@ byte *Game::loadLocTexts(void) {
handle = openLocTextFile(locTextFile, _vm->_global->_languageWanted);
if (handle >= 0) {
+
_foundTotLoc = true;
_vm->_global->_language = _vm->_global->_languageWanted;
- }
- else if (!_foundTotLoc) {
- for (i = 0; i < 10; i++) {
- handle = openLocTextFile(locTextFile, i);
+
+ } else if (!_foundTotLoc) {
+ bool found = false;
+
+ if (_vm->_global->_languageWanted == 2) {
+ handle = openLocTextFile(locTextFile, 5);
+ if (handle >= 0) {
+ _vm->_global->_language = 5;
+ found = true;
+ }
+ } else if (_vm->_global->_languageWanted == 5) {
+ handle = openLocTextFile(locTextFile, 2);
if (handle >= 0) {
- _vm->_global->_language = i;
- break;
+ _vm->_global->_language = 2;
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (i = 0; i < 10; i++) {
+ handle = openLocTextFile(locTextFile, i);
+ if (handle >= 0) {
+ _vm->_global->_language = i;
+ break;
+ }
}
}
+
}
+
debugC(1, kDebugFileIO, "Using language %d for %s",
_vm->_global->_language, _curTotFile);
if (handle >= 0) {
_vm->_dataIO->closeData(handle);
+
+ if (dataSize)
+ *dataSize = _vm->_dataIO->getDataSize(locTextFile);
+
return _vm->_dataIO->getData(locTextFile);
}
return 0;
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 2181d219f2..c83497eaeb 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -147,11 +147,14 @@ public:
void evaluateScroll(int16 x, int16 y);
- int16 checkKeys(int16 *pMousex, int16 *pMouseY, int16 *pButtons, char handleMouse);
+ int16 checkKeys(int16 *pMousex = 0, int16 *pMouseY = 0,
+ int16 *pButtons = 0, char handleMouse = 0);
void start(void);
void totSub(int8 flags, const char *newTotFile);
void switchTotSub(int16 index, int16 skipPlay);
+ void freeCollision(int16 id);
+
virtual void playTot(int16 skipPlay) = 0;
virtual void clearCollisions(void) = 0;
@@ -215,13 +218,12 @@ protected:
int16 adjustKey(int16 key);
- byte *loadLocTexts(void);
+ byte *loadLocTexts(int32 *dataSize = 0);
int32 loadTotFile(const char *path);
void loadExtTable(void);
void loadImFile(void);
void setCollisions(void);
- void freeCollision(int16 id);
void collSub(uint16 offset);
void collAreaSub(int16 index, int8 enter);
int16 openLocTextFile(char *locTextFile, int language);
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index 6ba68553c7..9c18ec1151 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -911,7 +911,8 @@ void Game_v1::collisionsBlock(void) {
_shouldPushColls = 0;
_vm->_global->_inter_execPtr = savedIP;
deltaTime = timeVal -
- (_vm->_util->getTimeKey() - timeKey);
+ ((_vm->_util->getTimeKey() - timeKey)
+ - _vm->_video->_lastRetraceLength);
if (deltaTime < 2)
deltaTime = 2;
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index 245c1f4544..7e87b9e8f8 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -1,27 +1,27 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
+ /* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
#include "common/stdafx.h"
#include "common/endian.h"
@@ -34,13 +34,13 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/inter.h"
#include "gob/mult.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -101,6 +101,7 @@ void Game_v2::playTot(int16 skipPlay) {
_extTable = 0;
_extHandle = -1;
+ _vm->_draw->_cursorHotspotXVar = -1;
_totToLoad[0] = 0;
if ((_curTotFile[0] == 0) && (_totFileData == 0))
@@ -134,12 +135,16 @@ void Game_v2::playTot(int16 skipPlay) {
totTextLoc = false;
if (READ_LE_UINT32(filePtr) != (uint32) -1) {
_totTextData = new TotTextTable;
+
+ int32 size;
+
if (READ_LE_UINT32(filePtr) == 0) {
- _totTextData->dataPtr = loadLocTexts();
+ _totTextData->dataPtr = loadLocTexts(&size);
totTextLoc = true;
} else {
_totTextData->dataPtr =
(_totFileData + READ_LE_UINT32(_totFileData + 0x30));
+ size = totSize;
_vm->_global->_language = _vm->_global->_languageWanted;
}
@@ -147,7 +152,7 @@ void Game_v2::playTot(int16 skipPlay) {
if (_totTextData->dataPtr != 0) {
Common::MemoryReadStream totTextData(_totTextData->dataPtr,
4294967295U);
- _totTextData->itemsCount = totTextData.readSint16LE();
+ _totTextData->itemsCount = totTextData.readSint16LE() & 0x3FFF;
_totTextData->items = new TotTextItem[_totTextData->itemsCount];
for (int i = 0; i < _totTextData->itemsCount; ++i) {
@@ -267,7 +272,7 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_snd->freeSample(_soundSamples[i]);
}
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
if (_totToLoad[0] == 0)
break;
diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp
index ec2fa6b043..f3bc0611fd 100644
--- a/engines/gob/global.cpp
+++ b/engines/gob/global.cpp
@@ -112,7 +112,7 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_setAllPalette = false;
_dontSetPalette = false;
- _primarySurfDesc = new SurfaceDesc(0x13, 320, 200);
+ _primarySurfDesc = 0;
_debugFlag = 0;
_inVM = 0;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 32caca31d8..d9385b1b0f 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -48,7 +48,7 @@
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/music.h"
-#include "gob/imd.h"
+#include "gob/videoplayer.h"
#include "gob/saveload.h"
namespace Gob {
@@ -68,6 +68,16 @@ const Common::Language GobEngine::_gobToScummVMLang[] = {
};
GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
+ _vm = this;
+
+ _snd = 0; _adlib = 0; _mult = 0;
+ _game = 0; _global = 0; _cdrom = 0;
+ _dataIO = 0; _goblin = 0; _vidPlayer = 0;
+ _init = 0; _inter = 0; _map = 0;
+ _palAnim = 0; _parse = 0; _scenery = 0;
+ _draw = 0; _util = 0; _video = 0;
+ _saveLoad = 0;
+
// Setup mixer
if (!_mixer->isReady()) {
warning("Sound initialization failed.");
@@ -94,25 +104,7 @@ GobEngine::~GobEngine() {
// Stop all mixer streams (except for the permanent ones).
_vm->_mixer->stopAll();
- delete _snd;
- delete _adlib;
- delete _mult;
- delete _game;
- delete _global;
- delete _cdrom;
- delete _dataIO;
- delete _goblin;
- delete _imdPlayer;
- delete _init;
- delete _inter;
- delete _map;
- delete _palAnim;
- delete _parse;
- delete _scenery;
- delete _draw;
- delete _util;
- delete _video;
- delete _saveLoad;
+ deinitGameParts();
delete[] _startTot;
delete[] _startTot0;
}
@@ -129,15 +121,23 @@ void GobEngine::shutdown() {
void GobEngine::validateLanguage() {
if (_vm->_global->_languageWanted != _vm->_global->_language) {
- warning("Your game version doesn't support the requested language");
- warning("Using the first language available: %s",
- getLangDesc(_vm->_global->_language));
+ warning("Your game version doesn't support the requested language %s",
+ getLangDesc(_vm->_global->_languageWanted));
+
+ if (((_vm->_global->_languageWanted == 2) && (_vm->_global->_language == 5)) ||
+ ((_vm->_global->_languageWanted == 5) && (_vm->_global->_language == 2)))
+ warning("Using %s instead", getLangDesc(_vm->_global->_language));
+ else
+ warning("Using the first language available: %s",
+ getLangDesc(_vm->_global->_language));
+
_vm->_global->_languageWanted = _vm->_global->_language;
}
}
void GobEngine::validateVideoMode(int16 videoMode) {
- if ((videoMode != 0x13) && (videoMode != 0x14))
+ if ((videoMode != 0x10) && (videoMode != 0x13) &&
+ (videoMode != 0x14) && (videoMode != 0x18))
error("Video mode 0x%X is not supported!", videoMode);
}
@@ -148,82 +148,18 @@ int GobEngine::init() {
return -1;
}
- _adlib = 0;
- _saveLoad = 0;
- _global = new Global(this);
- _util = new Util(this);
- _dataIO = new DataIO(this);
- _palAnim = new PalAnim(this);
- _imdPlayer = new ImdPlayer(this);
- _cdrom = new CDROM(this);
- _snd = new Snd(this);
- if (_features & Gob::GF_GOB1) {
- _init = new Init_v1(this);
- _video = new Video_v1(this);
- _inter = new Inter_v1(this);
- _parse = new Parse_v1(this);
- _mult = new Mult_v1(this);
- _draw = new Draw_v1(this);
- _game = new Game_v1(this);
- _map = new Map_v1(this);
- _goblin = new Goblin_v1(this);
- _scenery = new Scenery_v1(this);
- } else if (_features & Gob::GF_GOB2) {
- _init = new Init_v2(this);
- _video = new Video_v2(this);
- _inter = new Inter_v2(this);
- _parse = new Parse_v2(this);
- _mult = new Mult_v2(this);
- _draw = new Draw_v2(this);
- _game = new Game_v2(this);
- _map = new Map_v2(this);
- _goblin = new Goblin_v2(this);
- _scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
- } else if (_features & Gob::GF_BARGON) {
- _init = new Init_v2(this);
- _video = new Video_v2(this);
- _inter = new Inter_Bargon(this);
- _parse = new Parse_v2(this);
- _mult = new Mult_v2(this);
- _draw = new Draw_Bargon(this);
- _game = new Game_v2(this);
- _map = new Map_v2(this);
- _goblin = new Goblin_v2(this);
- _scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
- } else if (_features & Gob::GF_GOB3) {
- _init = new Init_v3(this);
- _video = new Video_v2(this);
- _inter = new Inter_v3(this);
- _parse = new Parse_v2(this);
- _mult = new Mult_v2(this);
- _draw = new Draw_v2(this);
- _game = new Game_v2(this);
- _map = new Map_v2(this);
- _goblin = new Goblin_v3(this);
- _scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
- } else
- error("GobEngine::init(): Unknown version of game engine");
-
- _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
- if (!_noMusic && !(_platform == Common::kPlatformAmiga) &&
- !(_platform == Common::kPlatformAtariST) &&
- (((_platform == Common::kPlatformMacintosh) && (_features & Gob::GF_GOB1)) ||
- (_features & Gob::GF_GOB2) || (_features & Gob::GF_GOB3)))
- _adlib = new Adlib(this);
- _vm = this;
-
- _map->init();
+ if (!initGameParts()) {
+ GUIErrorMessage("GobEngine::init(): Unknown version of game engine");
+ return -1;
+ }
_system->beginGFXTransaction();
- initCommonGFX(false);
- _system->initSize(320, 200);
+ _system->initSize(_width, _height);
+ initCommonGFX(is640());
_system->endGFXTransaction();
// On some systems it's not safe to run CD audio games from the CD.
- if (_features & GF_CD)
+ if (isCD())
checkCD();
int cd_num = ConfMan.getInt("cdrom");
@@ -293,4 +229,167 @@ int GobEngine::init() {
return 0;
}
+bool GobEngine::initGameParts() {
+ _adlib = 0;
+ _saveLoad = 0;
+
+ _global = new Global(this);
+ _util = new Util(this);
+ _dataIO = new DataIO(this);
+ _palAnim = new PalAnim(this);
+ _vidPlayer = new VideoPlayer(this);
+ _cdrom = new CDROM(this);
+ _snd = new Snd(this);
+
+ switch (_gameType) {
+ case kGameTypeGob1:
+ _init = new Init_v1(this);
+ _video = new Video_v1(this);
+ _inter = new Inter_v1(this);
+ _parse = new Parse_v1(this);
+ _mult = new Mult_v1(this);
+ _draw = new Draw_v1(this);
+ _game = new Game_v1(this);
+ _map = new Map_v1(this);
+ _goblin = new Goblin_v1(this);
+ _scenery = new Scenery_v1(this);
+ break;
+
+ case kGameTypeGob2:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v2(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
+ break;
+
+ case kGameTypeBargon:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_Bargon(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_Bargon(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
+ break;
+
+ case kGameTypeWeen:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v2(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
+ break;
+
+ case kGameTypeGob3:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v3(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v3(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ break;
+
+ case kGameTypeLostInTime:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v3(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v3(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str(), 4768, 0, 50);
+ break;
+
+ case kGameTypeWoodruff:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v4(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v3(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ break;
+
+ default:
+ deinitGameParts();
+ return false;
+ break;
+ }
+
+ _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
+ if (!_noMusic && hasAdlib())
+ _adlib = new Adlib(this);
+
+ _map->init();
+
+ if (is640()) {
+ _video->_surfWidth = _width = 640;
+ _video->_surfHeight = _video->_splitHeight1 = _height = 480;
+ _global->_mouseMaxCol = 640;
+ _global->_mouseMaxRow = 480;
+ _mode = 0x18;
+ _global->_primarySurfDesc = new SurfaceDesc(0x18, 640, 480);
+ } else {
+ _video->_surfWidth = _width = 320;
+ _video->_surfHeight = _video->_splitHeight1 = _height = 200;
+ _global->_mouseMaxCol = 320;
+ _global->_mouseMaxRow = 200;
+ _mode = 0x14;
+ _global->_primarySurfDesc = new SurfaceDesc(0x14, 320, 200);
+ }
+
+ return true;
+}
+
+void GobEngine::deinitGameParts() {
+ delete _snd; _snd = 0;
+ delete _adlib; _adlib = 0;
+ delete _mult; _mult = 0;
+ delete _game; _game = 0;
+ delete _global; _global = 0;
+ delete _cdrom; _cdrom = 0;
+ delete _dataIO; _dataIO = 0;
+ delete _goblin; _goblin = 0;
+ delete _vidPlayer; _vidPlayer = 0;
+ delete _init; _init = 0;
+ delete _inter; _inter = 0;
+ delete _map; _map = 0;
+ delete _palAnim; _palAnim = 0;
+ delete _parse; _parse = 0;
+ delete _scenery; _scenery = 0;
+ delete _draw; _draw = 0;
+ delete _util; _util = 0;
+ delete _video; _video = 0;
+ delete _saveLoad; _saveLoad = 0;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 97ee312bff..d573dc3a89 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -42,7 +42,7 @@ class Draw;
class CDROM;
class DataIO;
class Goblin;
-class ImdPlayer;
+class VideoPlayer;
class Init;
class Inter;
class Map;
@@ -78,14 +78,23 @@ class Adlib;
#define VAR(var) READ_VAR_UINT32(var)
#define VAR_ADDRESS(var) ((uint32 *) VARP((var) << 2))
-enum {
- GF_GOB1 = 1 << 0,
- GF_GOB2 = 1 << 1,
- GF_GOB3 = 1 << 2,
- GF_WOODRUFF = 1 << 3,
- GF_BARGON = 1 << 4,
- GF_CD = 1 << 5,
- GF_EGA = 1 << 6
+enum GameType {
+ kGameTypeNone = 0,
+ kGameTypeGob1,
+ kGameTypeGob2,
+ kGameTypeGob3,
+ kGameTypeWoodruff,
+ kGameTypeBargon,
+ kGameTypeWeen,
+ kGameTypeLostInTime
+};
+
+enum Features {
+ kFeaturesNone = 0,
+ kFeaturesCD = 1 << 0,
+ kFeaturesEGA = 1 << 1,
+ kFeaturesAdlib = 1 << 2,
+ kFeatures640 = 1 << 3
};
enum {
@@ -165,6 +174,9 @@ protected:
int go();
int init();
+ bool initGameParts();
+ void deinitGameParts();
+
bool detectGame();
public:
@@ -172,9 +184,15 @@ public:
Common::RandomSource _rnd;
+ GameType _gameType;
int32 _features;
Common::Language _language;
Common::Platform _platform;
+
+ uint16 _width;
+ uint16 _height;
+ uint8 _mode;
+
char *_startTot;
char *_startTot0;
bool _copyProtection;
@@ -199,7 +217,7 @@ public:
Inter *_inter;
SaveLoad *_saveLoad;
Adlib *_adlib;
- ImdPlayer *_imdPlayer;
+ VideoPlayer *_vidPlayer;
void shutdown();
@@ -211,6 +229,12 @@ public:
void validateLanguage();
void validateVideoMode(int16 videoMode);
+ GameType getGameType() { return _gameType; }
+ bool isCD() { return (_features & kFeaturesCD) != 0; }
+ bool isEGA() { return (_features & kFeaturesEGA) != 0; }
+ bool is640() { return (_features & kFeatures640) != 0; }
+ bool hasAdlib() { return (_features & kFeaturesAdlib) != 0; }
+
GobEngine(OSystem *syst);
virtual ~GobEngine();
};
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
index 418b31e2ee..1db741bd44 100644
--- a/engines/gob/goblin.cpp
+++ b/engines/gob/goblin.cpp
@@ -1698,6 +1698,9 @@ void Goblin::playSounds(Mult::Mult_Object *obj) {
int16 sndSlot;
int16 frame;
+ if (!obj->goblinStates)
+ return;
+
animData = obj->pAnimData;
for (int i = 1; i <= obj->goblinStates[animData->state][0].dataCount; i++) {
diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp
index 67e9f65444..608b0f0790 100644
--- a/engines/gob/goblin_v2.cpp
+++ b/engines/gob/goblin_v2.cpp
@@ -314,6 +314,9 @@ void Goblin_v2::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
int16 state;
int16 layer;
+ if (!obj->goblinStates)
+ return;
+
movePathFind(obj, 0, 0);
playSounds(obj);
diff --git a/engines/gob/goblin_v3.cpp b/engines/gob/goblin_v3.cpp
index 002ef7b749..f4aa872fa1 100644
--- a/engines/gob/goblin_v3.cpp
+++ b/engines/gob/goblin_v3.cpp
@@ -115,6 +115,9 @@ void Goblin_v3::placeObject(Gob_Object *objDesc, char animated,
Mult::Mult_Object &obj = _vm->_mult->_objects[index];
Mult::Mult_AnimData &objAnim = *(obj.pAnimData);
+ if (!obj.goblinStates)
+ return;
+
if ((state != -1) && (obj.goblinStates[state] != 0)) {
if (state == 8)
objAnim.curLookDir = 0;
diff --git a/engines/gob/imd.cpp b/engines/gob/imd.cpp
deleted file mode 100644
index 395fb01f9b..0000000000
--- a/engines/gob/imd.cpp
+++ /dev/null
@@ -1,1249 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-#include "common/endian.h"
-
-#include "gob/gob.h"
-#include "gob/imd.h"
-#include "gob/global.h"
-#include "gob/util.h"
-#include "gob/dataio.h"
-#include "gob/draw.h"
-#include "gob/game.h"
-#include "gob/inter.h"
-#include "gob/palanim.h"
-#include "gob/sound.h"
-#include "gob/video.h"
-
-namespace Gob {
-
-ImdPlayer::ImdPlayer(GobEngine *vm) : _vm(vm) {
- _curImd = 0;
- _curFile[0] = 0;
-
- _curX = 0;
- _curY = 0;
- _left = 0;
- _top = 0;
- _right = 0;
- _bottom = 0;
-
- _frameData = 0;
- _vidBuffer = 0;
-
- _frontSurf = 21;
- _backSurf = 21;
- _frontMem = 0;
- _frameDelay = 0;
-
- _noSound = true;
-
- _soundStartTime = 0;
- _skipFrames = 0;
-
- _soundFreq = 0;
- _soundSliceSize = 0;
- _soundSlicesCount = 0;
-
- _soundSliceLength = 0;
- _soundStage = 0;
-
- _audioStream = 0;
-}
-
-ImdPlayer::~ImdPlayer() {
- if (_curImd) {
- delete[] _curImd->palette;
- delete[] _curImd->framesPos;
- delete[] _curImd->frameCoords;
- delete[] _curImd->extraPalette;
- }
- delete[] _frameData;
- delete[] _vidBuffer;
- delete[] _frontMem;
- delete _curImd;
-}
-
-// flag bits: 0 = read and set palette
-// 1 = read palette
-ImdPlayer::Imd *ImdPlayer::loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags) {
- Imd *imdPtr;
- int16 handle;
- char buf[18];
- uint32 framesPosPos = 0;
- uint32 framesCordsPos = 0;
-
- strncpy0(buf, path, 17);
- if (!strchr(buf, '.')) {
- buf[13] = 0;
- strcat(buf, ".IMD");
- }
-
- handle = _vm->_dataIO->openData(buf);
-
- if (handle < 0) {
- warning("Can't open IMD \"%s\"", buf);
- return 0;
- }
-
- imdPtr = new Imd;
- assert(imdPtr);
- memset(imdPtr, 0, sizeof(Imd));
-
- imdPtr->handle = _vm->_dataIO->readUint16(handle);
- imdPtr->verMin = _vm->_dataIO->readUint16(handle);
- imdPtr->framesCount = _vm->_dataIO->readUint16(handle);
- imdPtr->x = _vm->_dataIO->readUint16(handle);
- imdPtr->y = _vm->_dataIO->readUint16(handle);
- imdPtr->width = _vm->_dataIO->readUint16(handle);
- imdPtr->height = _vm->_dataIO->readUint16(handle);
- imdPtr->field_E = _vm->_dataIO->readUint16(handle);
- imdPtr->curFrame = _vm->_dataIO->readUint16(handle);
-
- if ((imdPtr->handle != 0) || ((imdPtr->verMin & 0xFF) < 2)) {
- warning("%s: Version incorrect (%d,%X)", buf, imdPtr->handle, imdPtr->verMin);
- _vm->_dataIO->closeData(handle);
- delete imdPtr;
- return 0;
- }
-
- imdPtr->handle = handle;
- imdPtr->surfDesc = surfDesc;
- imdPtr->firstFramePos = imdPtr->curFrame;
- imdPtr->curFrame = 0;
-
- if ((imdPtr->verMin & 0x800) && ((flags & 3) != 3))
- imdPtr->extraPalette = new Video::Color[256];
-
- if (flags & 3) {
- imdPtr->palette = new Video::Color[256];
- assert(imdPtr->palette);
- _vm->_dataIO->readData(handle, (byte *) imdPtr->palette, 768);
- } else
- _vm->_dataIO->seekData(handle, 768, SEEK_CUR);
-
- if ((flags & 3) == 1)
- _vm->_video->setPalette(imdPtr->palette);
-
- if ((imdPtr->verMin & 0xFF) >= 3) {
- imdPtr->stdX = _vm->_dataIO->readUint16(handle);
- if (imdPtr->stdX > 1) {
- warning("%s: More than one standard coordinate quad found (%d)",
- buf, imdPtr->stdX);
- finishImd(imdPtr);
- return 0;
- }
- if (imdPtr->stdX != 0) {
- imdPtr->stdX = _vm->_dataIO->readUint16(handle);
- imdPtr->stdY = _vm->_dataIO->readUint16(handle);
- imdPtr->stdWidth = _vm->_dataIO->readUint16(handle);
- imdPtr->stdHeight = _vm->_dataIO->readUint16(handle);
- } else
- imdPtr->stdX = -1;
- } else
- imdPtr->stdX = -1;
-
- if ((imdPtr->verMin & 0xFF) >= 4) {
- framesPosPos = _vm->_dataIO->readUint32(handle);
- if (framesPosPos != 0) {
- imdPtr->framesPos = new int32[imdPtr->framesCount];
- assert(imdPtr->framesPos);
- }
- }
-
- if (imdPtr->verMin & 0x8000)
- framesCordsPos = _vm->_dataIO->readUint32(handle);
-
- _noSound = true;
- _soundStage = 0;
- if (imdPtr->verMin & 0x4000) {
- _soundFreq = _vm->_dataIO->readUint16(handle);
- _soundSliceSize = _vm->_dataIO->readUint16(handle);
- _soundSlicesCount = _vm->_dataIO->readUint16(handle);
-
- if (_soundFreq < 0)
- _soundFreq = -_soundFreq;
-
- if (_soundSlicesCount < 0)
- _soundSlicesCount = -_soundSlicesCount - 1;
-
- if (_soundSlicesCount > 40) {
- warning("%s: More than 40 sound slices found (%d)",
- buf, _soundSlicesCount);
- finishImd(imdPtr);
- return 0;
- }
-
- _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
-
- _soundStage = 1;
- _noSound = false;
-
- _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
- }
-
- if (imdPtr->verMin & 0x2000) {
- imdPtr->frameDataSize = _vm->_dataIO->readUint16(handle);
- if (imdPtr->frameDataSize == 0) {
- imdPtr->frameDataSize = _vm->_dataIO->readUint32(handle);
- imdPtr->vidBufferSize = _vm->_dataIO->readUint32(handle);
- } else
- imdPtr->vidBufferSize = _vm->_dataIO->readUint16(handle);
- } else {
- imdPtr->frameDataSize = imdPtr->width * imdPtr->height + 500;
- if (!(imdPtr->field_E & 0x100) || (imdPtr->field_E & 0x1000))
- imdPtr->vidBufferSize = imdPtr->frameDataSize;
- }
-
- if (imdPtr->framesPos) {
- _vm->_dataIO->seekData(handle, framesPosPos, SEEK_SET);
- for (int i = 0; i < imdPtr->framesCount; i++)
- imdPtr->framesPos[i] = _vm->_dataIO->readUint32(handle);
- }
-
- if (imdPtr->verMin & 0x8000) {
- _vm->_dataIO->seekData(handle, framesCordsPos, SEEK_SET);
- imdPtr->frameCoords = new ImdCoord[imdPtr->framesCount];
- assert(imdPtr->frameCoords);
- for (int i = 0; i < imdPtr->framesCount; i++) {
- imdPtr->frameCoords[i].left = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].top = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].right = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].bottom = _vm->_dataIO->readUint16(handle);
- }
- }
-
- _vm->_dataIO->seekData(handle, imdPtr->firstFramePos, SEEK_SET);
- return imdPtr;
-}
-
-void ImdPlayer::finishImd(ImdPlayer::Imd *&imdPtr) {
- if (!imdPtr)
- return;
-
- if (_soundStage == 2)
- _vm->_snd->stopSound(0);
-
- _vm->_dataIO->closeData(imdPtr->handle);
-
- delete[] imdPtr->frameCoords;
- delete[] imdPtr->palette;
- delete[] imdPtr->framesPos;
- delete[] imdPtr->extraPalette;
-
- delete imdPtr;
-
- if (_audioStream) {
- _audioStream->finish();
- _vm->_mixer->stopHandle(_audioHandle);
- _audioStream = 0;
- }
-}
-
-int8 ImdPlayer::openImd(const char *path, int16 x, int16 y,
- int16 startFrame, int16 flags) {
- const char *src;
- byte *vidMem;
- SurfaceDesc *surfDesc;
-
- if (!_curImd)
- _curFile[0] = 0;
-
- src = strrchr(path, '\\');
- src = !src ? path : src + 1;
-
- if ((path[0] != 0) && scumm_stricmp(_curFile, src)) {
- closeImd();
-
- _curImd = loadImdFile(path, 0, 3);
- if (!_curImd)
- return 0;
-
- _curX = _curImd->x;
- _curY = _curImd->y;
- strncpy0(_curFile, src, 17);
-
- delete[] _frameData;
- _frameData = new byte[_curImd->frameDataSize + 500];
- assert(_frameData);
- memset(_frameData, 0, _curImd->frameDataSize + 500);
-
- delete[] _vidBuffer;
- _vidBuffer = new byte[_curImd->vidBufferSize + 500];
- assert(_vidBuffer);
- memset(_vidBuffer, 0, _curImd->vidBufferSize + 500);
-
- if (!(flags & 0x100)) {
-
- if (_vm->_global->_videoMode == 0x14) {
-
- _backSurf = (flags & 0x80) ? 20 : 21;
- if (!(_curImd->field_E & 0x100) || (_curImd->field_E & 0x2000)) {
- setXY(_curImd, 0, 0);
- _curImd->surfDesc =
- _vm->_video->initSurfDesc(0x13,
- _curImd->width, _curImd->height, 0);
- } else {
- _curImd->surfDesc = _vm->_draw->_spritesArray[_frontSurf];
- if ((x != -1) || (y != -1)) {
- _curX = x != -1 ? x : _curX;
- _curY = y != -1 ? y : _curY;
- setXY(_curImd, _curX, _curY);
- }
- }
-
- if (flags & 0x40) {
- _curX = x != -1 ? x : _curX;
- _curY = y != -1 ? y : _curY;
- if (_curImd->surfDesc->_vidMode == 0x14) {
- surfDesc = _vm->_video->initSurfDesc(0x13,
- _curImd->width, _curImd->height, 0);
- _vm->_video->drawSprite(_vm->_draw->_spritesArray[21],
- surfDesc, _curX, _curY,
- _curX + _curImd->width - 1, _curY + _curImd->height - 1,
- 0, 0, 0);
-
- vidMem = _curImd->surfDesc->getVidMem();
- for (int i = 0; i < _curImd->height; i++)
- for (int j = 0; j < _curImd->width; j++, vidMem++) {
- *(vidMem) = *(surfDesc->getVidMem() +
- (j / 4) + (surfDesc->getWidth() / 4 * i));
- }
- surfDesc = 0;
- }
- }
-
- } else {
- if ((x != -1) || (y != -1)) {
- _curX = (x != -1) ? x : _curX;
- _curY = (y != -1) ? y : _curY;
- setXY(_curImd, _curX, _curY);
- }
- _backSurf = (flags & 0x80) ? 20 : 21;
- _curImd->surfDesc = _vm->_draw->_spritesArray[_backSurf];
- }
-
- }
- }
-
- if (!_curImd)
- return 0;
-
- if (startFrame == -1) {
- closeImd();
- return 0;
- }
-
- _curX = (x != -1) ? x : _curX;
- _curY = (y != -1) ? y : _curY;
-
- WRITE_VAR(7, _curImd->framesCount);
-
- return 1;
-}
-
-void ImdPlayer::closeImd(void) {
- finishImd(_curImd);
-
- delete[] _frameData;
- delete[] _vidBuffer;
- _frameData = 0;
- _vidBuffer = 0;
-
- _curImd = 0;
-}
-
-void ImdPlayer::setXY(ImdPlayer::Imd *imdPtr, int16 x, int16 y) {
- int i;
-
- if (imdPtr->stdX != -1) {
- imdPtr->stdX = imdPtr->stdX - imdPtr->x + x;
- imdPtr->stdY = imdPtr->stdY - imdPtr->y + y;
- }
-
- if (imdPtr->frameCoords) {
- for (i = 0; i < imdPtr->framesCount; i++) {
- if (imdPtr->frameCoords[i].left != -1) {
- imdPtr->frameCoords[i].left =
- imdPtr->frameCoords[i].left - imdPtr->x + x;
- imdPtr->frameCoords[i].top =
- imdPtr->frameCoords[i].top - imdPtr->y + y;
- imdPtr->frameCoords[i].right =
- imdPtr->frameCoords[i].right - imdPtr->x + x;
- imdPtr->frameCoords[i].bottom =
- imdPtr->frameCoords[i].bottom - imdPtr->y + y;
- }
- }
- }
-
- imdPtr->x = x;
- imdPtr->y = y;
-}
-
-void ImdPlayer::drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
- SurfaceDesc *dest) {
- if (!dest)
- dest = _vm->_draw->_frontSurface;
-
- if (frame == 0)
- _vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
- imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
- else if (imdPtr->frameCoords && (imdPtr->frameCoords[frame].left != -1))
- _vm->_video->drawSprite(imdPtr->surfDesc, dest,
- imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top,
- imdPtr->frameCoords[frame].right, imdPtr->frameCoords[frame].bottom,
- imdPtr->frameCoords[frame].left + x,
- imdPtr->frameCoords[frame].top + y, 0);
- else if (imdPtr->stdX != -1)
- _vm->_video->drawSprite(imdPtr->surfDesc, dest,
- imdPtr->stdX, imdPtr->stdY, imdPtr->stdX + imdPtr->stdWidth - 1,
- imdPtr->stdY + imdPtr->stdHeight - 1, x + imdPtr->stdX,
- y + imdPtr->stdY, 0);
- else
- _vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
- imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
-}
-
-void ImdPlayer::renderFrame(Imd *imdPtr) {
- int16 imdX, imdY;
- int16 imdW, imdH;
- int16 sW;
- uint16 pixCount, pixWritten;
- uint8 type;
- byte *imdVidMem;
- byte *imdVidMemBak;
- byte *dataPtr = 0;
- byte *srcPtr = 0;
-
- dataPtr = _frameData;
- imdX = imdPtr->x;
- imdY = imdPtr->y;
- imdW = imdPtr->width;
- imdH = imdPtr->height;
- sW = imdPtr->surfDesc->getWidth();
- imdVidMem = imdPtr->surfDesc->getVidMem() + sW * imdY + imdX;
-
- type = *dataPtr++;
- srcPtr = dataPtr;
-
- if (type & 0x10) { // Palette data
- type ^= 0x10;
- dataPtr += 49;
- }
-
- srcPtr = dataPtr;
- if (type & 0x80) { // Frame data is compressed
- srcPtr = _vidBuffer;
- type &= 0x7F;
- if ((type == 2) && (imdW == sW)) {
- frameUncompressor(imdVidMem, dataPtr);
- return;
- } else
- frameUncompressor(srcPtr, dataPtr);
- }
-
- if (type == 2) { // Whole block
- for (int i = 0; i < imdH; i++) {
- memcpy(imdVidMem, srcPtr, imdW);
- srcPtr += imdW;
- imdVidMem += sW;
- }
- } else if (type == 1) { // Sparse block
- imdVidMemBak = imdVidMem;
- for (int i = 0; i < imdH; i++) {
- pixWritten = 0;
- while (pixWritten < imdW) {
- pixCount = *srcPtr++;
- if (pixCount & 0x80) { // data
- pixCount = MIN((pixCount & 0x7F) + 1, imdW - 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 == 0x42) { // Whole quarter-wide block
- for (int i = 0; i < imdH; i++) {
- imdVidMemBak = imdVidMem;
-
- for (int j = 0; j < imdW; 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);
- }
- if (imdH == -1)
- memcpy(imdVidMem, srcPtr, imdW);
- } else { // Sparse half-high block
- imdVidMemBak = imdVidMem;
- for (int i = 0; i < imdH; i += 2) {
- pixWritten = 0;
- while (pixWritten < imdW) {
- pixCount = *srcPtr++;
- if (pixCount & 0x80) { // data
- pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
- memcpy(imdVidMem, srcPtr, pixCount);
- memcpy(imdVidMem + sW, srcPtr, pixCount);
-
- pixWritten += pixCount;
- imdVidMem += pixCount;
- srcPtr += pixCount;
- } else { // "hole"
- pixCount = (pixCount + 1) % 256;
- pixWritten += pixCount;
- imdVidMem += pixCount;
- }
- }
- imdVidMemBak += sW + sW;
- imdVidMem = imdVidMemBak;
- }
- }
-}
-
-void ImdPlayer::frameUncompressor(byte *dest, byte *src) {
- int i;
- byte buf[4370];
- uint16 chunkLength;
- uint16 frameLength;
- uint16 bufPos1;
- uint16 bufPos2;
- uint16 tmp;
- uint8 chunkBitField;
- uint8 chunkCount;
- bool mode;
-
- frameLength = READ_LE_UINT16(src);
- src += 4;
-
- if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
- src += 4;
- bufPos1 = 273;
- mode = 1; // 123Ch (cmp al, 12h)
- } else {
- bufPos1 = 4078;
- mode = 0; // 275h (jnz +2)
- }
-
- memset(buf, 32, bufPos1);
- chunkCount = 1;
- chunkBitField = 0;
-
- while (frameLength > 0) {
- chunkCount--;
- if (chunkCount == 0) {
- tmp = *src++;
- chunkCount = 8;
- chunkBitField = tmp;
- }
- if (chunkBitField % 2) {
- chunkBitField >>= 1;
- buf[bufPos1] = *src;
- *dest++ = *src++;
- bufPos1 = (bufPos1 + 1) % 4096;
- frameLength--;
- continue;
- }
- chunkBitField >>= 1;
-
- tmp = READ_LE_UINT16(src);
- src += 2;
- chunkLength = ((tmp & 0xF00) >> 8) + 3;
-
- if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
- (!mode && (chunkLength == 0)))
- chunkLength = *src++ + 0x12;
-
- bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
- if (((tmp + chunkLength) >= 4096) ||
- ((chunkLength + bufPos1) >= 4096)) {
-
- for (i = 0; i < chunkLength; i++, dest++) {
- *dest = buf[bufPos2];
- buf[bufPos1] = buf[bufPos2];
- bufPos1 = (bufPos1 + 1) % 4096;
- bufPos2 = (bufPos2 + 1) % 4096;
- }
-
- } else if (((tmp + chunkLength) < bufPos1) ||
- ((chunkLength + bufPos1) < bufPos2)) {
-
- memcpy(dest, buf + bufPos2, chunkLength);
- memmove(buf + bufPos1, buf + bufPos2, chunkLength);
-
- dest += chunkLength;
- bufPos1 += chunkLength;
- bufPos2 += chunkLength;
-
- } else {
-
- for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
- *dest = buf[bufPos2];
- buf[bufPos1] = buf[bufPos2];
- }
-
- }
- frameLength -= chunkLength;
-
- }
-}
-
-void ImdPlayer::play(const char *path, int16 x, int16 y, bool interruptible) {
- int16 mouseX;
- int16 mouseY;
- int16 buttons;
-
- _vm->_util->setFrameRate(12);
- if (!openImd(path, x, y, 0, 2))
- return;
-
- _vm->_video->fillRect(_vm->_draw->_frontSurface, x, y,
- x + _curImd->width - 1, y + _curImd->height - 1, 0);
-
- for (int i = 0; i < _curImd->framesCount; i++) {
- play(i, 4, 0, 255, 0, _curImd->framesCount - 1);
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B)))
- break;
- }
-
- closeImd();
-}
-
-void ImdPlayer::play(const char *path, int16 x, int16 y, int16 startFrame,
- int16 frames, bool fade, bool interruptible) {
- int16 mouseX;
- int16 mouseY;
- int16 buttons = 0;
- int endFrame;
-
- _vm->_util->setFrameRate(12);
- if (!openImd(path, x, y, 0, 0))
- return;
-
- _vm->_video->fillRect(_vm->_draw->_frontSurface, x, y,
- x + _curImd->width - 1, y + _curImd->height - 1, 0);
-
- if (fade)
- _vm->_palAnim->fade(0, -2, 0);
-
- endFrame = frames > 0 ? frames : _curImd->framesCount;
- for (int i = startFrame; i < endFrame; i++) {
- view(_curImd, i);
- drawFrame(_curImd, i, x, y);
- if (fade) {
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- fade = false;
- }
- _vm->_video->waitRetrace();
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B))) {
- _vm->_palAnim->fade(0, -2, 0);
- _vm->_video->clearSurf(_vm->_draw->_frontSurface);
- memset((char *) _vm->_draw->_vgaPalette, 0, 768);
-
- WRITE_VAR(4, buttons);
- WRITE_VAR(0, 0x11B);
- WRITE_VAR(57, (uint32) -1);
- break;
- }
-
- _vm->_util->waitEndFrame();
- }
-
- if (frames < 0) {
- endFrame = _curImd->framesCount + frames;
- for (int i = _curImd->framesCount - 1; i >= endFrame; i--) {
- seekFrame(_curImd, i, SEEK_SET, true);
- drawFrame(_curImd, i, x, y);
- _vm->_video->waitRetrace();
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B))) {
- _vm->_palAnim->fade(0, -2, 0);
- _vm->_video->clearSurf(_vm->_draw->_frontSurface);
- memset((char *) _vm->_draw->_vgaPalette, 0, 768);
-
- WRITE_VAR(4, buttons);
- WRITE_VAR(0, 0x11B);
- WRITE_VAR(57, (uint32) -1);
- break;
- }
-
- _vm->_util->waitEndFrame();
- }
- }
-
- closeImd();
-}
-
-void ImdPlayer::play(int16 frame, uint16 palCmd,
- int16 palStart, int16 palEnd, int16 palFrame, int16 lastFrame) {
- uint32 viewRet = 0;
- SurfaceDesc *surfDescBak;
- bool modifiedPal = false;
-
- _vm->_draw->_showCursor = 0;
-
- if ((frame < 0) || (frame > lastFrame))
- return;
-
- palCmd &= 0x3F;
- if ((frame == palFrame) || ((frame == lastFrame) && (palCmd == 8))) {
- modifiedPal = true;
- _vm->_draw->_applyPal = true;
-
- if (palCmd >= 4)
- copyPalette(palStart, palEnd);
- }
-
- if (modifiedPal && (palCmd == 8) && (_backSurf == 20))
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
- if (_curImd->surfDesc) {
- if (_curImd->surfDesc->_vidMode == 0x14) {
-
- if ((_frontMem == _vm->_draw->_frontSurface->getVidMem()) &&
- (_frontSurf == 20)) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_backSurface);
- viewRet = view(_curImd, frame);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_backSurface);
- } else
- viewRet = view(_curImd, frame);
-
- if (_frontSurf == 21)
- _vm->_draw->invalidateRect(_left, _top, _right, _bottom);
-
- } else {
- if ((_curImd->field_E & 0x100) &&
- (_vm->_global->_videoMode == 0x14) &&
- (_frontSurf == 20) &&
- (checkFrameType(_curImd, frame) & 0x8000) &&
- (_backSurf == 21)) {
-
- surfDescBak = _curImd->surfDesc;
- if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem())
- _curImd->surfDesc = _vm->_draw->_spritesArray[21];
- else
- _curImd->surfDesc = _vm->_draw->_spritesArray[20];
- setXY(_curImd, _curX, _curY);
- viewRet = view(_curImd, frame);
- _curImd->surfDesc = surfDescBak;
- setXY(_curImd, 0, 0);
-
- } else {
- viewRet = view(_curImd, frame);
- if (!(viewRet & 0x800))
- drawFrame(frame);
- }
- }
- } else
- viewRet = view(_curImd, frame);
-
- if (modifiedPal && (palCmd == 16)) {
- if (_backSurf == 21)
- _vm->_draw->forceBlit();
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- _vm->_draw->_noInvalidated = true;
- }
-
- if (viewRet & 0x10) {
- copyPalette(palStart, palEnd);
-
- if (_backSurf == 20)
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- else
- _vm->_draw->_applyPal = true;
- }
-
- if (modifiedPal && (palCmd == 8) && (_backSurf == 21))
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
- if (!(viewRet & 0x800)) {
- if (_vm->_draw->_cursorIndex == -1) {
- if (_frontSurf == 20)
- flipFrontMem();
- else
- _vm->_draw->blitInvalidated();
- } else
- _vm->_draw->animateCursor(-1);
- }
-
- if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
-
- // To allow quitting, etc. during IMDs
- _vm->_util->processInput();
- if (_vm->_quitRequested)
- return;
-
- if (_soundStage != 2) {
- if (viewRet & 0x800) {
- if (_frameDelay == 0)
- _vm->_util->delay(30);
- else {
- _frameDelay -= 30;
- if (_frameDelay < 0)
- _frameDelay = 0;
- }
- } else
- _vm->_util->waitEndFrame();
- }
-
- _vm->_inter->animPalette();
-}
-
-inline void ImdPlayer::drawFrame(int16 frame) {
- if (_backSurf == 21) {
-
- if (_vm->_global->_videoMode == 0x14) {
- if (_frontSurf == 21) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- drawFrame(_curImd, frame, _curX, _curY);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- _vm->_draw->invalidateRect(_curX + _left, _curY + _top,
- _curX + _right, _curY + _bottom);
- } else {
- if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem()) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- drawFrame(_curImd, frame, _curX, _curY);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- } else
- drawFrame(_curImd, frame, _curX, _curY);
- }
- } else
- _vm->_draw->invalidateRect(_left, _top, _right, _bottom);
-
- } else if (_vm->_global->_videoMode == 0x14)
- drawFrame(_curImd, frame, _curX, _curY);
-}
-
-inline void ImdPlayer::copyPalette(int16 palStart, int16 palEnd) {
- if ((palStart == -1) || (palEnd == -1))
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- (char *) _curImd->palette, 768);
- else
- memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
- palStart * 3, ((char *) (_curImd->palette)) + palStart * 3,
- (palEnd - palStart + 1) * 3);
-}
-
-inline void ImdPlayer::flipFrontMem() {
- if (_frontMem == _vm->_draw->_frontSurface->getVidMem())
- _frontMem = _vm->_draw->_backSurface->getVidMem();
- else
- _frontMem = _vm->_draw->_frontSurface->getVidMem();
-}
-
-uint16 ImdPlayer::checkFrameType(Imd *imdPtr, int16 frame) {
- uint16 retVal = 0;
- uint32 posBak;
- uint32 tmp;
- uint16 cmd;
- int16 frameBak;
-
- if (!imdPtr)
- return 0x8000;
-
- posBak = _vm->_dataIO->getPos(imdPtr->handle);
- frameBak = imdPtr->curFrame;
-
- if (imdPtr->curFrame != frame) {
- retVal |= 0x2000;
- seekFrame(imdPtr, frame, SEEK_SET);
- }
-
- do {
- if (frame != 0) {
- if (imdPtr->stdX != -1)
- retVal |= 0x1000;
- if (imdPtr->frameCoords && (imdPtr->frameCoords[frame].left != -1))
- retVal |= 0x400;
- }
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- if ((cmd & 0xFFF8) == 0xFFF0) {
- if (cmd == 0xFFF0) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- if (cmd == 0xFFF1) {
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF2) { // Skip (16 bit)
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF3) { // Skip (32 bit)
- tmp = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- }
- }
-
- // Jump to frame
- if (cmd == 0xFFFD) {
- frame = _vm->_dataIO->readUint16(imdPtr->handle);
- if (imdPtr->framesPos) {
- _vm->_dataIO->seekData(imdPtr->handle,
- imdPtr->framesPos[frame], SEEK_SET);
- retVal |= 0x200;
- continue;
- }
- break;
- }
-
- // Next sound slice data
- if (cmd == 0xFF00) {
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- // Initial sound data (all slices)
- } else if (cmd == 0xFF01) {
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize * _soundSlicesCount, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- // Frame video data
- if (cmd != 0) {
- _vm->_dataIO->readData(imdPtr->handle, _frameData, 5);
- retVal |= _frameData[0];
- } else
- retVal |= 0x800;
-
- break;
-
- } while (true);
-
- _vm->_dataIO->seekData(imdPtr->handle, posBak, SEEK_SET);
- imdPtr->curFrame = frameBak;
- return retVal;
-}
-
-void ImdPlayer::seekFrame(Imd *imdPtr, int16 frame, int16 from, bool restart) {
- uint32 framePos = 0;
-
- if (!imdPtr)
- return;
-
- if (from == SEEK_CUR)
- frame += imdPtr->curFrame;
- else if (from == SEEK_END)
- frame = imdPtr->framesCount - frame - 1;
-
- if (frame >= imdPtr->framesCount)
- return;
-
- if (frame == 0) {
- framePos = imdPtr->firstFramePos;
- } else if (frame == 1) {
- framePos = imdPtr->firstFramePos;
- _vm->_dataIO->seekData(imdPtr->handle, framePos, SEEK_SET);
- framePos += _vm->_dataIO->readUint16(imdPtr->handle) + 4;
- } else if (imdPtr->framesPos) {
- framePos = imdPtr->framesPos[frame];
- } else if (restart && (_soundStage == 0)) {
- for (int i = 0; i <= frame; i++)
- view(_curImd, i);
- } else
- error("%s: Frame %d is not directly accessible", _curFile, frame);
-
- _vm->_dataIO->seekData(imdPtr->handle, framePos, SEEK_SET);
- imdPtr->curFrame = frame;
-}
-
-uint32 ImdPlayer::view(Imd *imdPtr, int16 frame) {
- uint32 retVal = 0;
- uint32 cmd = 0;
- int16 xBak, yBak, heightBak, widthBak;
- bool hasNextCmd = false;
- bool startSound = false;
-
- if (!imdPtr)
- return 0x8000;
-
- if (frame != imdPtr->curFrame) {
- retVal |= 0x2000;
- seekFrame(imdPtr, frame, SEEK_SET);
- }
-
- _left = xBak = imdPtr->x;
- _top = yBak = imdPtr->y;
- _bottom = heightBak= imdPtr->height;
- _right = widthBak = imdPtr->width;
- _right += _left - 1;
- _bottom += _top - 1;
-
- if ((frame == 0) && (imdPtr->verMin & 0x800))
- _vm->_video->setPalette(imdPtr->palette);
-
- do {
- if (frame != 0) {
- if (imdPtr->stdX != -1) {
- _left = imdPtr->x = imdPtr->stdX;
- _top = imdPtr->y = imdPtr->stdY;
- _right = imdPtr->width = imdPtr->stdWidth;
- _bottom = imdPtr->height = imdPtr->stdHeight;
- _right += _left - 1;
- _bottom += _top - 1;
- retVal |= 0x1000;
- }
- if (imdPtr->frameCoords &&
- (imdPtr->frameCoords[frame].left != -1)) {
- _left = imdPtr->x = imdPtr->frameCoords[frame].left;
- _top = imdPtr->y = imdPtr->frameCoords[frame].top;
- _right = imdPtr->width =
- imdPtr->frameCoords[frame].right - imdPtr->x + 1;
- _bottom = imdPtr->height =
- imdPtr->frameCoords[frame].bottom - imdPtr->y + 1;
- _right += _left - 1;
- _bottom += _top - 1;
- retVal |= 0x400;
- }
- }
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- if ((cmd & 0xFFF8) == 0xFFF0) {
- if (cmd == 0xFFF0) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- if (cmd == 0xFFF1) {
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF2) { // Skip (16 bit)
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF3) { // Skip (32 bit)
- cmd = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- }
- }
-
- if (_soundStage != 0) {
- byte *soundBuf;
-
- if (!hasNextCmd)
- waitEndSoundSlice();
-
- // Next sound slice data
- if (cmd == 0xFF00) {
-
- if (!hasNextCmd && !_noSound) {
- soundBuf = new byte[_soundSliceSize];
- assert(soundBuf);
-
- _vm->_dataIO->readData(imdPtr->handle, soundBuf,
- _soundSliceSize);
- _vm->_snd->convToSigned(soundBuf, _soundSliceSize);
- _audioStream->queueBuffer(soundBuf, _soundSliceSize);
- } else
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize, SEEK_CUR);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- // Initial sound data (all slices)
- } else if (cmd == 0xFF01) {
- int dataLength = _soundSliceSize * _soundSlicesCount;
-
- if (!hasNextCmd && !_noSound) {
- soundBuf = new byte[dataLength];
- assert(soundBuf);
-
- _vm->_dataIO->readData(imdPtr->handle, soundBuf, dataLength);
- _vm->_snd->convToSigned(soundBuf, dataLength);
-
- _soundStage = 1;
- startSound = true;
- _audioStream->queueBuffer(soundBuf, dataLength);
- } else
- _vm->_dataIO->seekData(imdPtr->handle, dataLength, SEEK_CUR);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- // Empty sound slice
- } else if (!hasNextCmd && (!_noSound)) {
- soundBuf = new byte[_soundSliceSize];
- assert(soundBuf);
-
- memset(soundBuf, 0, _soundSliceSize);
- _audioStream->queueBuffer(soundBuf, _soundSliceSize);
- }
- }
-
- // Set palette
- if (cmd == 0xFFF4) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- retVal |= 0x10;
- if (imdPtr->extraPalette) {
- _vm->_dataIO->readData(imdPtr->handle,
- (byte *) imdPtr->extraPalette, 768);
- _vm->_video->setPalette(imdPtr->extraPalette);
- } else if (imdPtr->palette)
- _vm->_dataIO->readData(imdPtr->handle,
- (byte *) imdPtr->palette, 768);
- else
- _vm->_dataIO->readData(imdPtr->handle, _frameData, 768);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- hasNextCmd = false;
-
- // Jump to frame
- if (cmd == 0xFFFD) {
-
- frame = _vm->_dataIO->readUint16(imdPtr->handle);
- if (imdPtr->framesPos) {
- imdPtr->curFrame = frame;
- _vm->_dataIO->seekData(imdPtr->handle,
- imdPtr->framesPos[frame], SEEK_SET);
-
- hasNextCmd = true;
- retVal |= 0x200;
- }
-
- } else if (cmd == 0xFFFC) {
-
- retVal |= 1;
- cmd = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->readData(imdPtr->handle, _frameData, cmd + 2);
-
- if (imdPtr->surfDesc) {
- int16 left = imdPtr->x;
- int16 top = imdPtr->y;
- int16 right = imdPtr->width + left;
- int16 bottom = imdPtr->height + top;
-
- if (imdPtr->surfDesc->getWidth() < right) {
- left = 0;
- right = imdPtr->width;
- }
- if (imdPtr->surfDesc->getWidth() < right)
- right = imdPtr->surfDesc->getWidth();
- if (imdPtr->surfDesc->getHeight() < bottom) {
- top = 0;
- bottom = imdPtr->height;
- }
- if (imdPtr->surfDesc->getHeight() < bottom)
- bottom = imdPtr->surfDesc->getHeight();
-
- imdPtr->x = left;
- imdPtr->y = top;
- imdPtr->height = bottom - top;
- imdPtr->width = right - left;
-
- renderFrame(imdPtr);
- }
-
- retVal |= _frameData[0];
-
- // Frame video data
- } else if (cmd != 0) {
-
- _vm->_dataIO->readData(imdPtr->handle, _frameData, cmd + 2);
- if (imdPtr->surfDesc)
- renderFrame(imdPtr);
-
- retVal |= _frameData[0];
-
- } else
- retVal |= 0x800;
-
- } while (hasNextCmd);
-
- if (startSound) {
- _vm->_snd->stopSound(0);
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
- _soundStartTime = _vm->_util->getTimeKey();
- _skipFrames = 0;
- _soundStage = 2;
- }
-
- imdPtr->x = xBak;
- imdPtr->y = yBak;
- imdPtr->width = widthBak;
- imdPtr->height = heightBak;
-
- imdPtr->curFrame++;
- if ((imdPtr->curFrame == imdPtr->framesCount) && (_soundStage == 2)) {
- waitEndSoundSlice();
- _audioStream->finish();
- _vm->_mixer->stopHandle(_audioHandle);
- _audioStream = 0;
- }
-
- return retVal;
-}
-
-inline void ImdPlayer::waitEndSoundSlice() {
- if (_soundStage != 2)
- return;
-
- if (_skipFrames == 0) {
-
- _vm->_video->retrace();
-
- int32 waitTime = (_curImd->curFrame * _soundSliceLength) -
- (_vm->_util->getTimeKey() - _soundStartTime);
-
- if (waitTime < 0) {
- _skipFrames = -waitTime / _soundSliceLength;
- warning("IMD A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
- } else if (waitTime > 0)
- _vm->_util->delay(waitTime);
-
- } else
- _skipFrames--;
-}
-
-} // End of namespace Gob
diff --git a/engines/gob/imd.h b/engines/gob/imd.h
deleted file mode 100644
index 27d95cd579..0000000000
--- a/engines/gob/imd.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef GOB_IMD_H
-#define GOB_IMD_H
-
-#include "gob/video.h"
-#include "gob/sound.h"
-
-namespace Gob {
-
-class ImdPlayer {
-public:
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
- struct ImdCoord {
- int16 left;
- int16 top;
- int16 right;
- int16 bottom;
- } PACKED_STRUCT;
-
- struct Imd {
- int16 handle;
- int16 verMin;
- int16 framesCount;
- int16 x;
- int16 y;
- int16 width;
- int16 height;
- int16 field_E;
- int16 curFrame;
- Video::Color *palette;
- SurfaceDesc *surfDesc;
- int32 *framesPos;
- int32 firstFramePos;
- int16 stdX;
- int16 stdY;
- int16 stdWidth;
- int16 stdHeight;
- ImdCoord *frameCoords;
- int32 frameDataSize;
- int32 vidBufferSize;
- Video::Color *extraPalette;
- } PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
- Imd *_curImd;
- byte _frontSurf;
- int8 _backSurf;
- byte *_frontMem;
- int32 _frameDelay;
-
- uint8 _soundStage; // (0: no sound, 1: loaded, 2: playing)
-
- ImdPlayer(GobEngine *vm);
- virtual ~ImdPlayer();
-
- Imd *loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags);
- void finishImd(Imd *&imdPtr);
-
- int8 openImd(const char *path, int16 x, int16 y,
- int16 startFrame, int16 flags);
- void closeImd(void);
-
- void play(int16 frame, uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 lastFrame);
- void play(const char *path, int16 x, int16 y, bool interruptible);
- void play(const char *path, int16 x, int16 y, int16 startFrame,
- int16 frames, bool fade, bool interruptible);
-
-protected:
- char _curFile[18];
-
- int16 _curX;
- int16 _curY;
- int16 _left;
- int16 _top;
- int16 _right;
- int16 _bottom;
-
- byte *_frameData;
- byte *_vidBuffer;
-
- bool _noSound;
-
- uint32 _soundStartTime;
- uint32 _skipFrames;
-
- int16 _soundFreq;
- uint16 _soundSliceSize;
- int16 _soundSlicesCount;
- uint16 _soundSliceLength;
-
- Audio::AppendableAudioStream *_audioStream;
- Audio::SoundHandle _audioHandle;
-
- GobEngine *_vm;
-
- void copyPalette(int16 palStart, int16 palEnd);
- void flipFrontMem();
- void drawFrame(int16 frame);
- void setXY(Imd *imdPtr, int16 x, int16 y);
-
- void seekFrame(Imd *imdPtr, int16 frame, int16 from, bool restart = false);
- uint16 checkFrameType(Imd *imdPtr, int16 frame);
- void drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
- SurfaceDesc *dest = 0);
-
- uint32 view(ImdPlayer::Imd *imdPtr, int16 arg_4);
- void renderFrame(Imd *imdPtr);
- void frameUncompressor(byte *dest, byte *src);
-
- void waitEndSoundSlice();
-};
-
-} // End of namespace Gob
-
-#endif // GOB_IMD_H
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 2f1dbe5326..4712a19a5d 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -37,7 +37,7 @@
#include "gob/palanim.h"
#include "gob/sound.h"
#include "gob/video.h"
-#include "gob/imd.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -147,10 +147,12 @@ void Init::initGame(const char *totName) {
handle = _vm->_dataIO->openData(buffer);
if (handle >= 0) {
- // Get variables count
- _vm->_dataIO->seekData(handle, 0x2C, SEEK_SET);
- varsCount = _vm->_dataIO->readUint16(handle);
- _vm->_dataIO->closeData(handle);
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
+ stream->seek(0x2C);
+ varsCount = stream->readUint16LE();
+
+ delete stream;
_vm->_global->_inter_variables = new byte[varsCount * 4];
_vm->_global->_inter_variablesSizes = new byte[varsCount * 4];
@@ -167,14 +169,23 @@ void Init::initGame(const char *totName) {
_vm->_dataIO->closeData(imdHandle);
_vm->_draw->initScreen();
_vm->_draw->_cursorIndex = -1;
+
_vm->_util->longDelay(200); // Letting everything settle
- _vm->_imdPlayer->play("coktel", -1, -1, true);
+
+ if (_vm->_vidPlayer->openVideo("coktel.imd")) {
+ _vm->_vidPlayer->play();
+ _vm->_vidPlayer->closeVideo();
+ }
+
_vm->_draw->closeScreen();
} else if ((imdHandle = _vm->_dataIO->openData("coktel.clt")) >= 0) {
_vm->_draw->initScreen();
+
+ stream = _vm->_dataIO->openAsStream(imdHandle, true);
_vm->_util->clearPalette();
- _vm->_dataIO->readData(imdHandle, (byte *) _vm->_draw->_vgaPalette, 768);
- _vm->_dataIO->closeData(imdHandle);
+ stream->read((byte *) _vm->_draw->_vgaPalette, 768);
+ delete stream;
+
imdHandle = _vm->_dataIO->openData("coktel.ims");
if (imdHandle >= 0) {
byte *sprBuf;
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 1f529b7634..4da3746681 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -209,7 +209,7 @@ void Inter::funcBlock(int16 retFlag) {
// WORKAROUND:
// The EGA version of gob1 doesn't add a delay after showing
// images between levels. We manually add it here.
- if ((_vm->_features & GF_GOB1) && (_vm->_features & GF_EGA)) {
+ if ((_vm->getGameType() == kGameTypeGob1) && _vm->isEGA()) {
int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData;
if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie
!strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) ||
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index fe84741eed..a7317492ad 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -342,6 +342,7 @@ protected:
virtual void checkSwitchTable(byte **ppExec);
void o2_playMult();
+ void o2_freeMultKeys();
void o2_setRenderFlags();
void o2_multSub();
void o2_initMult();
@@ -378,6 +379,8 @@ protected:
bool o2_evaluateStore(OpFuncParams &params);
bool o2_printText(OpFuncParams &params);
bool o2_animPalInit(OpFuncParams &params);
+ bool o2_addCollision(OpFuncParams &params);
+ bool o2_freeCollision(OpFuncParams &params);
bool o2_goblinFunc(OpFuncParams &params);
bool o2_createSprite(OpFuncParams &params);
bool o2_stopSound(OpFuncParams &params);
@@ -478,6 +481,45 @@ protected:
bool o3_checkData(OpFuncParams &params);
bool o3_readData(OpFuncParams &params);
bool o3_writeData(OpFuncParams &params);
+
+ void o3_wobble(OpGobParams &params);
+};
+
+class Inter_v4 : public Inter_v3 {
+public:
+ Inter_v4(GobEngine *vm);
+ virtual ~Inter_v4() {}
+
+protected:
+ typedef void (Inter_v4::*OpcodeDrawProcV4)();
+ typedef bool (Inter_v4::*OpcodeFuncProcV4)(OpFuncParams &);
+ typedef void (Inter_v4::*OpcodeGoblinProcV4)(OpGobParams &);
+ struct OpcodeDrawEntryV4 {
+ OpcodeDrawProcV4 proc;
+ const char *desc;
+ };
+ struct OpcodeFuncEntryV4 {
+ OpcodeFuncProcV4 proc;
+ const char *desc;
+ };
+ struct OpcodeGoblinEntryV4 {
+ OpcodeGoblinProcV4 proc;
+ const char *desc;
+ };
+ const OpcodeDrawEntryV4 *_opcodesDrawV4;
+ const OpcodeFuncEntryV4 *_opcodesFuncV4;
+ const OpcodeGoblinEntryV4 *_opcodesGoblinV4;
+ static const int _goblinFuncLookUp[][2];
+
+ virtual void setupOpcodes();
+ virtual void executeDrawOpcode(byte i);
+ virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
+ virtual void executeGoblinOpcode(int i, OpGobParams &params);
+ virtual const char *getOpcodeDrawDesc(byte i);
+ virtual const char *getOpcodeFuncDesc(byte i, byte j);
+ virtual const char *getOpcodeGoblinDesc(int i);
+
+ void o4_playVmdOrMusic();
};
} // End of namespace Gob
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index ffbe9e45ea..492ea198a1 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -33,10 +33,10 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/imd.h"
#include "gob/palanim.h"
#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -717,11 +717,17 @@ const char *Inter_Bargon::getOpcodeGoblinDesc(int i) {
}
void Inter_Bargon::oBargon_intro0(OpGobParams &params) {
- _vm->_imdPlayer->play("scaa", 0, 160, 0, 92, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
+ _vm->_vidPlayer->play(0, 92, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro1(OpGobParams &params) {
- _vm->_imdPlayer->play("scaa", 0, 160, 0, -23, 1, 1);
+ if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true, 23);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
@@ -813,27 +819,45 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
}
void Inter_Bargon::oBargon_intro4(OpGobParams &params) {
- _vm->_imdPlayer->play("scba", 191, 54, 0, 0, 1, 1);
+ if (_vm->_vidPlayer->openVideo("scba", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro5(OpGobParams &params) {
- _vm->_imdPlayer->play("scbb", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbb", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro6(OpGobParams &params) {
- _vm->_imdPlayer->play("scbc", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro7(OpGobParams &params) {
- _vm->_imdPlayer->play("scbf", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbf", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro8(OpGobParams &params) {
- _vm->_imdPlayer->play("scbc", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro9(OpGobParams &params) {
- _vm->_imdPlayer->play("scbd", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbd", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
} // End of namespace Gob
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index a3277047e7..9f30d9dea2 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1136,13 +1136,13 @@ bool Inter_v1::o1_callSub(OpFuncParams &params) {
}
// Skipping the copy protection screen in Gobliiins
- if (!_vm->_copyProtection && (_vm->_features & GF_GOB1) && (offset == 3905)
+ if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob1) && (offset == 3905)
&& !scumm_stricmp(_vm->_game->_curTotFile, _vm->_startTot)) {
debugC(2, kDebugGameFlow, "Skipping copy protection screen");
return false;
}
// Skipping the copy protection screen in Gobliins 2
- if (!_vm->_copyProtection && (_vm->_features & GF_GOB2) && (offset == 1746)
+ if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob2) && (offset == 1746)
&& !scumm_stricmp(_vm->_game->_curTotFile, _vm->_startTot0)) {
debugC(2, kDebugGameFlow, "Skipping copy protection screen");
return false;
@@ -1174,6 +1174,10 @@ bool Inter_v1::o1_loadCursor(OpFuncParams &params) {
id = load16();
index = (int8) *_vm->_global->_inter_execPtr++;
+
+ if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth())
+ return false;
+
itemPtr = &_vm->_game->_totResourceTable->items[id];
offset = itemPtr->offset;
@@ -1613,7 +1617,7 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
_vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1;
if (_vm->_global->_videoMode < 0x13) {
- _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaSmallPalette;
+ _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
return false;
}
@@ -1650,8 +1654,9 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
// WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter
// to become 5000. We deliberately slow down busy-waiting, so we shorten
// the counting, too.
- if (((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
- (VAR(59) < 4000) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
+ if ((_vm->getGameType() == kGameTypeWeen) && (VAR(59) < 4000) &&
+ ((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
+ !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
WRITE_VAR(59, 4000);
switch (cmd) {
@@ -1700,6 +1705,10 @@ bool Inter_v1::o1_capturePush(OpFuncParams &params) {
top = _vm->_parse->parseValExpr();
width = _vm->_parse->parseValExpr();
height = _vm->_parse->parseValExpr();
+
+ if ((width < 0) || (height < 0))
+ return false;
+
_vm->_game->capturePush(left, top, width, height);
(*_vm->_scenery->_pCaptureCounter)++;
return false;
@@ -1887,7 +1896,9 @@ bool Inter_v1::o1_copySprite(OpFuncParams &params) {
}
bool Inter_v1::o1_fillRect(OpFuncParams &params) {
- _vm->_draw->_destSurface = load16();
+ int16 destSurf;
+
+ _vm->_draw->_destSurface = destSurf = load16();
_vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
_vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
@@ -1895,6 +1906,19 @@ bool Inter_v1::o1_fillRect(OpFuncParams &params) {
_vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
_vm->_draw->_backColor = _vm->_parse->parseValExpr();
+
+ if (!_vm->_draw->_spritesArray[(destSurf > 100) ? (destSurf - 80) : destSurf])
+ return false;
+
+ if (_vm->_draw->_spriteRight < 0) {
+ _vm->_draw->_destSpriteX += _vm->_draw->_spriteRight - 1;
+ _vm->_draw->_spriteRight = -_vm->_draw->_spriteRight + 2;
+ }
+ if (_vm->_draw->_spriteBottom < 0) {
+ _vm->_draw->_destSpriteY += _vm->_draw->_spriteBottom - 1;
+ _vm->_draw->_spriteBottom = -_vm->_draw->_spriteBottom + 2;
+ }
+
_vm->_draw->spriteOperation(DRAW_FILLRECT);
return false;
}
@@ -2201,22 +2225,23 @@ bool Inter_v1::o1_readData(OpFuncParams &params) {
WRITE_VAR(1, 1);
handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
if (handle >= 0) {
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
_vm->_draw->animateCursor(4);
if (offset < 0)
- _vm->_dataIO->seekData(handle, -offset - 1, SEEK_END);
+ stream->seek(-offset - 1, SEEK_END);
else
- _vm->_dataIO->seekData(handle, offset, SEEK_SET);
+ stream->seek(offset);
if (((dataVar >> 2) == 59) && (size == 4))
- WRITE_VAR(59, _vm->_dataIO->readUint32(handle));
+ WRITE_VAR(59, stream->readUint32LE());
else
- retSize = _vm->_dataIO->readData(handle,
- _vm->_global->_inter_variables + dataVar, size);
-
- _vm->_dataIO->closeData(handle);
+ retSize = stream->read(_vm->_global->_inter_variables + dataVar, size);
if (retSize == size)
WRITE_VAR(1, 0);
+
+ delete stream;
}
if (_vm->_game->_extHandle >= 0)
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index d69b6fda97..376aef75d9 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -38,7 +38,6 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/parse.h"
@@ -46,6 +45,7 @@
#include "gob/sound.h"
#include "gob/video.h"
#include "gob/saveload.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -134,7 +134,7 @@ void Inter_v2::setupOpcodes() {
/* 00 */
OPCODE(o1_loadMult),
OPCODE(o2_playMult),
- OPCODE(o1_freeMultKeys),
+ OPCODE(o2_freeMultKeys),
{NULL, ""},
/* 04 */
{NULL, ""},
@@ -485,8 +485,8 @@ void Inter_v2::setupOpcodes() {
OPCODE(o1_capturePop),
OPCODE(o2_animPalInit),
/* 18 */
- {NULL, ""},
- {NULL, ""},
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
{NULL, ""},
{NULL, ""},
/* 1C */
@@ -826,6 +826,17 @@ void Inter_v2::o2_playMult() {
_vm->_mult->playMult(VAR(57), -1, checkEscape & 0x1, 0);
}
+void Inter_v2::o2_freeMultKeys() {
+ uint16 index = load16();
+
+ if (!_vm->_mult->hasMultData(index))
+ return;
+
+ _vm->_mult->setMultData(index);
+ _vm->_mult->freeMultKeys();
+ _vm->_mult->zeroMultData(index);
+}
+
void Inter_v2::o2_setRenderFlags() {
int16 expr;
@@ -1364,11 +1375,37 @@ void Inter_v2::o2_initScreen() {
width = _vm->_parse->parseValExpr();
height = _vm->_parse->parseValExpr();
+ // Lost in Time switches to 640x400x16 when showing the title screen
+ if (_vm->getGameType() == kGameTypeLostInTime) {
+ if (videoMode == 0x10) {
+ width = _vm->_width = 640;
+ height = _vm->_height = 400;
+ _vm->_global->_colorCount = 16;
+ _vm->_system->beginGFXTransaction();
+ _vm->_system->initSize(_vm->_width, _vm->_height);
+ _vm->initCommonGFX(true);
+ _vm->_system->endGFXTransaction();
+ } else if (_vm->_global->_videoMode == 0x10) {
+ if (width == -1)
+ width = 320;
+ if (height == -1)
+ height = 200;
+
+ _vm->_width = 320;
+ _vm->_height = 200;
+ _vm->_global->_colorCount = 256;
+ _vm->_system->beginGFXTransaction();
+ _vm->_system->initSize(_vm->_width, _vm->_height);
+ _vm->initCommonGFX(false);
+ _vm->_system->endGFXTransaction();
+ }
+ }
+
_vm->_global->_fakeVideoMode = videoMode;
// Some versions require this
if (videoMode == 0xD)
- videoMode = 0x14;
+ videoMode = _vm->_mode;
if ((videoMode == _vm->_global->_videoMode) && (width == -1))
return;
@@ -1378,7 +1415,8 @@ void Inter_v2::o2_initScreen() {
if (height > 0)
_vm->_video->_surfHeight = height;
- _vm->_video->_splitHeight1 = MIN(200, _vm->_video->_surfHeight - offY);
+ _vm->_video->_splitHeight1 =
+ MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
_vm->_video->_splitHeight2 = offY;
_vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
@@ -1414,13 +1452,13 @@ void Inter_v2::o2_scroll() {
int16 curY;
startX = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfWidth - 320);
+ _vm->_video->_surfWidth - _vm->_width);
startY = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfHeight - 200);
+ _vm->_video->_surfHeight - _vm->_height);
endX = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfWidth - 320);
+ _vm->_video->_surfWidth - _vm->_width);
endY = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfHeight - 200);
+ _vm->_video->_surfHeight - _vm->_height);
stepX = _vm->_parse->parseValExpr();
stepY = _vm->_parse->parseValExpr();
@@ -1481,48 +1519,28 @@ void Inter_v2::o2_playImd() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
- if (!_vm->_imdPlayer->openImd(imd, x, y, startFrame, flags)) {
+ if ((imd[0] != 0) && !_vm->_vidPlayer->openVideo(imd, x, y, flags)) {
WRITE_VAR(11, -1);
return;
}
close = (lastFrame == -1);
- if (lastFrame < 0)
- lastFrame = _vm->_imdPlayer->_curImd->framesCount - 1;
if (startFrame == -2) {
startFrame = lastFrame = 0;
close = false;
}
- _vm->_game->_preventScroll = true;
- for (int i = startFrame; i <= lastFrame; i++) {
- _vm->_imdPlayer->play(i, palCmd, palStart, palEnd, 0, lastFrame);
- WRITE_VAR(11, i);
-
- if (_vm->_quitRequested)
- break;
-
- if (breakKey != 0) {
- _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
- &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
-
- storeKey(_vm->_util->checkKey());
- if (VAR(0) == (unsigned) breakKey) {
- if (_vm->_imdPlayer->_soundStage == 2)
- _vm->_snd->stopSound(0);
- _vm->_game->_preventScroll = false;
- return;
- }
- }
+ if (startFrame >= 0) {
+ _vm->_game->_preventScroll = true;
+ _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ _vm->_game->_preventScroll = false;
}
- _vm->_game->_preventScroll = false;
if (close)
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
}
void Inter_v2::o2_getImdInfo() {
- ImdPlayer::Imd *imd;
int16 varX, varY;
int16 varFrames;
int16 varWidth, varHeight;
@@ -1533,21 +1551,9 @@ void Inter_v2::o2_getImdInfo() {
varFrames = _vm->_parse->parseVarIndex();
varWidth = _vm->_parse->parseVarIndex();
varHeight = _vm->_parse->parseVarIndex();
- imd = _vm->_imdPlayer->loadImdFile(_vm->_global->_inter_resStr, 0, 2);
- if (!imd) {
- WRITE_VAR_OFFSET(varX, -1);
- WRITE_VAR_OFFSET(varY, -1);
- WRITE_VAR_OFFSET(varFrames, -1);
- WRITE_VAR_OFFSET(varWidth, -1);
- WRITE_VAR_OFFSET(varHeight, -1);
- } else {
- WRITE_VAR_OFFSET(varX, imd->x);
- WRITE_VAR_OFFSET(varY, imd->y);
- WRITE_VAR_OFFSET(varFrames, imd->framesCount);
- WRITE_VAR_OFFSET(varWidth, imd->width);
- WRITE_VAR_OFFSET(varHeight, imd->height);
- }
- _vm->_imdPlayer->finishImd(imd);
+
+ _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
+ varFrames, varWidth, varHeight);
}
void Inter_v2::o2_openItk() {
@@ -1565,21 +1571,9 @@ void Inter_v2::o2_closeItk() {
}
void Inter_v2::o2_setImdFrontSurf() {
- _vm->_imdPlayer->_frontSurf = 21;
- if (_vm->_global->_videoMode == 0x14) {
- _vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
- _vm->_draw->blitInvalidated();
- _vm->_imdPlayer->_frontSurf = 20;
- }
}
void Inter_v2::o2_resetImdFrontSurf() {
- _vm->_imdPlayer->_frontSurf = 21;
- if (_vm->_imdPlayer->_frontMem) {
- _vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
- _vm->_draw->forceBlit();
- } else
- _vm->_draw->forceBlit(true);
}
bool Inter_v2::o2_evaluateStore(OpFuncParams &params) {
@@ -1721,6 +1715,71 @@ bool Inter_v2::o2_animPalInit(OpFuncParams &params) {
return false;
}
+bool Inter_v2::o2_addCollision(OpFuncParams &params) {
+ int16 id;
+ int16 left, top, width, height;
+ int16 flags;
+ int16 key;
+ int16 funcSub;
+
+ id = _vm->_parse->parseValExpr();
+ funcSub = _vm->_global->_inter_execPtr - _vm->_game->_totFileData;
+ left = _vm->_parse->parseValExpr();
+ top = _vm->_parse->parseValExpr();
+ width = _vm->_parse->parseValExpr();
+ height = _vm->_parse->parseValExpr();
+ flags = _vm->_parse->parseValExpr();
+ key = load16();
+
+ if (key == 0)
+ key = ABS(id) + 41960;
+
+ _vm->_draw->adjustCoords(0, &left, &top);
+ _vm->_draw->adjustCoords(2, &width, &height);
+
+ if (left < 0) {
+ width += left;
+ left = 0;
+ }
+
+ if (top < 0) {
+ height += top;
+ top = 0;
+ }
+
+ int16 index;
+ if (id < 0)
+ index = _vm->_game->addNewCollision(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
+ left + width + 3, top + height + 3, flags, key, 0, 0);
+ else
+ index = _vm->_game->addNewCollision(0xE000 + id, left, top,
+ left + width - 1, top + height - 1, flags, key, 0, 0);
+
+ _vm->_game->_collisionAreas[index].funcSub = funcSub;
+
+ return false;
+}
+
+bool Inter_v2::o2_freeCollision(OpFuncParams &params) {
+ int16 id;
+
+ id = _vm->_parse->parseValExpr();
+ if (id == -2) {
+ for (int i = 0; i < 150; i++) {
+ if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000)
+ _vm->_game->_collisionAreas[i].left = 0xFFFF;
+ }
+ } else if (id == -1) {
+ for (int i = 0; i < 150; i++) {
+ if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000)
+ _vm->_game->_collisionAreas[i].left = 0xFFFF;
+ }
+ } else
+ _vm->_game->freeCollision(0xE000 + id);
+
+ return false;
+}
+
bool Inter_v2::o2_goblinFunc(OpFuncParams &params) {
OpGobParams gobParams;
int16 cmd;
@@ -1870,25 +1929,27 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
if (handle < 0)
return false;
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
_vm->_draw->animateCursor(4);
if (offset < 0)
- _vm->_dataIO->seekData(handle, -offset - 1, SEEK_END);
+ stream->seek(-offset - 1, SEEK_END);
else
- _vm->_dataIO->seekData(handle, offset, SEEK_SET);
+ stream->seek(offset);
if (((dataVar >> 2) == 59) && (size == 4)) {
- WRITE_VAR(59, _vm->_dataIO->readUint32(handle));
+ WRITE_VAR(59, stream->readUint32LE());
// The scripts in some versions divide through 256^3 then,
// effectively doing a LE->BE conversion
if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256))
WRITE_VAR(59, SWAP_BYTES_32(VAR(59)));
} else
- retSize = _vm->_dataIO->readData(handle, buf, size);
+ retSize = stream->read(buf, size);
if (retSize == size)
WRITE_VAR(1, 0);
- _vm->_dataIO->closeData(handle);
+ delete stream;
return false;
}
diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp
index d3389f2671..51413c839a 100644
--- a/engines/gob/inter_v3.cpp
+++ b/engines/gob/inter_v3.cpp
@@ -122,7 +122,7 @@ void Inter_v3::setupOpcodes() {
/* 00 */
OPCODE(o1_loadMult),
OPCODE(o2_playMult),
- OPCODE(o1_freeMultKeys),
+ OPCODE(o2_freeMultKeys),
{NULL, ""},
/* 04 */
{NULL, ""},
@@ -473,8 +473,8 @@ void Inter_v3::setupOpcodes() {
OPCODE(o1_capturePop),
OPCODE(o2_animPalInit),
/* 18 */
- {NULL, ""},
- {NULL, ""},
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
OPCODE(o3_getTotTextItemPart),
{NULL, ""},
/* 1C */
@@ -594,7 +594,7 @@ void Inter_v3::setupOpcodes() {
{NULL, ""},
{NULL, ""},
{NULL, ""},
- OPCODE(o2_handleGoblins),
+ OPCODE(o3_wobble),
/* 28 */
{NULL, ""},
{NULL, ""},
@@ -894,4 +894,8 @@ bool Inter_v3::o3_copySprite(OpFuncParams &params) {
return false;
}
+void Inter_v3::o3_wobble(OpGobParams &params) {
+ _vm->_draw->wobble(_vm->_draw->_backSurface);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
new file mode 100644
index 0000000000..81f53757a3
--- /dev/null
+++ b/engines/gob/inter_v4.cpp
@@ -0,0 +1,786 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/endian.h"
+#include "common/file.h"
+
+#include "gob/gob.h"
+#include "gob/inter.h"
+#include "gob/global.h"
+#include "gob/game.h"
+#include "gob/parse.h"
+#include "gob/videoplayer.h"
+
+namespace Gob {
+
+#define OPCODE(x) _OPCODE(Inter_v4, x)
+
+const int Inter_v4::_goblinFuncLookUp[][2] = {
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {4, 3},
+ {5, 4},
+ {6, 5},
+ {7, 6},
+ {8, 7},
+ {9, 8},
+ {10, 9},
+ {12, 10},
+ {13, 11},
+ {14, 12},
+ {15, 13},
+ {16, 14},
+ {21, 15},
+ {22, 16},
+ {23, 17},
+ {24, 18},
+ {25, 19},
+ {26, 20},
+ {27, 21},
+ {28, 22},
+ {29, 23},
+ {30, 24},
+ {32, 25},
+ {33, 26},
+ {34, 27},
+ {35, 28},
+ {36, 29},
+ {37, 30},
+ {40, 31},
+ {41, 32},
+ {42, 33},
+ {43, 34},
+ {44, 35},
+ {50, 36},
+ {52, 37},
+ {53, 38},
+ {100, 39},
+ {152, 40},
+ {200, 41},
+ {201, 42},
+ {202, 43},
+ {203, 44},
+ {204, 45},
+ {250, 46},
+ {251, 47},
+ {252, 48},
+ {500, 49},
+ {502, 50},
+ {503, 51},
+ {600, 52},
+ {601, 53},
+ {602, 54},
+ {603, 55},
+ {604, 56},
+ {605, 57},
+ {1000, 58},
+ {1001, 59},
+ {1002, 60},
+ {1003, 61},
+ {1004, 62},
+ {1005, 63},
+ {1006, 64},
+ {1008, 65},
+ {1009, 66},
+ {1010, 67},
+ {1011, 68},
+ {1015, 69},
+ {2005, 70}
+};
+
+Inter_v4::Inter_v4(GobEngine *vm) : Inter_v3(vm) {
+ setupOpcodes();
+}
+
+void Inter_v4::setupOpcodes() {
+ static const OpcodeDrawEntryV4 opcodesDraw[256] = {
+ /* 00 */
+ OPCODE(o1_loadMult),
+ OPCODE(o2_playMult),
+ OPCODE(o2_freeMultKeys),
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_initCursor),
+ /* 08 */
+ OPCODE(o1_initCursorAnim),
+ OPCODE(o1_clearCursorAnim),
+ OPCODE(o2_setRenderFlags),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ OPCODE(o1_loadAnim),
+ OPCODE(o1_freeAnim),
+ OPCODE(o1_updateAnim),
+ OPCODE(o2_multSub),
+ /* 14 */
+ OPCODE(o2_initMult),
+ OPCODE(o1_freeMult),
+ OPCODE(o1_animate),
+ OPCODE(o2_loadMultObject),
+ /* 18 */
+ OPCODE(o1_getAnimLayerInfo),
+ OPCODE(o1_getObjAnimSize),
+ OPCODE(o1_loadStatic),
+ OPCODE(o1_freeStatic),
+ /* 1C */
+ OPCODE(o2_renderStatic),
+ OPCODE(o2_loadCurLayer),
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ OPCODE(o2_playCDTrack),
+ OPCODE(o2_waitCDTrackEnd),
+ OPCODE(o2_stopCD),
+ OPCODE(o2_readLIC),
+ /* 24 */
+ OPCODE(o2_freeLIC),
+ OPCODE(o2_getCDTrackPos),
+ {NULL, ""},
+ {NULL, ""},
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o2_loadFontToSprite),
+ OPCODE(o1_freeFontToSprite),
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ OPCODE(o2_totSub),
+ OPCODE(o2_switchTotSub),
+ OPCODE(o2_copyVars),
+ OPCODE(o2_pasteVars),
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 48 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 4C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 50 */
+ OPCODE(o2_loadMapObjects),
+ OPCODE(o2_freeGoblins),
+ OPCODE(o2_moveGoblin),
+ OPCODE(o2_writeGoblinPos),
+ /* 54 */
+ OPCODE(o2_stopGoblin),
+ OPCODE(o2_setGoblinState),
+ OPCODE(o2_placeGoblin),
+ {NULL, ""},
+ /* 58 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 5C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 60 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 64 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 68 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 6C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 70 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 74 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 78 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 7C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 80 */
+ OPCODE(o2_initScreen),
+ OPCODE(o2_scroll),
+ OPCODE(o2_setScrollOffset),
+ OPCODE(o4_playVmdOrMusic),
+ /* 84 */
+ OPCODE(o2_getImdInfo),
+ OPCODE(o2_openItk),
+ OPCODE(o2_closeItk),
+ OPCODE(o2_setImdFrontSurf),
+ /* 88 */
+ OPCODE(o2_resetImdFrontSurf),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 8C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 90 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 94 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 98 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 9C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* AC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* BC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* CC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* DC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* EC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* FC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""}
+ };
+
+ static const OpcodeFuncEntryV4 opcodesFunc[80] = {
+ /* 00 */
+ OPCODE(o1_callSub),
+ OPCODE(o1_callSub),
+ OPCODE(o1_printTotText),
+ OPCODE(o1_loadCursor),
+ /* 04 */
+ {NULL, ""},
+ OPCODE(o1_switch),
+ OPCODE(o1_repeatUntil),
+ OPCODE(o1_whileDo),
+ /* 08 */
+ OPCODE(o1_if),
+ OPCODE(o2_evaluateStore),
+ OPCODE(o1_loadSpriteToPos),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ OPCODE(o2_printText),
+ OPCODE(o1_loadTot),
+ OPCODE(o1_palLoad),
+ /* 14 */
+ OPCODE(o1_keyFunc),
+ OPCODE(o1_capturePush),
+ OPCODE(o1_capturePop),
+ OPCODE(o2_animPalInit),
+ /* 18 */
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
+ OPCODE(o3_getTotTextItemPart),
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_drawOperations),
+ OPCODE(o1_setcmdCount),
+ /* 20 */
+ OPCODE(o1_return),
+ OPCODE(o1_renewTimeInVars),
+ OPCODE(o1_speakerOn),
+ OPCODE(o1_speakerOff),
+ /* 24 */
+ OPCODE(o1_putPixel),
+ OPCODE(o2_goblinFunc),
+ OPCODE(o2_createSprite),
+ OPCODE(o1_freeSprite),
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o1_returnTo),
+ OPCODE(o1_loadSpriteContent),
+ OPCODE(o3_copySprite),
+ OPCODE(o1_fillRect),
+ /* 34 */
+ OPCODE(o1_drawLine),
+ OPCODE(o1_strToLong),
+ OPCODE(o1_invalidate),
+ OPCODE(o1_setBackDelta),
+ /* 38 */
+ OPCODE(o1_playSound),
+ OPCODE(o2_stopSound),
+ OPCODE(o2_loadSound),
+ OPCODE(o1_freeSoundSlot),
+ /* 3C */
+ OPCODE(o1_waitEndPlay),
+ OPCODE(o1_playComposition),
+ OPCODE(o2_getFreeMem),
+ OPCODE(o2_checkData),
+ /* 40 */
+ {NULL, ""},
+ OPCODE(o1_prepareStr),
+ OPCODE(o1_insertStr),
+ OPCODE(o1_cutStr),
+ /* 44 */
+ OPCODE(o1_strstr),
+ OPCODE(o1_istrlen),
+ OPCODE(o1_setMousePos),
+ OPCODE(o1_setFrameRate),
+ /* 48 */
+ OPCODE(o1_animatePalette),
+ OPCODE(o1_animateCursor),
+ OPCODE(o1_blitCursor),
+ OPCODE(o1_loadFont),
+ /* 4C */
+ OPCODE(o1_freeFont),
+ OPCODE(o2_readData),
+ OPCODE(o2_writeData),
+ OPCODE(o1_manageDataFile),
+ };
+
+ static const OpcodeGoblinEntryV4 opcodesGoblin[71] = {
+ /* 00 */
+ OPCODE(o2_loadInfogramesIns),
+ OPCODE(o2_startInfogrames),
+ OPCODE(o2_stopInfogrames),
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 08 */
+ {NULL, ""},
+ OPCODE(o2_playInfogrames),
+ {NULL, ""},
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 14 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 18 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 24 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o2_handleGoblins),
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ };
+
+ _opcodesDrawV4 = opcodesDraw;
+ _opcodesFuncV4 = opcodesFunc;
+ _opcodesGoblinV4 = opcodesGoblin;
+}
+
+void Inter_v4::executeDrawOpcode(byte i) {
+ debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
+ i, i, getOpcodeDrawDesc(i));
+
+ OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeDraw: %d", i);
+ else
+ (this->*op) ();
+}
+
+bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
+ debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
+ i, j, i, j, getOpcodeFuncDesc(i, j));
+
+ if ((i > 4) || (j > 15)) {
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ return false;
+ }
+
+ OpcodeFuncProcV4 op = _opcodesFuncV4[i*16 + j].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ else
+ return (this->*op) (params);
+
+ return false;
+}
+
+void Inter_v4::executeGoblinOpcode(int i, OpGobParams &params) {
+ debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
+ i, i, getOpcodeGoblinDesc(i));
+
+ OpcodeGoblinProcV4 op = NULL;
+
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i) {
+ op = _opcodesGoblinV4[_goblinFuncLookUp[j][1]].proc;
+ break;
+ }
+
+ if (op == NULL) {
+ int16 val;
+
+ _vm->_global->_inter_execPtr -= 2;
+ val = load16();
+ _vm->_global->_inter_execPtr += val << 1;
+ } else
+ (this->*op) (params);
+}
+
+const char *Inter_v4::getOpcodeDrawDesc(byte i) {
+ return _opcodesDrawV4[i].desc;
+}
+
+const char *Inter_v4::getOpcodeFuncDesc(byte i, byte j) {
+ if ((i > 4) || (j > 15))
+ return "";
+
+ return _opcodesFuncV4[i*16 + j].desc;
+}
+
+const char *Inter_v4::getOpcodeGoblinDesc(int i) {
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i)
+ return _opcodesGoblinV4[_goblinFuncLookUp[j][1]].desc;
+ return "";
+}
+
+void Inter_v4::o4_playVmdOrMusic() {
+ char fileName[128];
+ int16 x, y;
+ int16 startFrame;
+ int16 lastFrame;
+ int16 breakKey;
+ int16 flags;
+ int16 palStart;
+ int16 palEnd;
+ uint16 palCmd;
+ bool close;
+
+ evalExpr(0);
+ _vm->_global->_inter_resStr[8] = 0;
+ strncpy0(fileName, _vm->_global->_inter_resStr, 127);
+
+ x = _vm->_parse->parseValExpr();
+ y = _vm->_parse->parseValExpr();
+ startFrame = _vm->_parse->parseValExpr();
+ lastFrame = _vm->_parse->parseValExpr();
+ breakKey = _vm->_parse->parseValExpr();
+ flags = _vm->_parse->parseValExpr();
+ palStart = _vm->_parse->parseValExpr();
+ palEnd = _vm->_parse->parseValExpr();
+ palCmd = 1 << (flags & 0x3F);
+
+ close = false;
+ if (lastFrame == -1) {
+ close = true;
+ } else if (lastFrame == -3) {
+ warning("Woodruff Stub: Video/Music command -3: Play background video %s", fileName);
+// return;
+ } else if (lastFrame == -4) {
+ warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName);
+ return;
+ } else if (lastFrame == -5) {
+ warning("Woodruff Stub: Video/Music command -5: Stop background music");
+ return;
+ } else if (lastFrame == -6) {
+ warning("Woodruff Stub: Video/Music command -6: Load background video %s", fileName);
+ return;
+ } else if (lastFrame == -8) {
+ warning("Woodruff Stub: Video/Music command -8: Play background video %s", fileName);
+ return;
+ } else if (lastFrame == -9) {
+ warning("Woodruff Stub: Video/Music command -9: Play background music %s (%d-%d)", fileName, palEnd, palStart);
+ return;
+ } else if (lastFrame < 0) {
+ warning("Unknown Video/Music command: %d, %s", lastFrame, fileName);
+ return;
+ }
+
+ if (startFrame == -2) {
+ startFrame = lastFrame = 0;
+ close = false;
+ }
+
+ if ((fileName[0] != 0) && !_vm->_vidPlayer->openVideo(fileName, x, y, flags)) {
+ WRITE_VAR(11, -1);
+ return;
+ }
+
+ if (startFrame >= 0) {
+ _vm->_game->_preventScroll = true;
+ _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ _vm->_game->_preventScroll = false;
+ }
+
+ if (close)
+ _vm->_vidPlayer->closeVideo();
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp
index 3c1895d099..5485d66987 100644
--- a/engines/gob/map.cpp
+++ b/engines/gob/map.cpp
@@ -261,7 +261,7 @@ void Map::findNearestWalkable(int16 &gobDestX, int16 &gobDestY,
int i;
mapWidth = _screenWidth / _tilesWidth;
- mapHeight = 200 / _tilesHeight;
+ mapHeight = _vm->_width / _tilesHeight;
direction = 0;
for (i = 1; i <= gobDestX; i++)
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index db0660fa5c..7571853f27 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -18,7 +18,8 @@ MODULE_OBJS := \
goblin_v1.o \
goblin_v2.o \
goblin_v3.o \
- imd.o \
+ coktelvideo.o \
+ videoplayer.o \
init.o \
init_v1.o \
init_v2.o \
@@ -26,8 +27,9 @@ MODULE_OBJS := \
inter.o \
inter_v1.o \
inter_v2.o \
- inter_v3.o \
inter_bargon.o \
+ inter_v3.o \
+ inter_v4.o \
map.o \
map_v1.o \
map_v2.o \
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index edfbb682ea..16d9961f89 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -112,7 +112,7 @@ public:
} PACKED_STRUCT;
struct Mult_AnimKey {
- int16 frame;
+ uint16 frame;
int16 layer;
int16 posX;
int16 posY;
@@ -246,8 +246,10 @@ public:
virtual void loadMult(int16 resId) = 0;
virtual void freeMultKeys() = 0;
- virtual void setMultData(uint16 multindex) = 0;
- virtual void multSub(uint16 multindex) = 0;
+ virtual bool hasMultData(uint16 multIndex) = 0;
+ virtual void setMultData(uint16 multIndex) = 0;
+ virtual void zeroMultData(uint16 multIndex) = 0;
+ virtual void multSub(uint16 multIndex) = 0;
virtual void animate() = 0;
Mult(GobEngine *vm);
@@ -299,8 +301,10 @@ public:
virtual void loadMult(int16 resId);
virtual void freeMultKeys();
- virtual void setMultData(uint16 multindex);
- virtual void multSub(uint16 multindex);
+ virtual bool hasMultData(uint16 multIndex);
+ virtual void setMultData(uint16 multIndex);
+ virtual void zeroMultData(uint16 multIndex);
+ virtual void multSub(uint16 multIndex);
virtual void animate();
protected:
@@ -317,8 +321,10 @@ public:
virtual void loadMult(int16 resId);
virtual void freeMultKeys();
- virtual void setMultData(uint16 multindex);
- virtual void multSub(uint16 multindex);
+ virtual bool hasMultData(uint16 multIndex);
+ virtual void setMultData(uint16 multIndex);
+ virtual void zeroMultData(uint16 multIndex);
+ virtual void multSub(uint16 multIndex);
virtual void animate();
protected:
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp
index 45ce9aa8a0..0c367870ac 100644
--- a/engines/gob/mult_v1.cpp
+++ b/engines/gob/mult_v1.cpp
@@ -237,11 +237,19 @@ void Mult_v1::freeMultKeys() {
_multData = 0;
}
-void Mult_v1::setMultData(uint16 multindex) {
+bool Mult_v1::hasMultData(uint16 multIndex) {
error("Switching mults not supported for Gob1");
}
-void Mult_v1::multSub(uint16 multindex) {
+void Mult_v1::setMultData(uint16 multIndex) {
+ error("Switching mults not supported for Gob1");
+}
+
+void Mult_v1::zeroMultData(uint16 multIndex) {
+ error("Switching mults not supported for Gob1");
+}
+
+void Mult_v1::multSub(uint16 multIndex) {
error("Switching mults not supported for Gob1");
}
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index f57d5ecb0c..cced4aac63 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -34,11 +34,11 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/inter.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -346,28 +346,42 @@ void Mult_v2::freeMultKeys() {
_multData = 0;
}
-void Mult_v2::setMultData(uint16 multindex) {
- if (multindex > 7)
+bool Mult_v2::hasMultData(uint16 multIndex) {
+ if (multIndex > 7)
error("Multindex out of range");
- debugC(4, kDebugGameFlow, "Switching to mult %d", multindex);
- _multData = _multDatas[multindex];
+ return _multDatas[multIndex] != 0;
}
-void Mult_v2::multSub(uint16 multindex) {
+void Mult_v2::setMultData(uint16 multIndex) {
+ if (multIndex > 7)
+ error("Multindex out of range");
+
+ debugC(4, kDebugGameFlow, "Switching to mult %d", multIndex);
+ _multData = _multDatas[multIndex];
+}
+
+void Mult_v2::zeroMultData(uint16 multIndex) {
+ if (multIndex > 7)
+ error("Multindex out of range");
+
+ _multDatas[multIndex] = 0;
+}
+
+void Mult_v2::multSub(uint16 multIndex) {
uint16 flags;
int16 expr;
int16 index;
int16 startFrame, stopFrame, firstFrame;
- flags = multindex;
- multindex = (multindex >> 12) & 0xF;
+ flags = multIndex;
+ multIndex = (multIndex >> 12) & 0xF;
- if (multindex > 7)
+ if (multIndex > 7)
error("Multindex out of range");
- debugC(4, kDebugGameFlow, "Sub mult %d", multindex);
- _multData = _multDatas[multindex];
+ debugC(4, kDebugGameFlow, "Sub mult %d", multIndex);
+ _multData = _multDatas[multIndex];
if (!_multData) {
_vm->_parse->parseValExpr();
@@ -1027,7 +1041,7 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
x = y = -1;
if (key.imdFile == -1) {
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
_vm->_game->_preventScroll = false;
return;
}
@@ -1045,23 +1059,24 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
if ((lastFrame - palFrame) < startFrame)
if (!(key.flags & 0x4000)) {
_vm->_game->_preventScroll = false;
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
return;
}
- if (!_vm->_imdPlayer->openImd(imdFile, x, y, 0, flags)) {
+ if (!_vm->_vidPlayer->openVideo(imdFile, x, y, flags)) {
_vm->_game->_preventScroll = false;
return;
}
if (palFrame == -1)
palFrame = 0;
+
if (lastFrame == -1)
- lastFrame = _vm->_imdPlayer->_curImd->framesCount - 1;
+ lastFrame = _vm->_vidPlayer->getFramesCount() - 1;
baseFrame = startFrame % (lastFrame - palFrame + 1);
- _vm->_imdPlayer->play(baseFrame + palFrame, flags & 0x7F,
- palStart, palEnd, palFrame, lastFrame);
+ _vm->_vidPlayer->play(baseFrame + palFrame, baseFrame + palFrame, 0,
+ flags & 0x7F, palStart, palEnd, palFrame, lastFrame);
}
void Mult_v2::advanceObjects(int16 index) {
@@ -1074,13 +1089,19 @@ void Mult_v2::advanceObjects(int16 index) {
return;
for (int i = 0; i < 4; i++) {
+ int obj = _multData->animObjs[index][i];
+
if (_multData->animObjs[index][i] != -1) {
int keyIndex = _multData->animKeysIndices[index][i];
int count = _multData->animKeysCount[i];
for (int j = keyIndex; j < count; j++) {
+
+ if ((obj == -1) || (obj == 1024))
+ continue;
+
Mult_AnimKey &key = _multData->animKeys[i][j];
- Mult_Object &animObj = _objects[_multData->animObjs[index][i]];
+ Mult_Object &animObj = _objects[obj];
Mult_AnimData &animData = *(animObj.pAnimData);
if (key.frame > frame)
@@ -1122,7 +1143,7 @@ void Mult_v2::advanceObjects(int16 index) {
}
}
- if (_multData->animObjs[index][i] != -1) {
+ if (obj != -1) {
int keyIndex = _multData->imdKeysIndices[index][i];
int count = _multData->imdKeysCount[i];
diff --git a/engines/gob/saveload.h b/engines/gob/saveload.h
index b8c9e730dd..d7e45246ad 100644
--- a/engines/gob/saveload.h
+++ b/engines/gob/saveload.h
@@ -136,7 +136,8 @@ class SaveLoad_v3 : public SaveLoad_v2 {
public:
virtual SaveType getSaveType(const char *fileName);
- SaveLoad_v3(GobEngine *vm, const char *targetName);
+ SaveLoad_v3(GobEngine *vm, const char *targetName, uint32 screenshotSize = 19968,
+ int32 indexOffset = 40, int32 screenshotOffset = 80);
virtual ~SaveLoad_v3() {}
protected:
@@ -144,13 +145,15 @@ protected:
bool _firstSizeGame;
int8 _saveSlot;
+ uint32 _screenshotSize;
+ int32 _indexOffset;
+ int32 _screenshotOffset;
+
virtual uint32 getSaveGameSize();
virtual int32 getSizeGame();
- virtual int32 getSizeNotes();
virtual int32 getSizeScreenshot();
virtual bool loadGame(int16 dataVar, int32 size, int32 offset);
- virtual bool loadNotes(int16 dataVar, int32 size, int32 offset);
virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset);
virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
diff --git a/engines/gob/saveload_v2.cpp b/engines/gob/saveload_v2.cpp
index 35c3429ab6..13f23cccb6 100644
--- a/engines/gob/saveload_v2.cpp
+++ b/engines/gob/saveload_v2.cpp
@@ -47,6 +47,10 @@ SaveLoad_v2::SaveLoad_v2(GobEngine *vm, const char *targetName) :
}
SaveType SaveLoad_v2::getSaveType(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ fileName = backSlash + 1;
+
if (!scumm_stricmp(fileName, "cat.inf"))
return kSaveGame;
if (!scumm_stricmp(fileName, "cat.cat"))
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index b376a8a75c..d0f791d8df 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -34,9 +34,14 @@
namespace Gob {
-SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName) :
+SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName,
+ uint32 screenshotSize, int32 indexOffset, int32 screenshotOffset) :
SaveLoad_v2(vm, targetName) {
+ _screenshotSize = screenshotSize;
+ _indexOffset = indexOffset;
+ _screenshotOffset = screenshotOffset;
+
_saveSlot = -1;
_stagesCount = 3;
@@ -58,12 +63,18 @@ SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName) :
}
SaveType SaveLoad_v3::getSaveType(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ fileName = backSlash + 1;
+
if (!scumm_stricmp(fileName, "cat.inf"))
return kSaveGame;
if (!scumm_stricmp(fileName, "ima.inf"))
return kSaveScreenshot;
if (!scumm_stricmp(fileName, "intro.$$$"))
return kSaveTempSprite;
+ if (!scumm_stricmp(fileName, "bloc.inf"))
+ return kSaveNotes;
if (!scumm_stricmp(fileName, "prot"))
return kSaveIgnore;
if (!scumm_stricmp(fileName, "config"))
@@ -77,15 +88,11 @@ uint32 SaveLoad_v3::getSaveGameSize() {
size = 1040 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2;
if (_useScreenshots)
- size += 19968;
+ size += _screenshotSize;
return size;
}
-int32 SaveLoad_v3::getSizeNotes() {
- return -1;
-}
-
int32 SaveLoad_v3::getSizeGame() {
if (_firstSizeGame) {
_firstSizeGame = false;
@@ -122,7 +129,7 @@ int32 SaveLoad_v3::getSizeScreenshot() {
in = saveMan->openForLoading(setCurSlot(i));
if (in) {
delete in;
- size = (i + 1) * 19968 + 80;
+ size = (i + 1) * _screenshotSize + _screenshotOffset;
break;
}
}
@@ -206,19 +213,15 @@ bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) {
return false;
}
-bool SaveLoad_v3::loadNotes(int16 dataVar, int32 size, int32 offset) {
- return false;
-}
-
bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
- int slot = (offset - 80) / 19968;
- int slotR = (offset - 80) % 19968;
+ int slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotR = (offset - _screenshotOffset) % _screenshotSize;
_useScreenshots = true;
- if ((size == 40) && (offset == 40)) {
+ if ((size == 40) && (offset == _indexOffset)) {
char buf[40];
memset(buf, 0, 40);
@@ -327,16 +330,16 @@ bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) {
}
bool SaveLoad_v3::saveNotes(int16 dataVar, int32 size, int32 offset) {
- return false;
+ return SaveLoad_v2::saveNotes(dataVar, size - 160, offset);
}
bool SaveLoad_v3::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - 80) / 19968;
- int slotR = (offset - 80) % 19968;
+ int slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotR = (offset - _screenshotOffset) % _screenshotSize;
_useScreenshots = true;
- if ((offset < 80) && (size > 0)) {
+ if ((offset < _screenshotOffset) && (size > 0)) {
return true;
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index ae04c220d3..95cf90bddc 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -320,7 +320,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
int16 top;
int16 bottom;
- if (layer >= _statics[index].layersCount)
+ if ((index >= 10) || layer >= _statics[index].layersCount)
return;
layerPtr = &_statics[index].layers[layer];
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index ff6333aa9e..40acf21f9e 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -32,7 +32,6 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/imd.h"
#include "gob/sound.h"
#include "gob/video.h"
@@ -50,6 +49,9 @@ uint32 Util::getTimeKey(void) {
}
int16 Util::getRandom(int16 max) {
+ if (max == 0)
+ return 0;
+
return _vm->_rnd.getRandomNumber(max - 1);
}
@@ -126,8 +128,8 @@ void Util::processInput(bool scroll) {
_vm->_global->_speedFactor = MIN(_fastMode + 1, 3);
if (scroll && hasMove) {
- if (y >= (200 - _vm->_video->_splitHeight2)) {
- y = 200 - _vm->_video->_splitHeight2 - 1;
+ if (y >= (_vm->_height - _vm->_video->_splitHeight2)) {
+ y = _vm->_height - _vm->_video->_splitHeight2 - 1;
_vm->_util->setMousePos(x, y);
}
_vm->_game->evaluateScroll(x, y);
@@ -301,7 +303,6 @@ void Util::setFrameRate(int16 rate) {
_vm->_global->_frameWaitTime = 1000 / rate;
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = 0;
}
void Util::waitEndFrame() {
@@ -312,17 +313,13 @@ void Util::waitEndFrame() {
time = getTimeKey() - _vm->_global->_startFrameTime;
if ((time > 1000) || (time < 0)) {
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = 0;
return;
}
- if (_vm->_global->_frameWaitTime - time > 0) {
- _vm->_imdPlayer->_frameDelay = 0;
- delay(_vm->_global->_frameWaitTime - _vm->_imdPlayer->_frameDelay - time);
- }
+ if ((_vm->_global->_frameWaitTime - time) > 0)
+ delay(_vm->_global->_frameWaitTime - time);
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = time - _vm->_global->_frameWaitTime;
}
void Util::setScrollOffset(int16 x, int16 y) {
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 6f88a5a993..0dc15a8657 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -94,6 +94,7 @@ Video::Video(GobEngine *vm) : _vm(vm) {
_splitHeight1 = 200;
_splitHeight2 = 0;
_splitStart = 0;
+ _lastRetraceLength = 0;
_curSparse = 0;
_lastSparse = 0xFFFFFFFF;
@@ -161,26 +162,27 @@ SurfaceDesc *Video::initSurfDesc(int16 vidMode, int16 width, int16 height,
}
void Video::retrace(bool mouse) {
+ uint32 time = _vm->_util->getTimeKey();
+
if (mouse)
CursorMan.showMouse((_vm->_draw->_showCursor & 2) != 0);
if (_vm->_global->_primarySurfDesc) {
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() +
_scrollOffsetY * _surfWidth + _scrollOffsetX, _surfWidth,
- 0, 0, 320, _splitHeight1);
+ 0, 0, _vm->_width, _splitHeight1);
if (_splitHeight2 > 0)
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() +
_splitStart * _surfWidth, _surfWidth, 0,
- 200 - _splitHeight2, 320, _splitHeight2);
+ _vm->_height - _splitHeight2, _vm->_width, _splitHeight2);
g_system->updateScreen();
}
+
+ _lastRetraceLength = _vm->_util->getTimeKey() - time;
}
void Video::waitRetrace(bool mouse) {
- uint32 time;
-
- time = _vm->_util->getTimeKey();
retrace(mouse);
- _vm->_util->delay(MAX(1, 10 - (int)(_vm->_util->getTimeKey() - time)));
+ _vm->_util->delay(MAX(1, 10 - (int) _lastRetraceLength));
}
void Video::sparseRetrace(int max) {
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 51d02bd219..dc23bda81e 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -104,6 +104,7 @@ public:
int16 _splitHeight1;
int16 _splitHeight2;
int16 _splitStart;
+ uint32 _lastRetraceLength;
void freeDriver();
void initPrimary(int16 mode);
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
new file mode 100644
index 0000000000..e72354a169
--- /dev/null
+++ b/engines/gob/videoplayer.cpp
@@ -0,0 +1,333 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "gob/videoplayer.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/video.h"
+#include "gob/draw.h"
+#include "gob/game.h"
+#include "gob/palanim.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+const char *VideoPlayer::_extensions[] = { "IMD", "VMD" };
+
+VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
+ _curFile[0] = 0;
+ _stream = 0;
+ _video = 0;
+ _backSurf = false;
+}
+
+VideoPlayer::~VideoPlayer() {
+ closeVideo();
+}
+
+bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) {
+ char fileName[256];
+
+ strncpy0(fileName, video, 250);
+
+ char *extStart = strchr(fileName, '.');
+ if (extStart) {
+ // The requested file already has an extension. Verifying.
+
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if (!scumm_stricmp(extStart + 1, _extensions[i])) {
+ if ((which != kVideoTypeTry) && (which == ((Type) i))) {
+ warning("Attempted to open video \"%s\", "
+ "but requested a different type", fileName);
+ return false;
+ }
+ which = (Type) i;
+ break;
+ }
+ }
+ if (i >= ARRAYSIZE(_extensions))
+ extStart = 0;
+
+ }
+
+ if (!extStart) {
+ // No or unrecognized extension. Probing.
+
+ int len = strlen(fileName);
+
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if ((which == kVideoTypeTry) || (which == ((Type) i))) {
+ int16 handle;
+
+ fileName[len] = '.';
+ fileName[len + 1] = 0;
+ strcat(fileName, _extensions[i]);
+
+ handle = _vm->_dataIO->openData(fileName);
+ if (handle >= 0) {
+ _vm->_dataIO->closeData(handle);
+ which = (Type) i;
+ break;
+ }
+ }
+ }
+ if ((i >= ARRAYSIZE(_extensions)) || (which == kVideoTypeTry)) {
+ fileName[len] = 0;
+ warning("Couldn't open video \"%s\"", fileName);
+ return false;
+ }
+
+ }
+
+ if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) {
+ closeVideo();
+
+ int16 handle = _vm->_dataIO->openData(fileName);
+
+ if (handle < 0) {
+ warning("Couldn't open video \"%s\": No such file", fileName);
+ return false;
+ }
+
+ _stream = _vm->_dataIO->openAsStream(handle, true);
+
+ if (which == kVideoTypeIMD) {
+ _video = new Imd();
+ } else if (which == kVideoTypeVMD) {
+ _video = new Vmd();
+ } else {
+ warning("Couldn't open video \"%s\": Invalid video Type", fileName);
+ closeVideo();
+ return false;
+ }
+
+ if (!_video->load(*_stream)) {
+ warning("While loading video \"%s\"", fileName);
+ closeVideo();
+ return false;
+ }
+
+ _video->setXY(x, y);
+
+ if (!(flags & kFlagNoVideo)) {
+ _backSurf = ((flags & kFlagFrontSurface) == 0);
+ SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
+ _video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight());
+ } else
+ _video->setVideoMemory();
+
+ _video->enableSound(*_vm->_mixer);
+ }
+
+ if (!_video)
+ return false;
+
+ WRITE_VAR(7, _video->getFramesCount());
+
+ return true;
+}
+
+void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) {
+
+ if (!_video)
+ return;
+
+ breakKey = 27;
+ if (startFrame < 0)
+ startFrame = _video->getCurrentFrame();
+ if (lastFrame < 0)
+ lastFrame = _video->getFramesCount() - 1;
+ if (palFrame < 0)
+ palFrame = startFrame;
+ if (endFrame < 0)
+ endFrame = lastFrame;
+ palCmd &= 0x3F;
+
+ if (_video->getCurrentFrame() != startFrame)
+ _video->seekFrame(startFrame);
+
+ _vm->_draw->_showCursor = 0;
+ _vm->_util->setFrameRate(12);
+
+ if (fade)
+ _vm->_palAnim->fade(0, -2, 0);
+
+ while (startFrame <= lastFrame) {
+ if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame))
+ break;
+
+ if (fade) {
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ fade = false;
+ }
+
+ _video->waitEndFrame();
+ startFrame++;
+ }
+
+ if (reverseTo >= 0) {
+ int16 toFrame = _video->getFramesCount() - reverseTo;
+ for (int i = _video->getCurrentFrame(); i >= toFrame; i--) {
+ _video->seekFrame(i, SEEK_SET, true);
+ if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) {
+ _vm->_palAnim->fade(0, -2, 0);
+ memset((char *) _vm->_draw->_vgaPalette, 0, 768);
+ }
+ _video->waitEndFrame();
+ }
+ }
+}
+
+int16 VideoPlayer::getFramesCount() const {
+ if (!_video)
+ return 0;
+
+ return _video->getFramesCount();
+}
+
+int16 VideoPlayer::getCurrentFrame() const {
+ if (!_video)
+ return 0;
+
+ return _video->getCurrentFrame();
+}
+
+bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame) {
+
+ bool modifiedPal = false;
+
+ if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) {
+ modifiedPal = true;
+ _vm->_draw->_applyPal = true;
+
+ if (palCmd >= 4)
+ copyPalette(palStart, palEnd);
+ }
+
+ if (modifiedPal && (palCmd == 8) && !_backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+
+ CoktelVideo::State state = _video->nextFrame();
+ WRITE_VAR(11, frame);
+
+
+ if (modifiedPal && (palCmd == 16)) {
+ if (_backSurf)
+ _vm->_draw->forceBlit();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ _vm->_draw->_noInvalidated = true;
+ }
+
+ if (state.flags & CoktelVideo::kStatePalette) {
+ copyPalette(palStart, palEnd);
+
+ if (!_backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ else
+ _vm->_draw->_applyPal = true;
+ }
+
+ if (modifiedPal && (palCmd == 8) && _backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+
+ if (_backSurf) {
+ _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom);
+ _vm->_draw->blitInvalidated();
+ }
+ _vm->_video->retrace();
+
+
+ if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+
+
+ _vm->_util->processInput();
+
+ if (_vm->_quitRequested) {
+ _video->disableSound();
+ return true;
+ }
+
+ if (breakKey != 0) {
+ _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
+ &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
+
+ _vm->_inter->storeKey(_vm->_util->checkKey());
+ if (VAR(0) == (unsigned) breakKey) {
+ _video->disableSound();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
+ if ((palStart == -1) || (palEnd == -1))
+ memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
+ _video->getPalette(), 768);
+ else
+ memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
+ palStart * 3, _video->getPalette() + palStart * 3,
+ (palEnd - palStart + 1) * 3);
+}
+
+void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight) {
+
+ if (openVideo(video)) {
+ WRITE_VAR_OFFSET(varX, _video->getX());
+ WRITE_VAR_OFFSET(varY, _video->getY());
+ WRITE_VAR_OFFSET(varFrames, _video->getFramesCount());
+ WRITE_VAR_OFFSET(varWidth, _video->getWidth());
+ WRITE_VAR_OFFSET(varHeight, _video->getHeight());
+ closeVideo();
+ } else {
+ WRITE_VAR_OFFSET(varX, -1);
+ WRITE_VAR_OFFSET(varY, -1);
+ WRITE_VAR_OFFSET(varFrames, -1);
+ WRITE_VAR_OFFSET(varWidth, -1);
+ WRITE_VAR_OFFSET(varHeight, -1);
+ }
+}
+
+void VideoPlayer::closeVideo() {
+ delete _video;
+ delete _stream;
+
+ _video = 0;
+ _stream = 0;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
new file mode 100644
index 0000000000..c4c608dc99
--- /dev/null
+++ b/engines/gob/videoplayer.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_VIDEOPLAYER_H
+#define GOB_VIDEOPLAYER_H
+
+#include "gob/coktelvideo.h"
+#include "gob/dataio.h"
+
+namespace Gob {
+
+class GobEngine;
+
+class VideoPlayer {
+public:
+ enum Flags {
+ kFlagNone = 0,
+ kFlagFrontSurface = 0x80,
+ kFlagNoVideo = 0x100
+ };
+
+ enum Type {
+ kVideoTypeTry = -1,
+ kVideoTypeIMD = 0,
+ kVideoTypeVMD = 1
+ };
+
+ VideoPlayer(GobEngine *vm);
+ ~VideoPlayer();
+
+ bool openVideo(const char *video, int16 x = -1, int16 y = -1,
+ int16 flags = kFlagFrontSurface, Type which = kVideoTypeTry);
+
+ void play(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27,
+ uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255,
+ int16 palFrame = -1, int16 endFrame = -1, bool fade = false,
+ int16 reverseTo = -1);
+
+ int16 getFramesCount() const;
+ int16 getCurrentFrame() const;
+ void writeVideoInfo(const char *video, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight);
+
+ void closeVideo();
+
+private:
+ static const char *_extensions[];
+
+ GobEngine *_vm;
+
+ char _curFile[256];
+ DataStream *_stream;
+ CoktelVideo *_video;
+ bool _backSurf;
+
+ void copyPalette(int16 palStart = -1, int16 palEnd = -1);
+ bool doPlay(int16 frame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_VIDEOPLAYER_H