aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob/game.cpp')
-rw-r--r--engines/gob/game.cpp848
1 files changed, 847 insertions, 1 deletions
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index adfaec9c4c..5bf3c289e4 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -39,6 +39,7 @@
#include "gob/goblin.h"
#include "gob/cdrom.h"
#include "gob/music.h"
+#include "gob/palanim.h"
namespace Gob {
@@ -107,13 +108,28 @@ Game::Game(GobEngine *vm) : _vm(vm) {
_curTotFileArray[i][0] = 0;
}
- warning("GOB2 Stub! _byte_2FC9B, _word_2FC9C, _word_2FC9E, _word_2E51F, _off_2E51B, _off_2E517");
+ _imdFile = 0;
+ _curImdFile[0] = 0;
+ _imdX = 0;
+ _imdY = 0;
+ _imdFrameDataSize = 0;
+ _imdVidBufferSize = 0;
+ _imdFrameData = 0;
+ _imdVidBuffer = 0;
+
+ warning("GOB2 Stub! _byte_2FC82, _byte_2FC83, _word_2FC80");
+ _byte_2FC82 = 0;
+ _byte_2FC83 = 0;
+ _word_2FC80 = 0;
+
+ warning("GOB2 Stub! _byte_2FC9B, _word_2FC9C, _word_2FC9E, _word_2E51F, _off_2E51B, _off_2E517, _dword_2F2B6");
_byte_2FC9B = 0;
_word_2FC9C = 0;
_word_2FC9E = 0;
_word_2E51F = 0;
_off_2E51B = 0;
_off_2E517 = 0;
+ _dword_2F2B6 = 0;
}
char *Game::loadExtData(int16 itemId, int16 *pResWidth, int16 *pResHeight) {
@@ -1650,6 +1666,7 @@ void Game::collAreaSub(int16 index, int8 enter) {
}
}
+// "DEVinitscreen"
void Game::sub_ADD2(void) {
_word_2FC9C = 0;
_word_2FC9E = 0;
@@ -1687,6 +1704,7 @@ void Game::sub_ADD2(void) {
}*/
}
+// "DEVclosescreen"
void Game::sub_BB28(void) {
_vm->_draw->freeSprite(23);
_vm->_video->freeSurfDesc(_vm->_draw->_cursorBack);
@@ -1748,4 +1766,832 @@ Snd::SoundDesc *Game::loadSND(const char *path, int8 arg_4) {
return soundDesc;
}
+int8 Game::openImd(const char *path, int16 x, int16 y, int16 repeat, int16 flags) {
+ int i;
+ int j;
+ const char *src;
+ byte *vidMem;
+ Video::SurfaceDesc *surfDesc;
+
+ if (path[0] != 0) {
+ if (_imdFile == 0)
+ _curImdFile[0] = 0;
+
+ src = strrchr(path, '\\');
+ src = src == 0 ? path : src+1;
+
+ if (strcmp(_curImdFile, src) != 0) {
+ closeImd();
+ _imdFile = loadImdFile(path, 0, 2);
+ if (_imdFile == 0)
+ return 0;
+
+ _imdX = _imdFile->x;
+ _imdY = _imdFile->y;
+ strcpy(_curImdFile, src);
+ _imdFrameData = new byte[_imdFrameDataSize + 1000];
+ _imdVidBuffer = new byte[_imdVidBufferSize + 1000];
+ memset(_imdFrameData, 0, _imdFrameDataSize + 1000);
+ memset(_imdVidBuffer, 0, _imdVidBufferSize + 1000);
+
+ if (_vm->_video->_extraMode) {
+ _byte_2FC83 = (flags & 0x80) ? 1 : 0;
+ if (!(_imdFile->field_E & 0x100) || (_imdFile->field_E & 0x2000)) {
+ setImdXY(_imdFile, 0, 0);
+ _imdFile->surfDesc =
+ _vm->_video->initSurfDesc(0x13, _imdFile->width, _imdFile->height, 0);
+ } else {
+ if (_byte_2FC82 == 0)
+ _imdFile->surfDesc = _vm->_draw->_spritesArray[21];
+ else
+ _imdFile->surfDesc = _vm->_draw->_spritesArray[20];
+ if ((x != -1) || (y != -1)) {
+ _imdX = x != -1 ? x : _imdX;
+ _imdY = y != -1 ? y : _imdY;
+ setImdXY(_imdFile, _imdX, _imdY);
+ }
+ }
+ if (flags & 0x40) {
+ _imdX = x != -1 ? x : _imdX;
+ _imdY = y != -1 ? y : _imdY;
+ if (_vm->_video->_extraMode && ((_imdFile->surfDesc->vidMode & 0x7F) == 0x13)) {
+ surfDesc = _vm->_video->initSurfDesc(0x13, _imdFile->width, _imdFile->height, 0);
+ _vm->_video->drawSprite(_vm->_draw->_spritesArray[21], surfDesc, _imdX, _imdY,
+ _imdX + _imdFile->width - 1, _imdY + _imdFile->height - 1, 0, 0, 0);
+ vidMem = _imdFile->surfDesc->vidPtr;
+ for (i = 0; i < _imdFile->height; i++)
+ for (j = 0; j < _imdFile->width; j++, vidMem++) {
+ *(vidMem) = *(surfDesc->vidPtr
+ + (j / 4)
+ + (surfDesc->width / 4 * i)
+ + (surfDesc->reserved2 * (j & 3)));
+ }
+ _vm->_video->freeSurfDesc(surfDesc);
+ }
+ }
+ } else {
+ if ((x != -1) || (y != -1)) {
+ _imdX = x != -1 ? x : _imdX;
+ _imdY = y != -1 ? y : _imdY;
+ setImdXY(_imdFile, _imdX, _imdY);
+ }
+ _byte_2FC83 = (flags & 0x80) ? 1 : 0;
+ if (_byte_2FC83 == 0)
+ _imdFile->surfDesc = _vm->_draw->_spritesArray[21];
+ else
+ _imdFile->surfDesc = _vm->_draw->_spritesArray[20];
+ }
+ }
+ }
+
+ if (_imdFile == 0)
+ return 0;
+
+ if (repeat == -1) {
+ closeImd();
+ return 0;
+ }
+
+ _imdX = x != -1 ? x : _imdX;
+ _imdY = y != -1 ? y : _imdY;
+
+ WRITE_VAR(7, _imdFile->framesCount);
+
+ return 1;
+}
+
+void Game::closeImd(void) {
+ if (_imdFile == 0)
+ return;
+
+ if ((_imdFile->surfDesc != _vm->_draw->_spritesArray[20]) &&
+ (_imdFile->surfDesc != _vm->_draw->_spritesArray[21]))
+ _vm->_video->freeSurfDesc(_imdFile->surfDesc);
+
+ finishImd(_imdFile);
+
+ delete[] _imdFrameData;
+ delete[] _imdVidBuffer;
+ _imdFrameData = 0;
+ _imdVidBuffer = 0;
+
+ _imdFile = 0;
+}
+
+void Game::finishImd(Game::Imd *imdPtr) {
+ if (imdPtr == 0)
+ return;
+
+/*
+ if (dword_31345 != 0) {
+ _vm->_sound->stopSound(0);
+ dword_31345 = 0;
+ delete off_31461;
+ byte_31344 = 0;
+ }
+*/
+
+ _vm->_dataio->closeData(imdPtr->fileHandle);
+
+ if (imdPtr->frameCoords != 0)
+ delete[] imdPtr->frameCoords;
+ if (imdPtr->palette != 0)
+ delete[] imdPtr->palette;
+ if (imdPtr->framesPos != 0)
+ delete[] imdPtr->framesPos;
+
+ delete imdPtr;
+ imdPtr = 0;
+}
+
+// flagsBit: 0 = read and set palette
+// 1 = read palette
+Game::Imd *Game::loadImdFile(const char *path, Video::SurfaceDesc *surfDesc, int8 flags) {
+ int i;
+ Imd *imdPtr;
+ int16 handle;
+ int16 setAllPalBak;
+ char buf[18];
+ Video::Color *palBak;
+
+ int32 byte_31449 = 0;
+ int32 byte_3144D = 0;
+
+ buf[0] = 0;
+ strcpy(buf, path);
+ strcat(buf, ".IMD");
+
+ handle = _vm->_dataio->openData(buf);
+
+ if (handle < 0) {
+ warning("Can't open IMD \"%s\"", buf);
+ return 0;
+ }
+
+ imdPtr = new Imd;
+ memset(imdPtr, 0, sizeof(Imd));
+
+ imdPtr->palette = 0;
+
+ _vm->_dataio->readData(handle, buf, 18);
+
+ // "fileHandle" holds the major version while loading
+ imdPtr->fileHandle = READ_LE_UINT16(buf);
+ imdPtr->verMin = READ_LE_UINT16(buf + 2);
+ imdPtr->framesCount = READ_LE_UINT16(buf + 4);
+ imdPtr->x = READ_LE_UINT16(buf + 6);
+ imdPtr->y = READ_LE_UINT16(buf + 8);
+ imdPtr->width = READ_LE_UINT16(buf + 10);
+ imdPtr->height = READ_LE_UINT16(buf + 12);
+ imdPtr->field_E = READ_LE_UINT16(buf + 14);
+ imdPtr->curFrame = READ_LE_UINT16(buf + 16);
+
+ if (imdPtr->fileHandle != 0)
+ imdPtr->verMin = 0;
+
+ if ((imdPtr->verMin & 0xFF) < 2) {
+ warning("IMD version incorrect (%d,%d)", imdPtr->fileHandle, imdPtr->verMin);
+ _vm->_dataio->closeData(handle);
+ delete imdPtr;
+ return 0;
+ }
+
+ imdPtr->surfDesc = surfDesc;
+ imdPtr->framesPos = 0;
+ imdPtr->firstFramePos = imdPtr->curFrame;
+
+ if (flags & 3) {
+ imdPtr->palette = new Video::Color[256];
+ _vm->_dataio->readData(handle, (char *) imdPtr->palette, 768);
+ } else {
+ _vm->_dataio->seekData(handle, 768, 1);
+ imdPtr->palette = 0;
+ }
+ if ((flags & 3) == 1) {
+ palBak = _vm->_global->_pPaletteDesc->vgaPal;
+ setAllPalBak = _vm->_global->_setAllPalette;
+ _vm->_global->_pPaletteDesc->vgaPal = imdPtr->palette;
+ _vm->_global->_setAllPalette = 1;
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ _vm->_global->_setAllPalette = setAllPalBak;
+ _vm->_global->_pPaletteDesc->vgaPal = palBak;
+ }
+
+ if ((imdPtr->verMin & 0xFF) >= 3) {
+ _vm->_dataio->readData(handle, buf, 2);
+ imdPtr->stdX = READ_LE_UINT16(buf);
+ if (imdPtr->stdX > 1) {
+ warning("IMD ListI incorrect (%d)", imdPtr->stdX);
+ _vm->_dataio->closeData(handle);
+ delete imdPtr;
+ return 0;
+ }
+ if(imdPtr->stdX != 0) {
+ _vm->_dataio->readData(handle, buf, 8);
+ imdPtr->stdX = READ_LE_UINT16(buf);
+ imdPtr->stdY = READ_LE_UINT16(buf + 2);
+ imdPtr->stdWidth = READ_LE_UINT16(buf + 4);
+ imdPtr->stdHeight = READ_LE_UINT16(buf + 6);
+ } else
+ imdPtr->stdX = -1;
+ } else
+ imdPtr->stdX = -1;
+
+ if ((imdPtr->verMin & 0xFF) >= 4) {
+ _vm->_dataio->readData(handle, buf, 4);
+ byte_31449 = READ_LE_UINT32(buf);
+ imdPtr->framesPos = byte_31449 == 0 ? 0 : new int32[imdPtr->framesCount];
+ } else
+ imdPtr->framesPos = 0;
+
+ if (imdPtr->verMin & 0x8000) {
+ _vm->_dataio->readData(handle, buf, 4);
+ byte_3144D = READ_LE_UINT32(buf);
+ }
+
+ if (imdPtr->verMin & 0x4000) {
+ // loc_29C4F
+ error("GOB2 Stub! loadImdFile, imdPtr->verMin & 0x4000");
+ // Sound stuff, I presume...
+ }
+
+ if (imdPtr->verMin & 0x2000) {
+ _vm->_dataio->readData(handle, buf, 4);
+ imdPtr->frameDataSize = READ_LE_UINT16(buf);
+ imdPtr->vidBufferSize = READ_LE_UINT16(buf + 2);
+ } else {
+ imdPtr->frameDataSize = imdPtr->width * imdPtr->height + 1000;
+ imdPtr->vidBufferSize = imdPtr->width * imdPtr->height + 1000;
+ }
+
+ if (imdPtr->framesPos != 0) {
+ _vm->_dataio->seekData(handle, byte_31449, 0);
+ for (i = 0; i < imdPtr->framesCount; i++) {
+ _vm->_dataio->readData(handle, buf, 4);
+ imdPtr->framesPos[i] = READ_LE_UINT32(buf);
+ }
+ }
+
+ if (imdPtr->verMin & 0x8000) {
+ _vm->_dataio->seekData(handle, byte_3144D, 0);
+ imdPtr->frameCoords = new ImdCoord[imdPtr->framesCount];
+ for (i = 0; i < imdPtr->framesCount; i++) {
+ _vm->_dataio->readData(handle, buf, 8);
+ imdPtr->frameCoords[i].left = READ_LE_UINT16(buf);
+ imdPtr->frameCoords[i].top = READ_LE_UINT16(buf + 2);
+ imdPtr->frameCoords[i].right = READ_LE_UINT16(buf + 4);
+ imdPtr->frameCoords[i].bottom = READ_LE_UINT16(buf + 6);
+ }
+ } else
+ imdPtr->frameCoords = 0;
+
+ _vm->_dataio->seekData(handle, imdPtr->firstFramePos, 0);
+ imdPtr->curFrame = 0;
+ imdPtr->fileHandle = handle;
+ imdPtr->filePos = imdPtr->firstFramePos;
+ _imdFrameDataSize = imdPtr->frameDataSize;
+ _imdVidBufferSize = imdPtr->vidBufferSize;
+ if (flags & 0x80) {
+ imdPtr->verMin |= 0x1000;
+ warning("GOB2 Stub! loadImdFile(), flags & 0x80");
+ }
+
+ return imdPtr;
+}
+
+void Game::setImdXY(Game::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 != 0) {
+ for (i = 0; i < imdPtr->framesCount; i++) {
+ 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 Game::playImd(int16 frame, int16 arg_2, int16 arg_4, int16 arg_6, int16 arg_8, int16 lastFrame) {
+ int16 var_1;
+ int16 var_4 = 0;
+ byte *vidMemBak;
+ Video::SurfaceDesc *surfDescBak;
+ Video::SurfaceDesc frontSurfBak;
+
+ int8 byte_31344 = 0;
+
+ if ((frame < 0) || (frame > lastFrame))
+ return;
+
+ if ((frame == arg_8) || ((frame == lastFrame) && (arg_2 == 8))) { // loc_1C3F0
+ var_1 = 1;
+ _vm->_draw->_applyPal = 0;
+ if (arg_2 >= 4) {
+ if (arg_4 != -1)
+ memcpy( ((char *) (_vm->_global->_pPaletteDesc->vgaPal)) + arg_4 * 3,
+ ((char *) (_imdFile->palette)) + arg_4 * 3, (arg_6 - arg_4 + 1) * 3);
+ else
+ memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, (char *) _imdFile->palette, 768);
+ }
+ } else
+ var_1 = 0;
+
+ if ((var_1 == 1) && (arg_2 == 8) && (_byte_2FC83 != 0))
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+ if (_vm->_video->_extraMode && (_imdFile->surfDesc->vidMode == 0x13)) {
+ if ((_byte_2FC82 != 0) && (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr)) {
+ vidMemBak = _vm->_draw->_spritesArray[20]->vidPtr;
+ _vm->_draw->_spritesArray[20]->vidPtr = _vm->_draw->_spritesArray[21]->vidPtr;
+ var_4 = viewImd(_imdFile, frame);
+ _vm->_draw->_spritesArray[20]->vidPtr = vidMemBak;
+ } else
+ var_4 = viewImd(_imdFile, frame);
+ if (_byte_2FC82 == 0) {
+ if ((_imdFile->frameCoords == 0) || (_imdFile->frameCoords[frame].left == -1))
+ _vm->_draw->invalidateRect(_imdX, _imdY,
+ _imdX + _imdFile->width - 1, _imdY + _imdFile->height - 1);
+ else
+ _vm->_draw->invalidateRect(_imdFile->frameCoords[frame].left,
+ _imdFile->frameCoords[frame].top, _imdFile->frameCoords[frame].right,
+ _imdFile->frameCoords[frame].bottom);
+ }
+ } else {
+ if ((_imdFile->field_E & 0x100) && (_vm->_video->_extraMode) &&
+ (_byte_2FC82 != 0) && (sub_2C825(_imdFile) & 0x8000) && (_byte_2FC83 == 0)) {
+ surfDescBak = _imdFile->surfDesc;
+ if (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr)
+ _imdFile->surfDesc = _vm->_draw->_spritesArray[21];
+ else
+ _imdFile->surfDesc = _vm->_draw->_spritesArray[20];
+ setImdXY(_imdFile, _imdX, _imdY);
+ var_4 = viewImd(_imdFile, frame);
+ _imdFile->surfDesc = surfDescBak;
+ setImdXY(_imdFile, 0, 0);
+ } else {
+ var_4 = viewImd(_imdFile, frame);
+ if (!(var_4 & 0x800)) {
+ if (_byte_2FC83 == 0) {
+ if (_vm->_video->_extraMode) {
+ if (_byte_2FC82 == 0) {
+ memcpy((char *) &frontSurfBak, (char *) &_vm->_draw->_frontSurface,
+ sizeof(Video::SurfaceDesc));
+ memcpy((char *) &_vm->_draw->_frontSurface, (char *) &_vm->_draw->_spritesArray[21],
+ sizeof(Video::SurfaceDesc));
+ imdDrawFrame(_imdFile, frame, _imdX, _imdY);
+ memcpy((char *) &_vm->_draw->_frontSurface, (char *) &frontSurfBak,
+ sizeof(Video::SurfaceDesc));
+ if ((_imdFile->frameCoords == 0) || (_imdFile->frameCoords[frame].left == -1))
+ _vm->_draw->invalidateRect(_imdX, _imdY, _imdX + _imdFile->width - 1,
+ _imdY + _imdFile->height - 1);
+ else
+ _vm->_draw->invalidateRect(_imdFile->frameCoords[frame].left,
+ _imdFile->frameCoords[frame].top, _imdFile->frameCoords[frame].right,
+ _imdFile->frameCoords[frame].bottom);
+ } else {
+ if (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr) { // loc_1C68D
+ memcpy((char *) &frontSurfBak, (char *) &_vm->_draw->_frontSurface,
+ sizeof(Video::SurfaceDesc));
+ memcpy((char *) &_vm->_draw->_frontSurface, (char *) &_vm->_draw->_spritesArray[21],
+ sizeof(Video::SurfaceDesc));
+ imdDrawFrame(_imdFile, frame, _imdX, _imdY);
+ memcpy((char *) &_vm->_draw->_frontSurface, (char *) &frontSurfBak,
+ sizeof(Video::SurfaceDesc));
+ } else
+ imdDrawFrame(_imdFile, frame, _imdX, _imdY);
+ }
+ } else {
+ if ((_imdFile->frameCoords == 0) || (_imdFile->frameCoords[frame].left == -1))
+ _vm->_draw->invalidateRect(_imdX, _imdY, _imdX + _imdFile->width - 1,
+ _imdY + _imdFile->height - 1);
+ else
+ _vm->_draw->invalidateRect(_imdFile->frameCoords[frame].left,
+ _imdFile->frameCoords[frame].top, _imdFile->frameCoords[frame].right,
+ _imdFile->frameCoords[frame].bottom);
+ }
+ } else
+ if (_vm->_video->_extraMode)
+ imdDrawFrame(_imdFile, frame, _imdX, _imdY);
+ }
+ }
+ }
+
+ if ((var_1 != 0) && (arg_2 == 16)) {
+ if ((_vm->_draw->_spritesArray[20] != _vm->_draw->_spritesArray[21]) && (_byte_2FC83 == 0))
+ _vm->_video->drawSprite(_vm->_draw->_spritesArray[21],
+ _vm->_draw->_spritesArray[20], 0, 0,
+ _vm->_draw->_spritesArray[21]->width - 1,
+ _vm->_draw->_spritesArray[21]->height - 1, 0, 0, 0);
+ _vm->_palanim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ _vm->_draw->_noInvalidated = 1;
+ }
+ if ((var_1 != 0) && (arg_2 == 8) && (_byte_2FC83 == 0))
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+ if (!(var_4 & 0x800)) {
+ if (_vm->_draw->_cursorIndex == -1) {
+ if (_byte_2FC82 != 0) {
+ if (_word_2FC80 == _vm->_draw->_spritesArray[20]->vidPtr)
+ _word_2FC80 = _vm->_draw->_spritesArray[21]->vidPtr;
+ else
+ _word_2FC80 = _vm->_draw->_spritesArray[20]->vidPtr;
+ warning("GOB2 Stub! sub_1BC3A(_word_2FC80);");
+ } else
+ _vm->_draw->blitInvalidated();
+ } else
+ _vm->_draw->animateCursor(-1);
+ }
+
+ if ((var_1 != 0) && ((arg_2 == 2) || (arg_2 == 4)))
+ _vm->_palanim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+
+ // To allow quitting, etc. during IMDs
+ _vm->_util->processInput();
+
+ if (byte_31344 != 2) {
+ if (var_4 & 0x800) {
+ if (_dword_2F2B6 == 0)
+ _vm->_util->delay(30);
+ else {
+ _dword_2F2B6 -= 30;
+ if (_dword_2F2B6 < 0)
+ _dword_2F2B6 = 0;
+ }
+ } else
+ _vm->_util->waitEndFrame();
+ }
+ _vm->_inter->animPalette();
+}
+
+int16 Game::viewImd(Game::Imd *imdPtr, int16 frame) {
+ int16 x;
+ int16 y;
+ int16 width;
+ int16 height;
+ int16 retVal;
+ uint32 tmp;
+ char buf[4];
+
+ int8 var_4;
+ int32 var_12 = 0;
+
+ // .---
+ int16 word_31451 = 0;
+ int8 byte_31344 = 0;
+ int8 byte_2DA60 = 0;
+ int16 word_2DA61 = -1;
+ // '---
+
+ word_31451 = 0;
+
+ if (imdPtr == 0)
+ return 0x8000;
+
+ retVal = 0;
+ var_4 = 0;
+
+ if (frame != imdPtr->curFrame) {
+ retVal |= 0x2000;
+ if (frame == 0)
+ imdPtr->filePos = imdPtr->firstFramePos;
+ else if (frame == 1) {
+ imdPtr->filePos = imdPtr->firstFramePos;
+ _vm->_dataio->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
+ tmp = READ_LE_UINT16(buf);
+ imdPtr->filePos += tmp + 4;
+ } else if (imdPtr->framesPos != 0)
+ imdPtr->filePos = imdPtr->framesPos[frame];
+ else
+ error("Image %d innaccessible in IMD", frame);
+ imdPtr->curFrame = frame;
+ _vm->_dataio->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
+ }
+
+ x = imdPtr->x;
+ y = imdPtr->y;
+ width = imdPtr->width;
+ height = imdPtr->height;
+
+ do {
+ if (frame != 0) {
+ if (imdPtr->stdX != -1) {
+ imdPtr->x = imdPtr->stdX;
+ imdPtr->y = imdPtr->stdY;
+ imdPtr->width = imdPtr->stdWidth;
+ imdPtr->height = imdPtr->stdHeight;
+ retVal |= 0x1000;
+ }
+ if ((imdPtr->frameCoords != 0) && (imdPtr->frameCoords[frame].left != -1)) {
+ var_4 |= 0x400;
+ imdPtr->x = imdPtr->frameCoords[frame].left;
+ imdPtr->y = imdPtr->frameCoords[frame].top;
+ imdPtr->width = imdPtr->frameCoords[frame].right - imdPtr->x + 1;
+ imdPtr->height = imdPtr->frameCoords[frame].bottom - imdPtr->y + 1;
+ }
+ }
+
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
+ tmp = READ_LE_UINT16(buf);
+
+ imdPtr->filePos += 2;
+
+ if ((tmp & 0xFFF8) == 0xFFF0) {
+ if (tmp == 0xFFF0) {
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
+ tmp = READ_LE_UINT16(buf);
+ if (var_4 == 0)
+ word_31451 = tmp;
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
+ tmp = READ_LE_UINT16(buf);
+ imdPtr->filePos += 4;
+ } else if (tmp == 0xFFF1) {
+ retVal = 0x8000;
+ continue;
+ } else if (tmp == 0xFFF2) {
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
+ tmp = READ_LE_UINT16(buf);
+ imdPtr->filePos += 2;
+ _vm->_dataio->seekData(imdPtr->fileHandle, tmp, 1);
+ imdPtr->filePos += tmp;
+ retVal = 0x8000;
+ continue;
+ } else if (tmp == 0xFFF3) {
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 4);
+ tmp = READ_LE_UINT32(buf);
+ imdPtr->filePos += 4;
+ _vm->_dataio->seekData(imdPtr->fileHandle, tmp, 1);
+ imdPtr->filePos += tmp;
+ retVal = 0x8000;
+ continue;
+ }
+ }
+ if (byte_31344 != 0) {
+ if ((var_4 == 0) && (_vm->_global->_soundFlags & 0x14) && (byte_31344 == 2)) { // loc_2A503
+ var_12 = _vm->_util->getTimeKey();
+ warning("GOB2 Stub! viewImd, IMD sound stuff");
+ }
+ }
+ var_4 = 0;
+ if (tmp == 0xFFFD) {
+ _vm->_dataio->readData(imdPtr->fileHandle, buf, 2);
+ frame = READ_LE_UINT16(buf);
+ if ((imdPtr->framesPos != 0) && (byte_2DA60 == 0)) {
+ word_2DA61 = frame;
+ imdPtr->filePos = imdPtr->framesPos[frame];
+ _vm->_dataio->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
+ var_4 = 1;
+ retVal |= 0x200;
+ imdPtr->curFrame = frame;
+ } else
+ imdPtr->filePos += 2;
+ continue;
+ }
+ if (tmp != 0) {
+ imdPtr->filePos += tmp + 2;
+ if (byte_2DA60 != 0) {
+ _vm->_dataio->seekData(imdPtr->fileHandle, tmp + 2, 1);
+ } else {
+ _vm->_dataio->readData(imdPtr->fileHandle, (char *) _imdFrameData, tmp + 2);
+ retVal |= *_imdFrameData;
+ if (imdPtr->surfDesc == 0)
+ continue;
+ if (!(_vm->_video->_extraMode && (imdPtr->surfDesc->vidMode == 0x13))) // MODIFIED... NOT!
+ imdRenderFrame(imdPtr);
+ else
+ warning("GOB2 Stub! viedImd, sub_2C69A(imdPtr);");
+ }
+ } else
+ retVal |= 0x800;
+ } while(var_4 != 0);
+
+ if (byte_2DA60 != 0) {
+ byte_2DA60 = 0;
+ retVal |= 0x100;
+ }
+
+ imdPtr->x = x;
+ imdPtr->y = y;
+ imdPtr->width = width;
+ imdPtr->height = height;
+ imdPtr->curFrame++;
+
+ return retVal;
+}
+
+void Game::imdDrawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y) {
+ // In the original asm, "sub_2C348" is called instead of Video::drawSprite();
+ // it basically just blits.
+
+ if (frame == 0)
+ _vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface, 0, 0,
+ imdPtr->width - 1, imdPtr->height - 1, x, y, 1);
+ else if ((imdPtr->frameCoords != 0) && (imdPtr->frameCoords[frame].left != -1))
+ _vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface,
+ imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top,
+ imdPtr->frameCoords[frame].right, imdPtr->frameCoords[frame].bottom,
+ imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top, 1);
+ else if (imdPtr->stdX != -1)
+ _vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface,
+ imdPtr->stdX, imdPtr->stdY, imdPtr->stdX + imdPtr->stdWidth - 1,
+ imdPtr->stdY + imdPtr->stdHeight - 1, x + imdPtr->stdX,
+ y + imdPtr->stdY, 1);
+ else
+ _vm->_video->drawSprite(imdPtr->surfDesc, _vm->_draw->_frontSurface, 0, 0,
+ imdPtr->width - 1, imdPtr->height - 1, x, y, 1);
+}
+
+void Game::imdRenderFrame(Imd *imdPtr) {
+ int i;
+ int16 imdX;
+ int16 imdY;
+ int16 imdW;
+ int16 imdH;
+ int16 sW;
+ uint16 pixCount, pixWritten;
+ uint8 type;
+ byte *imdVidMem;
+ byte *imdVidMemBak;
+ byte *dataPtr = 0;
+ byte *srcPtr = 0;
+ byte *srcPtrBak = 0;
+
+ dataPtr = (byte *) _imdFrameData;
+ imdX = imdPtr->x;
+ imdY = imdPtr->y;
+ imdW = imdPtr->width;
+ imdH = imdPtr->height;
+ sW = imdPtr->surfDesc->width;
+ imdVidMem = imdPtr->surfDesc->vidPtr + sW * imdY + imdX;
+
+ type = *dataPtr++;
+ srcPtr = dataPtr;
+
+ if (type & 0x10) {
+ type ^= 0x10;
+ dataPtr++; // => 0x3C8 |_ palette
+ dataPtr += 48; // => 0x3C9 | stuff
+ }
+
+ srcPtr = dataPtr;
+ if (type & 0x80) {
+ srcPtr = (byte *) _imdVidBuffer;
+ type &= 0x7F;
+ if ((type == 2) && (imdW == sW)) {
+ imdFrameUncompressor(imdVidMem, dataPtr);
+ return;
+ } else
+ imdFrameUncompressor(srcPtr, dataPtr);
+ }
+
+ if (type == 2) {
+ for (i = 0; i < imdH; i++) {
+ memcpy(imdVidMem, srcPtr, imdW);
+ srcPtr += imdW;
+ imdVidMem += sW;
+ }
+ } else if (type == 1) {
+ imdVidMemBak = imdVidMem;
+ for (i = 0; i < imdH; i++) {
+ pixWritten = 0;
+ while (pixWritten < imdW) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) {
+ pixCount = (pixCount & 0x7F) + 1;
+ // Just to be safe
+ pixCount = (pixWritten + pixCount) > imdW ? imdW - pixWritten : pixCount;
+ pixWritten += pixCount;
+ memcpy(imdVidMem, srcPtr, pixCount);
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else {
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW;
+ imdVidMem = imdVidMemBak;
+ }
+ } else if (type == 0x42) { // loc_2AFC4
+ warning("=> type == 0x42");
+ } else if ((type & 0xF) == 2) { // loc_2AFEC
+ warning("=> (type & 0xF) == 2");
+ } else { // loc_2B021
+ srcPtrBak = srcPtr;
+ for (i = 0; i < imdH; i += 2) {
+ pixWritten = 0;
+ while (pixWritten < imdW) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) {
+ pixCount = (pixCount & 0x7F) + 1;
+ // Just to be safe
+ pixCount = (pixWritten + pixCount) > imdW ? imdW - pixWritten : pixCount;
+ pixWritten += pixCount;
+ memcpy(imdVidMem, srcPtr, pixCount);
+ memcpy(imdVidMem + sW, srcPtr, pixCount);
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else {
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ srcPtrBak += sW + sW;
+ srcPtr = srcPtrBak;
+ }
+ }
+}
+
+void Game::imdFrameUncompressor(byte *dest, byte *src) {
+ int i;
+ byte buf[4370];
+ int16 chunkLength;
+ int16 frameLength;
+ uint16 bufPos1;
+ uint16 bufPos2;
+ uint16 tmp;
+ uint8 chunkBitField;
+ uint8 chunkCount;
+ bool mode;
+
+ memset(buf, 0, sizeof(buf));
+
+ frameLength = READ_LE_UINT16(src);
+ src += 4;
+ bufPos1 = 4078;
+ mode = 0; // 275h (jnz +2)
+ if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
+ src += 4;
+ bufPos1 = 273;
+ mode = 1; // 123Ch (cmp al, 12h)
+ }
+ 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;
+ }
+ frameLength -= chunkLength;
+ } else if (((tmp + chunkLength) < bufPos1) || ((chunkLength + bufPos1) < bufPos2)) {
+ memcpy(dest, buf + bufPos2, chunkLength);
+ dest += chunkLength;
+ memmove(buf + bufPos1, buf + bufPos2, chunkLength);
+ bufPos1 += chunkLength;
+ bufPos2 += chunkLength;
+ frameLength -= chunkLength;
+ } else {
+ for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ }
+ frameLength -= chunkLength;
+ }
+ }
+}
+
+int16 Game::sub_2C825(Imd *imdPtr) {
+ warning("GOB2 Stub! sub_2C825()");
+ return 0;
+}
+
} // End of namespace Gob