diff options
Diffstat (limited to 'engines/gob')
30 files changed, 2012 insertions, 589 deletions
diff --git a/engines/gob/anim.h b/engines/gob/anim.h index f5252364b9..f4d255e590 100644 --- a/engines/gob/anim.h +++ b/engines/gob/anim.h @@ -23,6 +23,8 @@ #ifndef GOB_ANIM_H #define GOB_ANIM_H +#include "gob/video.h" + namespace Gob { class Anim { diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index b862302492..da61f7b187 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -317,6 +317,10 @@ void DataIO::seekData(int16 handle, int32 pos, int16 from) { file_getHandle(handle)->seek(pos, from); } +int32 DataIO::getPos(int16 handle) { + return file_getHandle(handle)->pos(); +} + int32 DataIO::getDataSize(const char *name) { char buf[128]; int32 chunkSz; diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h index 9b28adfd10..a2b27e98c4 100644 --- a/engines/gob/dataio.h +++ b/engines/gob/dataio.h @@ -55,6 +55,7 @@ public: int16 openData(const char *path, Common::File::AccessMode mode = Common::File::kFileReadMode); int32 readData(int16 handle, char *buf, int16 size); void seekData(int16 handle, int32 pos, int16 from); + int32 getPos(int16 handle); int32 getDataSize(const char *name); char *getData(const char *path); char *getSmallData(const char *path); 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 diff --git a/engines/gob/game.h b/engines/gob/game.h index 7e14a54091..f272ece7d3 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -94,6 +94,37 @@ public: int16 frontColor; char *ptr; } GCC_PACK; + + struct ImdCoord { + int16 left; + int16 top; + int16 right; + int16 bottom; + } GCC_PACK; + + struct Imd { + int16 fileHandle; + int16 verMin; + int16 framesCount; + int16 x; + int16 y; + int16 width; + int16 height; + int16 field_E; + int16 curFrame; + Video::Color *palette; + Video::SurfaceDesc *surfDesc; + int32 *framesPos; + int32 firstFramePos; + int16 stdX; + int16 stdY; + int16 stdWidth; + int16 stdHeight; + int32 filePos; + ImdCoord *frameCoords; + int32 frameDataSize; + int32 vidBufferSize; + } GCC_PACK; #pragma END_PACK_STRUCTS TotResTable *_totResourceTable; @@ -135,6 +166,18 @@ public: char *_variablesArray[5]; char _curTotFileArray[5][14]; + Imd *_imdFile; + char _curImdFile[15]; + int16 _imdX; + int16 _imdY; + int16 _imdFrameDataSize; + int16 _imdVidBufferSize; + byte *_imdFrameData; + byte *_imdVidBuffer; + int8 _byte_2FC82; + int8 _byte_2FC83; + byte *_word_2FC80; + Game(GobEngine *vm); virtual ~Game() {}; @@ -163,6 +206,18 @@ public: char *loadLocTexts(void); Snd::SoundDesc *loadSND(const char *path, int8 arg_4); + Imd *loadImdFile(const char *path, Video::SurfaceDesc *surfDesc, int8 flags); + int8 openImd(const char *path, int16 x, int16 y, int16 repeat, int16 flags); + void closeImd(void); + void finishImd(Imd *imdPtr); + void setImdXY(Imd *imdPtr, int16 x, int16 y); + void playImd(int16 arg_0, int16 arg_2, int16 arg_4, int16 arg_6, int16 arg_8, int16 arg_A); + int16 viewImd(Game::Imd *imdPtr, int16 arg_4); + void imdDrawFrame(Imd *imdPtr, int16 arg_4, int16 arg_6, int16 arg_8); + void imdRenderFrame(Imd *imdPtr); + void imdFrameUncompressor(byte *dest, byte *src); + int16 sub_2C825(Imd *imdPtr); + virtual void playTot(int16 skipPlay) = 0; virtual void clearCollisions(void) = 0; virtual void addNewCollision(int16 id, int16 left, int16 top, int16 right, @@ -177,10 +232,12 @@ public: int16 _word_2FC9C; int16 _word_2FC9E; int16 _word_2E51F; + int32 _dword_2F2B6; Video::SurfaceDesc *_off_2E51B; Video::SurfaceDesc *_off_2E517; void sub_ADD2(void); void sub_BB28(void); + protected: int16 _lastCollKey; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index fd6f67c601..61d64d6442 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -199,7 +199,6 @@ int GobEngine::init() { _dataio = new DataIO(this); _pack = new Pack(); _palanim = new PalAnim(this); - _scenery = new Scenery(this); _gtimer = new GTimer(); _util = new Util(this); if (_features & Gob::GF_GOB1) { @@ -212,6 +211,7 @@ int GobEngine::init() { _init = new Init_v1(this); _map = new Map_v1(this); _goblin = new Goblin_v1(this); + _scenery = new Scenery_v1(this); } else if (_features & Gob::GF_GOB2) { _inter = new Inter_v2(this); @@ -223,11 +223,16 @@ int GobEngine::init() { _init = new Init_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); + _scenery = new Scenery_v2(this); } else error("GobEngine::init(): Unknown version of game engine"); - if ((_features & Gob::GF_MAC) || (_features & Gob::GF_GOB1) || (_features & Gob::GF_GOB2)) - _music = new Music(this); + if ((_features & Gob::GF_MAC) || (_features & Gob::GF_GOB1) || (_features & Gob::GF_GOB2)) { + if (ConfMan.get("music_driver") == "null") + _music = new Music_Dummy(this); + else + _music = new Music(this); + } _system->beginGFXTransaction(); initCommonGFX(false); diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index 05bfe6fc5a..1e1c700f81 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -159,7 +159,6 @@ Goblin::Goblin(GobEngine *vm) : _vm(vm) { _word_2F9BA = 0; _dword_2F9B6 = 0; _dword_2F9B2 = 0; - _dword_2F2A4 = 0; } char Goblin::rotateState(int16 from, int16 to) { @@ -633,8 +632,8 @@ void Goblin::switchGoblin(int16 index) { else next = index - 1; - if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3 || - _vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6) + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3 || + _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6) return; if (_goblins[(_currentGoblin + 1) % 3]->type != 0 && @@ -686,7 +685,7 @@ void Goblin::adjustDest(int16 posX, int16 posY) { int16 deltaPix; int16 i; - if (_vm->_map->_passMap[_pressedMapY][_pressedMapX] == 0 && + if (_vm->_map->getPass(_pressedMapX, _pressedMapY) == 0 && (_gobAction == 0 || _vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0)) { @@ -696,7 +695,7 @@ void Goblin::adjustDest(int16 posX, int16 posY) { for (i = 1; i <= _pressedMapX - && _vm->_map->_passMap[_pressedMapY][_pressedMapX - i] == 0; + && _vm->_map->getPass(_pressedMapX - i, _pressedMapY) == 0; i++); if (i <= _pressedMapX) { @@ -705,11 +704,11 @@ void Goblin::adjustDest(int16 posX, int16 posY) { } for (i = 1; - (i + _pressedMapX) < Map::kMapWidth - && _vm->_map->_passMap[_pressedMapY][_pressedMapX + i] == 0; + (i + _pressedMapX) < _vm->_map->_mapWidth + && _vm->_map->getPass(_pressedMapX + i, _pressedMapY) == 0; i++); - if (_pressedMapX + i < Map::kMapWidth) { + if (_pressedMapX + i < _vm->_map->_mapWidth) { deltaPix = (i * 12) - (posX % 12); if (resDelta == -1 || deltaPix < resDeltaPix) { resDeltaPix = deltaPix; @@ -719,11 +718,11 @@ void Goblin::adjustDest(int16 posX, int16 posY) { } for (i = 1; - (i + _pressedMapY) < Map::kMapHeight - && _vm->_map->_passMap[_pressedMapY + i][_pressedMapX] == 0; + (i + _pressedMapY) < _vm->_map->_mapHeight + && _vm->_map->getPass(_pressedMapX, _pressedMapY + i) == 0; i++); - if (_pressedMapY + i < Map::kMapHeight) { + if (_pressedMapY + i < _vm->_map->_mapHeight) { deltaPix = (i * 6) - (posY % 6); if (resDelta == -1 || deltaPix < resDeltaPix) { resDeltaPix = deltaPix; @@ -734,7 +733,7 @@ void Goblin::adjustDest(int16 posX, int16 posY) { for (i = 1; i <= _pressedMapY - && _vm->_map->_passMap[_pressedMapY - i][_pressedMapX] == 0; + && _vm->_map->getPass(_pressedMapX, _pressedMapY - i) == 0; i++); if (i <= _pressedMapY) { @@ -775,11 +774,11 @@ void Goblin::adjustTarget(void) { && _vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX] != 0) { _pressedMapY--; - } else if (_pressedMapX < Map::kMapWidth - 1 + } else if (_pressedMapX < _vm->_map->_mapWidth - 1 && _vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1] != 0) { _pressedMapX++; - } else if (_pressedMapX < Map::kMapWidth - 1 && _pressedMapY > 0 + } else if (_pressedMapX < _vm->_map->_mapWidth - 1 && _pressedMapY > 0 && _vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX + 1] != 0) { _pressedMapY--; @@ -790,7 +789,7 @@ void Goblin::adjustTarget(void) { void Goblin::targetDummyItem(Gob_Object *gobDesc) { if (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0 && - _vm->_map->_passMap[_pressedMapY][_pressedMapX] == 1) { + _vm->_map->getPass(_pressedMapX, _pressedMapY) == 1) { if (gobDesc->curLookDir == 0) { _vm->_map->_itemPoses[0].x = _pressedMapX; _vm->_map->_itemPoses[0].y = _pressedMapY; @@ -938,7 +937,7 @@ void Goblin::targetItem(void) { tmpPosX++; } - if (_vm->_map->_passMap[tmpPosY][tmpPosX] == 1) { + if (_vm->_map->getPass(tmpPosX, tmpPosY) == 1) { _pressedMapX = tmpPosX; _vm->_map->_destX = tmpPosX; _gobDestX = tmpPosX; @@ -951,26 +950,6 @@ void Goblin::targetItem(void) { } } -void Goblin::initiateMove(void) { - _vm->_map->findNearestToDest(); - _vm->_map->findNearestToGob(); - _vm->_map->optimizePoints(); - - _pathExistence = _vm->_map->checkDirectPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY, - _pressedMapX, _pressedMapY); - - if (_pathExistence == 3) { - if (_vm->_map->checkLongPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY, - _pressedMapX, _pressedMapY, - _vm->_map->_nearestWayPoint, _vm->_map->_nearestDest) == 0) { - _pathExistence = 0; - } else { - _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; - _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; - } - } -} - void Goblin::moveFindItem(int16 posX, int16 posY) { int16 i; if (_gobAction == 3 || _gobAction == 4) { @@ -1121,7 +1100,7 @@ void Goblin::moveInitStep(int16 framesCount, int16 action, int16 cont, targetDummyItem(gobDesc); targetItem(); - initiateMove(); + initiateMove(0); moveCheckSelect(framesCount, gobDesc, pGobIndex, pNextAct); } else { @@ -1142,57 +1121,57 @@ void Goblin::moveTreatRopeStairs(Gob_Object *gobDesc) { return; if (gobDesc->nextState == 28 - && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 6) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6) { _forceNextState[0] = 28; _forceNextState[1] = -1; } if (gobDesc->nextState == 29 - && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 6) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6) { _forceNextState[0] = 29; _forceNextState[1] = -1; } if ((gobDesc->nextState == 28 || gobDesc->nextState == 29 || gobDesc->nextState == 20) - && _vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6) { if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4 || gobDesc->curLookDir == 2) - && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 6) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6) { _forceNextState[0] = 28; _forceNextState[1] = -1; } else if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4 || gobDesc->curLookDir == 6) - && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 6) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6) { _forceNextState[0] = 29; _forceNextState[1] = -1; } } if (gobDesc->nextState == 8 - && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 3) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 3) { _forceNextState[0] = 8; _forceNextState[1] = -1; } if (gobDesc->nextState == 9 - && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 3) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 3) { _forceNextState[0] = 9; _forceNextState[1] = -1; } if (gobDesc->nextState == 20 - && _vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3) { if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4 || gobDesc->curLookDir == 2) - && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 3) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 3) { _forceNextState[0] = 8; _forceNextState[1] = -1; } else if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4 || gobDesc->curLookDir == 6) - && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 3) { + && _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 3) { _forceNextState[0] = 9; _forceNextState[1] = -1; } @@ -1226,14 +1205,14 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { _vm->_map->_destY = _pressedMapY; } else { - if (_vm->_map->checkDirectPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY, + if (_vm->_map->checkDirectPath(-1, _vm->_map->_curGoblinX, _vm->_map->_curGoblinY, _gobDestX, _gobDestY) == 1) { _vm->_map->_destX = _gobDestX; _vm->_map->_destY = _gobDestY; } else if (_vm->_map->_curGoblinX == _vm->_map->_destX && _vm->_map->_curGoblinY == _vm->_map->_destY) { if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest) { - _vm->_map->optimizePoints(); + _vm->_map->optimizePoints(0, 0, 0); _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint]. @@ -1245,7 +1224,7 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest) _vm->_map->_nearestWayPoint--; } else if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest) { - _vm->_map->optimizePoints(); + _vm->_map->optimizePoints(0, 0, 0); _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint]. @@ -1257,9 +1236,9 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest) _vm->_map->_nearestWayPoint++; } else { - if (_vm->_map->checkDirectPath(_vm->_map->_curGoblinX, + if (_vm->_map->checkDirectPath(-1, _vm->_map->_curGoblinX, _vm->_map->_curGoblinY, _gobDestX, - _gobDestY) == 3 && _vm->_map->_passMap[_pressedMapY][_pressedMapX] != 0) { + _gobDestY) == 3 && _vm->_map->getPass(_pressedMapX, _pressedMapY) != 0) { _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; } else { @@ -1296,18 +1275,18 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; case Map::kDirN: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6 && _currentGoblin != 1) { _pathExistence = 0; break; } - if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3) { + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3) { gobDesc->nextState = 8; break; } - if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6 && _currentGoblin == 1) { gobDesc->nextState = 28; break; @@ -1317,18 +1296,18 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; case Map::kDirS: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6 && _currentGoblin != 1) { _pathExistence = 0; break; } - if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3) { + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3) { gobDesc->nextState = 9; break; } - if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6 && _currentGoblin == 1) { gobDesc->nextState = 29; break; @@ -1338,7 +1317,7 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; case Map::kDirSE: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX + 1] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX + 1, _vm->_map->_curGoblinY + 1) == 6 && _currentGoblin != 1) { _pathExistence = 0; break; @@ -1352,7 +1331,7 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; case Map::kDirSW: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX - 1] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX - 1, _vm->_map->_curGoblinY + 1) == 6 && _currentGoblin != 1) { _pathExistence = 0; break; @@ -1366,7 +1345,7 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; case Map::kDirNW: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX - 1] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX - 1, _vm->_map->_curGoblinY - 1) == 6 && _currentGoblin != 1) { _pathExistence = 0; break; @@ -1380,7 +1359,7 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; case Map::kDirNE: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX + 1] == 6 && + if (_vm->_map->getPass(_vm->_map->_curGoblinX + 1, _vm->_map->_curGoblinY - 1) == 6 && _currentGoblin != 1) { _pathExistence = 0; break; @@ -1439,8 +1418,8 @@ void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) { break; default: - if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3 || - (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6 + if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3 || + (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6 && _currentGoblin == 1)) { gobDesc->nextState = 20; break; @@ -2017,8 +1996,8 @@ void Goblin::pickItem(int16 indexToPocket, int16 idToPocket) { _itemIndInPocket = indexToPocket; _itemIdInPocket = idToPocket; - for (y = 0; y < Map::kMapHeight; y++) { - for (x = 0; x < Map::kMapWidth; x++) { + for (y = 0; y < _vm->_map->_mapHeight; y++) { + for (x = 0; x < _vm->_map->_mapWidth; x++) { if (_itemByteFlag == 1) { if (((_vm->_map->_itemsMap[y][x] & 0xff00) >> 8) == idToPocket) @@ -2084,7 +2063,7 @@ void Goblin::placeItem(int16 indexInPocket, int16 idInPocket) { } if (lookDir == 4) { - if (xPos < Map::kMapWidth - 1) { + if (xPos < _vm->_map->_mapWidth - 1) { _vm->_map->placeItem(xPos + 1, yPos, idInPocket); if (yPos > 0) { @@ -2107,10 +2086,10 @@ void Goblin::placeItem(int16 indexInPocket, int16 idInPocket) { _vm->_map->_itemPoses[idInPocket].orient = lookDir; if (_vm->_map->_itemPoses[idInPocket].orient == 0) { // _vm->_map->_itemPoses[idInPocket].x++; - if (_vm->_map->_passMap[(int)_vm->_map->_itemPoses[idInPocket].y][_vm->_map->_itemPoses[idInPocket].x + 1] == 1) + if (_vm->_map->getPass(_vm->_map->_itemPoses[idInPocket].x + 1, (int)_vm->_map->_itemPoses[idInPocket].y) == 1) _vm->_map->_itemPoses[idInPocket].x++; } else { - if (_vm->_map->_passMap[(int)_vm->_map->_itemPoses[idInPocket].y][_vm->_map->_itemPoses[idInPocket].x - 1] == 1) + if (_vm->_map->getPass(_vm->_map->_itemPoses[idInPocket].x - 1, (int)_vm->_map->_itemPoses[idInPocket].y) == 1) _vm->_map->_itemPoses[idInPocket].x--; } } @@ -2133,8 +2112,8 @@ void Goblin::swapItems(int16 indexToPick, int16 idToPick) { _itemIdInPocket = idToPick; if (_itemByteFlag == 0) { - for (y = 0; y < Map::kMapHeight; y++) { - for (x = 0; x < Map::kMapWidth; x++) { + for (y = 0; y < _vm->_map->_mapHeight; y++) { + for (x = 0; x < _vm->_map->_mapWidth; x++) { if ((_vm->_map->_itemsMap[y][x] & 0xff) == idToPick) _vm->_map->_itemsMap[y][x] = (_vm->_map->_itemsMap[y][x] & 0xff00) + @@ -2143,8 +2122,8 @@ void Goblin::swapItems(int16 indexToPick, int16 idToPick) { } } else { - for (y = 0; y < Map::kMapHeight; y++) { - for (x = 0; x < Map::kMapWidth; x++) { + for (y = 0; y < _vm->_map->_mapHeight; y++) { + for (x = 0; x < _vm->_map->_mapWidth; x++) { if (((_vm->_map->_itemsMap[y][x] & 0xff00) >> 8) == idToPick) _vm->_map->_itemsMap[y][x] = @@ -2296,11 +2275,11 @@ void Goblin::sub_19BD3(void) { Mult::Mult_Object *obj1; Mult::Mult_AnimData *anim0; Mult::Mult_AnimData *anim1; - int16 varVal; - int16 var_2; - int16 var_4; - int16 var_6; - int16 var_8; + int16 pass; + int16 gob1X; + int16 gob2X; + int16 gob1Y; + int16 gob2Y; int16 var_A; int16 var_C; int16 di; @@ -2380,73 +2359,73 @@ void Goblin::sub_19BD3(void) { warning("GOB2 Stub! sub_195C7(1, 16);"); } - var_2 = obj0->goblinX; - var_4 = obj1->goblinX; - var_6 = obj0->goblinY; - var_8 = obj1->goblinY; + gob1X = obj0->goblinX; + gob2X = obj1->goblinX; + gob1Y = obj0->goblinY; + gob2Y = obj1->goblinY; di = anim0->field_13; si = anim0->field_14; var_A = anim1->field_13; var_C = anim1->field_14; - varVal = _vm->_util->readVariableByte(_dword_2F2A4 + var_6 * 40 + var_2); - if ((varVal > 17) && (varVal < 21)) - warning("GOB2 Stub! sub_195C7(anim0);"); - varVal = _vm->_util->readVariableByte(_dword_2F2A4 + var_8 * 40 + var_4); - if ((varVal > 17) && (varVal < 21)) + pass = _vm->_map->getPass(gob1X, gob1Y, 40); + if ((pass > 17) && (pass < 21)) + warning("GOB2 Stub! sub_19AB7(anim0);"); + pass = _vm->_map->getPass(gob2X, gob2Y, 40); + if ((pass > 17) && (pass < 21)) warning("GOB2 Stub! sub_19B45(anim1);"); if ((di < 0) || (di > 39) || (si < 0) || (si > 39)) return; - if (var_6 > si) { - if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17) { + if (gob1Y > si) { + if (_vm->_map->getPass(di, si, 40) > 17) { do { si--; - } while (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17); + } while (_vm->_map->getPass(di, si, 40) > 17); si++; - if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di - 1) == 0) { - if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di + 1) != 0) + if (_vm->_map->getPass(di - 1, si, 40) == 0) { + if (_vm->_map->getPass(di + 1, si, 40) != 0) di++; } else di--; warning("GOB2 Stub! sub_197A6(di (=%d), si (=%d), 0);", si, di); } } else { - if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17) { + if (_vm->_map->getPass(di, si, 40) > 17) { do { si++; - } while (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17); + } while (_vm->_map->getPass(di, si, 40) > 17); si--; - if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di - 1) == 0) { - if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di + 1) != 0) + if (_vm->_map->getPass(di - 1, si, 40) == 0) { + if (_vm->_map->getPass(di + 1, si, 40) != 0) di++; } else di--; warning("GOB2 Stub! sub_197A6(di (=%d), si (=%d), 0);", si, di); } } - if (var_8 > var_C) { - if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17) { + if (gob2Y > var_C) { + if (_vm->_map->getPass(var_A, var_C, 40) > 17) { do { var_C--; - } while (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17); + } while (_vm->_map->getPass(var_A, var_C, 40) > 17); var_C++; - if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) == 0) { - if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) != 0) + if (_vm->_map->getPass(var_A - 1, var_C, 40) == 0) { + if (_vm->_map->getPass(var_A + 1, var_C, 40) != 0) var_A++; } else var_A--; warning("GOB2 Stub! sub_197A6(var_A (=%d), var_C (=%d), 1);", var_A, var_C); } } else { - if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17) { + if (_vm->_map->getPass(var_A, var_C, 40) > 17) { do { var_C++; - } while (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17); + } while (_vm->_map->getPass(var_A, var_C, 40) > 17); var_C--; - if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) == 0) { - if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) != 0) + if (_vm->_map->getPass(var_A - 1, var_C, 40) == 0) { + if (_vm->_map->getPass(var_A + 1, var_C, 40) != 0) var_A++; } else var_A--; diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index 2a43add91a..7e506e4214 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -23,6 +23,7 @@ #ifndef GOB_GOBLIN_H #define GOB_GOBLIN_H +#include "gob/gob.h" #include "gob/util.h" #include "gob/sound.h" @@ -192,7 +193,6 @@ public: int16 _word_2F9BA; int16 _dword_2F9B6; // index into the variables array int16 _dword_2F9B2; // index into the variables array - char *_dword_2F2A4; // index into the variables array // Functions char rotateState(int16 from, int16 to); @@ -223,6 +223,7 @@ public: virtual void placeObject(Gob_Object * objDesc, char animated, int16 index, int16 x, int16 y, int16 state) = 0; virtual void freeObjects(void) = 0; + virtual void initiateMove(int16 index) = 0; Goblin(GobEngine *vm); virtual ~Goblin() {}; @@ -238,7 +239,6 @@ protected: void adjustTarget(void); void targetDummyItem(Gob_Object *gobDesc); void targetItem(void); - void initiateMove(void); void moveFindItem(int16 posX, int16 posY); void moveCheckSelect(int16 framesCount, Gob_Object * gobDesc, int16 *pGobIndex, int16 *nextAct); void moveInitStep(int16 framesCount, int16 action, int16 cont, @@ -253,6 +253,7 @@ public: virtual void placeObject(Gob_Object * objDesc, char animated, int16 index, int16 x, int16 y, int16 state); virtual void freeObjects(void); + virtual void initiateMove(int16 index); Goblin_v1(GobEngine *vm); virtual ~Goblin_v1() {}; @@ -263,6 +264,7 @@ public: virtual void placeObject(Gob_Object * objDesc, char animated, int16 index, int16 x, int16 y, int16 state); virtual void freeObjects(void); + virtual void initiateMove(int16 index); Goblin_v2(GobEngine *vm); virtual ~Goblin_v2() {}; diff --git a/engines/gob/goblin_v1.cpp b/engines/gob/goblin_v1.cpp index 234cc778d9..d7623604e9 100644 --- a/engines/gob/goblin_v1.cpp +++ b/engines/gob/goblin_v1.cpp @@ -27,6 +27,7 @@ #include "gob/gob.h" #include "gob/goblin.h" #include "gob/scenery.h" +#include "gob/map.h" namespace Gob { @@ -137,4 +138,24 @@ void Goblin_v1::placeObject(Gob_Object *objDesc, char animated, } } +void Goblin_v1::initiateMove(int16 index) { + _vm->_map->findNearestToDest(0); + _vm->_map->findNearestToGob(0); + _vm->_map->optimizePoints(0, 0, 0); + + _pathExistence = _vm->_map->checkDirectPath(0, _vm->_map->_curGoblinX, _vm->_map->_curGoblinY, + _pressedMapX, _pressedMapY); + + if (_pathExistence == 3) { + if (_vm->_map->checkLongPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY, + _pressedMapX, _pressedMapY, + _vm->_map->_nearestWayPoint, _vm->_map->_nearestDest) == 0) { + _pathExistence = 0; + } else { + _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; + _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; + } + } +} + } // End of namespace Gob diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp index 724361ff4a..9c4befc5cc 100644 --- a/engines/gob/goblin_v2.cpp +++ b/engines/gob/goblin_v2.cpp @@ -29,6 +29,7 @@ #include "gob/mult.h" #include "gob/game.h" #include "gob/scenery.h" +#include "gob/map.h" namespace Gob { @@ -74,11 +75,13 @@ void Goblin_v2::placeObject(Gob_Object *objDesc, char animated, objAnim->newCycle = 0; _vm->_scenery->updateAnim(objAnim->layer, 0, objAnim->animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_mult->_word_2CC86 == 0) - *obj->pPosY = (y + 1) * _vm->_mult->_word_2F2AF; // - (_vm->_scenery->_animBottom - _vm->scenery->_animTop); + if (!_vm->_map->_bigTiles) + *obj->pPosY = (y + 1) * _vm->_map->_tilesHeight + - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); else - *obj->pPosY = ((y + 1) / 2) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->scenery->_animTop); - *obj->pPosX = x * _vm->_mult->_word_2F2B1; + *obj->pPosY = ((y + 1) / 2) * _vm->_map->_tilesHeight + - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); + *obj->pPosX = x * _vm->_map->_tilesWidth; } else { if (obj->goblinStates[state] != 0) { layer = obj->goblinStates[state][0].layer; @@ -91,14 +94,32 @@ void Goblin_v2::placeObject(Gob_Object *objDesc, char animated, objAnim->isStatic = 0; objAnim->newCycle = _vm->_scenery->_animations[animation].layers[layer]->framesCount; _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_mult->_word_2CC86 == 0) - *obj->pPosY = (y + 1) * _vm->_mult->_word_2F2AF; // - (_vm->_scenery->_animBottom - _vm->scenery->_animTop); + if (!_vm->_map->_bigTiles) + *obj->pPosY = (y + 1) * _vm->_map->_tilesHeight + - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); else - *obj->pPosY = ((y + 1) / 2) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->scenery->_animTop); - *obj->pPosX = x * _vm->_mult->_word_2F2B1; - warning("GOB2 Stub! sub_FE1D(obj"); + *obj->pPosY = ((y + 1) / 2) * _vm->_map->_tilesHeight + - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); + *obj->pPosX = x * _vm->_map->_tilesWidth; + initiateMove(index); } else - warning("GOB2 Stub! sub_FE1D(obj"); + initiateMove(index); + } +} + +void Goblin_v2::initiateMove(int16 index) { + Mult::Mult_Object *obj = &_vm->_mult->_objects[index]; + + obj->destX = obj->gobDestX; + obj->destY = obj->gobDestY; + _vm->_map->findNearestToDest(index); + _vm->_map->findNearestToGob(index); + _vm->_map->optimizePoints(index, obj->goblinX, obj->goblinY); + obj->pAnimData->field_12 = _vm->_map->checkDirectPath(index, + obj->goblinX, obj->goblinY, obj->gobDestX, obj->gobDestY); + if (obj->pAnimData->field_12 == 3) { + obj->destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; + obj->destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; } } diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index 69787ae601..9ef90718eb 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -304,8 +304,8 @@ void Inter::renewTimeInVars(void) { } void Inter::manipulateMap(int16 xPos, int16 yPos, int16 item) { - for (int16 y = 0; y < Map::kMapHeight; y++) { - for (int16 x = 0; x < Map::kMapWidth; x++) { + for (int16 y = 0; y < _vm->_map->_mapHeight; y++) { + for (int16 x = 0; x < _vm->_map->_mapWidth; x++) { if ((_vm->_map->_itemsMap[y][x] & 0xff) == item) { _vm->_map->_itemsMap[y][x] &= 0xff00; } else if (((_vm->_map->_itemsMap[y][x] & 0xff00) >> 8) @@ -315,7 +315,7 @@ void Inter::manipulateMap(int16 xPos, int16 yPos, int16 item) { } } - if (xPos < Map::kMapWidth - 1) { + if (xPos < _vm->_map->_mapWidth - 1) { if (yPos > 0) { if ((_vm->_map->_itemsMap[yPos][xPos] & 0xff00) != 0 || (_vm->_map->_itemsMap[yPos - 1][xPos] & 0xff00) != @@ -415,28 +415,28 @@ void Inter::manipulateMap(int16 xPos, int16 yPos, int16 item) { if (item < 0 || item >= 20) return; - if (xPos > 1 && _vm->_map->_passMap[yPos][xPos - 2] == 1) { + if (xPos > 1 && _vm->_map->getPass(xPos - 2, yPos) == 1) { _vm->_map->_itemPoses[item].x = xPos - 2; _vm->_map->_itemPoses[item].y = yPos; _vm->_map->_itemPoses[item].orient = 4; return; } - if (xPos < Map::kMapWidth - 2 && _vm->_map->_passMap[yPos][xPos + 2] == 1) { + if (xPos < _vm->_map->_mapWidth - 2 && _vm->_map->getPass(xPos + 2, yPos) == 1) { _vm->_map->_itemPoses[item].x = xPos + 2; _vm->_map->_itemPoses[item].y = yPos; _vm->_map->_itemPoses[item].orient = 0; return; } - if (xPos < Map::kMapWidth - 1 && _vm->_map->_passMap[yPos][xPos + 1] == 1) { + if (xPos < _vm->_map->_mapWidth - 1 && _vm->_map->getPass(xPos + 1, yPos) == 1) { _vm->_map->_itemPoses[item].x = xPos + 1; _vm->_map->_itemPoses[item].y = yPos; _vm->_map->_itemPoses[item].orient = 0; return; } - if (xPos > 0 && _vm->_map->_passMap[yPos][xPos - 1] == 1) { + if (xPos > 0 && _vm->_map->getPass(xPos - 1, yPos) == 1) { _vm->_map->_itemPoses[item].x = xPos - 1; _vm->_map->_itemPoses[item].y = yPos; _vm->_map->_itemPoses[item].orient = 4; diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 2ae07da874..3377287001 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -62,6 +62,7 @@ public: void manipulateMap(int16 xPos, int16 yPos, int16 item); virtual int16 loadSound(int16 slot) = 0; virtual void storeMouse(void) = 0; + virtual void animPalette(void) = 0; Inter(GobEngine *vm); virtual ~Inter() {}; @@ -77,7 +78,6 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j) = 0; virtual const char *getOpcodeGoblinDesc(int i) = 0; virtual void loadMult(void) = 0; - virtual void animPalette(void) = 0; }; class Inter_v1 : public Inter { @@ -86,6 +86,7 @@ public: virtual ~Inter_v1() {}; virtual int16 loadSound(int16 slot); virtual void storeMouse(void); + virtual void animPalette(void); protected: typedef void (Inter_v1::*OpcodeDrawProcV1)(void); @@ -116,7 +117,6 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j); virtual const char *getOpcodeGoblinDesc(int i); virtual void loadMult(void); - virtual void animPalette(void); void o1_loadMult(void); void o1_playMult(void); @@ -278,6 +278,7 @@ public: virtual ~Inter_v2() {}; virtual int16 loadSound(int16 search); virtual void storeMouse(void); + virtual void animPalette(void); protected: typedef void (Inter_v2::*OpcodeDrawProcV2)(void); @@ -308,16 +309,13 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j); virtual const char *getOpcodeGoblinDesc(int i); virtual void loadMult(void); - virtual void animPalette(void); void o2_drawStub(void) { error("Gob2 stub"); } void o2_totSub(void); void o2_switchTotSub(void); - void o2_stub0x52(void); void o2_stub0x54(void); void o2_stub0x80(void); void o2_stub0x82(void); - void o2_stub0x83(void); void o2_stub0x85(void); void o2_renderStatic(void); bool o2_animPalInit(char &cmdCount, int16 &counter, int16 &retFlag); @@ -332,6 +330,7 @@ protected: void o2_freeGoblins(void); void o2_writeGoblinPos(void); void o2_placeGoblin(void); + void o2_moveGoblin(void); void o2_multSub(void); void o2_setRenderFlags(void); void o2_initMult(void); @@ -343,6 +342,7 @@ protected: void o2_getCDTrackPos(void); void o2_playMult(void); void o2_initCursor(void); + void o2_playImd(void); void o2_setPickable(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc); }; diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 9e6b574f67..96e91b6559 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1485,7 +1485,20 @@ void Inter_v1::o1_freeAnim(void) { } void Inter_v1::o1_updateAnim(void) { - _vm->_scenery->interUpdateAnim(); + int16 deltaX; + int16 deltaY; + int16 flags; + int16 frame; + int16 layer; + int16 animation; + + evalExpr(&deltaX); + evalExpr(&deltaY); + evalExpr(&animation); + evalExpr(&layer); + evalExpr(&frame); + flags = load16(); + _vm->_scenery->updateAnim(layer, frame, animation, flags, deltaX, deltaY, 1); } void Inter_v1::o1_initMult(void) { @@ -2230,7 +2243,7 @@ void Inter_v1::o1_setPassMap(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Obj int16 xPos = load16(); int16 yPos = load16(); int16 val = load16(); - _vm->_map->_passMap[yPos][xPos] = val; + _vm->_map->setPass(xPos, yPos, val); } void Inter_v1::o1_setGoblinPosH(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc) { diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index b09dbf61fc..3757d59c70 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -227,7 +227,7 @@ void Inter_v2::setupOpcodes(void) { /* 50 */ OPCODE(o2_loadMapObjects), OPCODE(o2_freeGoblins), - OPCODE(o2_stub0x52), + OPCODE(o2_moveGoblin), OPCODE(o2_writeGoblinPos), /* 54 */ OPCODE(o2_stub0x54), @@ -288,7 +288,7 @@ void Inter_v2::setupOpcodes(void) { OPCODE(o2_stub0x80), OPCODE(o2_drawStub), OPCODE(o2_stub0x82), - OPCODE(o2_stub0x83), + OPCODE(o2_playImd), /* 84 */ OPCODE(o2_drawStub), OPCODE(o2_stub0x85), @@ -712,20 +712,10 @@ const char *Inter_v2::getOpcodeGoblinDesc(int i) { return ""; } -void Inter_v2::o2_stub0x52(void) { - int16 expr1 = _vm->_parse->parseValExpr(); - int16 expr2 = _vm->_parse->parseValExpr(); - int16 expr3 = _vm->_parse->parseValExpr(); - - warning("STUB: Gob2 drawOperation 0x52 (%d %d %d)", expr1, expr2, expr3); -} - void Inter_v2::o2_stub0x54(void) { int16 index = _vm->_parse->parseValExpr(); - warning("STUB: Gob2 drawOperation 0x54 (%d)", index); - -// _vm->_mult->_objects[index].pAnimData->field_12 = 4; + _vm->_mult->_objects[index].pAnimData->field_12 = 4; } void Inter_v2::o2_stub0x80(void) { @@ -757,7 +747,7 @@ void Inter_v2::o2_stub0x80(void) { memset(_vm->_global->_redPalette, 0, 256); memset(_vm->_global->_greenPalette, 0, 256); memset(_vm->_global->_bluePalette, 0, 256); - warning("GOB2 Stub! _vid_setStubDriver"); +// warning("GOB2 Stub! _vid_setStubDriver"); if (videoMode == 0x10) { _vm->_global->_videoMode = 0x12; @@ -820,32 +810,6 @@ void Inter_v2::o2_stub0x82(void) { warning("GOB2 Stub! _vid_setPixelShift(_vm->_game->_word_2FC9E, _vm->_game->_word_2FC9C);");*/ } -// some sub -void Inter_v2::o2_stub0x83(void) { - char dest[128]; - int16 expr1; - int16 expr2; - int16 expr3; - int16 expr4; - int16 expr5; - int16 expr6; - int16 expr7; - int16 expr8; - - evalExpr(0); - strcpy(dest, _vm->_global->_inter_resStr); - expr1 = _vm->_parse->parseValExpr(); - expr2 = _vm->_parse->parseValExpr(); - expr3 = _vm->_parse->parseValExpr(); - expr4 = _vm->_parse->parseValExpr(); - expr5 = _vm->_parse->parseValExpr(); - expr6 = _vm->_parse->parseValExpr(); - expr7 = _vm->_parse->parseValExpr(); - expr8 = _vm->_parse->parseValExpr(); - - warning("STUB: Gob2 drawOperation 0x83 (\"%s\" %d %d %d %d %d %d %d %d)", dest, expr1, expr2, expr3, expr4, expr5, expr6, expr7, expr8); -} - void Inter_v2::o2_stub0x85(void) { char dest[32]; @@ -977,6 +941,28 @@ void Inter_v2::o2_placeGoblin(void) { _vm->_goblin->placeObject(0, 0, index, x, y, state); } +void Inter_v2::o2_moveGoblin(void) { + Mult::Mult_Object *obj; + Mult::Mult_AnimData *objAnim; + int16 destX = _vm->_parse->parseValExpr(); + int16 destY = _vm->_parse->parseValExpr(); + int16 index = _vm->_parse->parseValExpr(); + + obj = &_vm->_mult->_objects[index]; + objAnim = obj->pAnimData; + + obj->gobDestX = destX; + obj->gobDestY = destY; + objAnim->field_13 = destX; + objAnim->field_14 = destY; + if (objAnim->someFlag != 0) { + if ((destX == -1) && (destY == -1)) { + warning("STUB: Gob2 drawOperation moveGoblin (%d %d %d), someFlag: %d", destX, destY, index, objAnim->someFlag); + } + } + _vm->_goblin->initiateMove(index); +} + void Inter_v2::o2_writeGoblinPos(void) { int16 var1; int16 var2; @@ -1033,14 +1019,14 @@ void Inter_v2::loadMult(void) { objAnim = obj->pAnimData; val = *obj->pPosX % 256; - obj->field_1C = val; - obj->field_1E = val; + obj->destX = val; + obj->gobDestX = val; obj->goblinX = val; val = *obj->pPosY % 256; - obj->field_1D = val; - obj->field_1F = val; + obj->destY = val; + obj->gobDestY = val; obj->goblinY = val; - *obj->pPosX *= _vm->_mult->_word_2F2B1; + *obj->pPosX *= _vm->_map->_tilesWidth; objAnim->field_15 = objAnim->unknown; objAnim->field_E = -1; objAnim->field_F = -1; @@ -1050,12 +1036,14 @@ void Inter_v2::loadMult(void) { objAnim->animation = obj->goblinStates[objAnim->state][0].animation; animation = objAnim->animation; _vm->_scenery->updateAnim(objAnim->state, 0, 0, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_mult->_word_2CC86 == 0) { - *obj->pPosY = (obj->goblinY + 1) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) + if (!_vm->_map->_bigTiles) { + *obj->pPosY = (obj->goblinY + 1) * _vm->_map->_tilesHeight + - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); } else { - *obj->pPosY = (obj->goblinY + 1) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (obj->goblinY + 1) / 2; + *obj->pPosY = ((obj->goblinY + 1) / 2) * _vm->_map->_tilesHeight + - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); } - *obj->pPosX = obj->goblinX * _vm->_mult->_word_2F2B1; + *obj->pPosX = obj->goblinX * _vm->_map->_tilesWidth; } } if (_vm->_mult->_objects[objIndex].pAnimData->animType == 101) { @@ -1675,6 +1663,53 @@ void Inter_v2::o2_initCursor(void) { } } +void Inter_v2::o2_playImd(void) { + char imd[128]; + int i; + int16 x; + int16 y; + int16 startFrame; // di + int16 lastFrame; // si + int16 breakKey; + int16 flags; + int16 expr7; + int16 expr8; + + evalExpr(0); + _vm->_global->_inter_resStr[8] = 0; + strcpy(imd, _vm->_global->_inter_resStr); + x = _vm->_parse->parseValExpr(); + y = _vm->_parse->parseValExpr(); + startFrame = _vm->_parse->parseValExpr(); + lastFrame = _vm->_parse->parseValExpr(); + breakKey = _vm->_parse->parseValExpr(); + flags = _vm->_parse->parseValExpr(); + expr7 = _vm->_parse->parseValExpr(); + expr8 = _vm->_parse->parseValExpr(); + + if (_vm->_game->openImd(imd, x, y, startFrame, flags) == 0) + return; + + int16 var_C; + + var_C = lastFrame; + if (lastFrame < 0) + lastFrame = _vm->_game->_imdFile->framesCount - 1; + for (i = startFrame; i <= lastFrame; i++) { + _vm->_game->playImd(i, 1 << (flags & 0x3F), expr7, expr8, 0, lastFrame); + WRITE_VAR(11, i); + 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) + return; + } + } + if (var_C == -1) + _vm->_game->closeImd(); +} + void Inter_v2::o2_totSub(void) { char totFile[14]; int flags; diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp index 5333ee5219..c69706b5e4 100644 --- a/engines/gob/map.cpp +++ b/engines/gob/map.cpp @@ -33,21 +33,26 @@ #include "gob/goblin.h" #include "gob/sound.h" #include "gob/scenery.h" +#include "gob/mult.h" namespace Gob { Map::Map(GobEngine *vm) : _vm(vm) { int i; - for (i = 0; i < kMapHeight; i++) - for (int j = 0; j < kMapWidth; j++) { - _passMap[i][j] = 0; - _itemsMap[i][j] = 0; - } - for (i = 0; i < 40; i++) { - _wayPoints[i].x = 0; - _wayPoints[i].y = 0; - } + _mapWidth = -1; + _mapHeight = -1; + _screenWidth = 0; + _tilesWidth = 0; + _tilesHeight = 0; + _passWidth = 0; + + _passMap = 0; + _itemsMap = 0; + _wayPointsCount = 0; + _wayPoints = 0; + _bigTiles = false; + for (i = 0; i < 40; i++) { _itemPoses[i].x = 0; _itemPoses[i].y = 0; @@ -85,7 +90,7 @@ int16 Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { if (x0 == x1 && y0 == y1) return 0; - if (!(x1 >= 0 && x1 < kMapWidth && y1 >= 0 && y1 < kMapHeight)) + if (!(x1 >= 0 && x1 < _mapWidth && y1 >= 0 && y1 < _mapHeight)) return 0; if (y1 > y0) @@ -98,91 +103,91 @@ int16 Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { else if (x1 < x0) dir |= kLeft; - if (_passMap[y0][x0] == 3 && (dir & kUp)) { - if (_passMap[y0 - 1][x0] != 0) + if (getPass(x0, y0) == 3 && (dir & kUp)) { + if (getPass(x0, y0 - 1) != 0) return kDirN; } - if (_passMap[y0][x0] == 3 && (dir & kDown)) { - if (_passMap[y0 + 1][x0] != 0) + if (getPass(x0, y0) == 3 && (dir & kDown)) { + if (getPass(x0, y0 + 1) != 0) return kDirS; } - if (_passMap[y0][x0] == 6 && (dir & kUp)) { - if (_passMap[y0 - 1][x0] != 0) + if (getPass(x0, y0) == 6 && (dir & kUp)) { + if (getPass(x0, y0 - 1) != 0) return kDirN; } - if (_passMap[y0][x0] == 6 && (dir & kDown)) { - if (_passMap[y0 + 1][x0] != 0) + if (getPass(x0, y0) == 6 && (dir & kDown)) { + if (getPass(x0, y0 + 1) != 0) return kDirS; } if (dir == kLeft) { - if (x0 - 1 >= 0 && _passMap[y0][x0 - 1] != 0) + if (x0 - 1 >= 0 && getPass(x0 - 1, y0) != 0) return kDirW; return 0; } if (dir == kRight) { - if (x0 + 1 < kMapWidth && _passMap[y0][x0 + 1] != 0) + if (x0 + 1 < _mapWidth && getPass(x0 + 1, y0) != 0) return kDirE; return 0; } if (dir == kUp) { - if (y0 - 1 >= 0 && _passMap[y0 - 1][x0] != 0) + if (y0 - 1 >= 0 && getPass(x0, y0 - 1) != 0) return kDirN; if (y0 - 1 >= 0 && x0 - 1 >= 0 - && _passMap[y0 - 1][x0 - 1] != 0) + && getPass(x0 - 1, y0 - 1) != 0) return kDirNW; - if (y0 - 1 >= 0 && x0 + 1 < kMapWidth - && _passMap[y0 - 1][x0 + 1] != 0) + if (y0 - 1 >= 0 && x0 + 1 < _mapWidth + && getPass(x0 + 1, y0 - 1) != 0) return kDirNE; return 0; } if (dir == kDown) { - if (y0 + 1 < kMapHeight && _passMap[y0 + 1][x0] != 0) + if (y0 + 1 < _mapHeight && getPass(x0, y0 + 1) != 0) return kDirS; - if (y0 + 1 < kMapHeight && x0 - 1 >= 0 - && _passMap[y0 + 1][x0 - 1] != 0) + if (y0 + 1 < _mapHeight && x0 - 1 >= 0 + && getPass(x0 - 1, y0 + 1) != 0) return kDirSW; - if (y0 + 1 < kMapHeight && x0 + 1 < kMapWidth - && _passMap[y0 + 1][x0 + 1] != 0) + if (y0 + 1 < _mapHeight && x0 + 1 < _mapWidth + && getPass(x0 + 1, y0 + 1) != 0) return kDirSE; return 0; } if (dir == (kRight | kUp)) { - if (y0 - 1 >= 0 && x0 + 1 < kMapWidth - && _passMap[y0 - 1][x0 + 1] != 0) + if (y0 - 1 >= 0 && x0 + 1 < _mapWidth + && getPass(x0 + 1, y0 - 1) != 0) return kDirNE; - if (y0 - 1 >= 0 && _passMap[y0 - 1][x0] != 0) + if (y0 - 1 >= 0 && getPass(x0, y0 - 1) != 0) return kDirN; - if (x0 + 1 < kMapWidth && _passMap[y0][x0 + 1] != 0) + if (x0 + 1 < _mapWidth && getPass(x0 + 1, y0) != 0) return kDirE; return 0; } if (dir == (kRight | kDown)) { - if (x0 + 1 < kMapWidth && y0 + 1 < kMapHeight - && _passMap[y0 + 1][x0 + 1] != 0) + if (x0 + 1 < _mapWidth && y0 + 1 < _mapHeight + && getPass(x0 + 1, y0 + 1) != 0) return kDirSE; - if (y0 + 1 < kMapHeight && _passMap[y0 + 1][x0] != 0) + if (y0 + 1 < _mapHeight && getPass(x0, y0 + 1) != 0) return kDirS; - if (x0 + 1 < kMapWidth && _passMap[y0][x0 + 1] != 0) + if (x0 + 1 < _mapWidth && getPass(x0 + 1, y0) != 0) return kDirE; return 0; @@ -190,27 +195,27 @@ int16 Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { if (dir == (kLeft | kUp)) { if (x0 - 1 >= 0 && y0 - 1 >= 0 - && _passMap[y0 - 1][x0 - 1] != 0) + && getPass(x0 - 1, y0 - 1) != 0) return kDirNW; - if (y0 - 1 >= 0 && _passMap[y0 - 1][x0] != 0) + if (y0 - 1 >= 0 && getPass(x0, y0 - 1) != 0) return kDirN; - if (x0 - 1 >= 0 && _passMap[y0][x0 - 1] != 0) + if (x0 - 1 >= 0 && getPass(x0 - 1, y0) != 0) return kDirW; return 0; } if (dir == (kLeft | kDown)) { - if (x0 - 1 >= 0 && y0 + 1 < kMapHeight - && _passMap[y0 + 1][x0 - 1] != 0) + if (x0 - 1 >= 0 && y0 + 1 < _mapHeight + && getPass(x0 - 1, y0 + 1) != 0) return kDirSW; - if (y0 + 1 < kMapHeight && _passMap[y0 + 1][x0] != 0) + if (y0 + 1 < _mapHeight && getPass(x0, y0 + 1) != 0) return kDirS; - if (x0 - 1 >= 0 && _passMap[y0][x0 - 1] != 0) + if (x0 - 1 >= 0 && getPass(x0 - 1, y0) != 0) return kDirW; return 0; @@ -226,10 +231,10 @@ int16 Map::findNearestWayPoint(int16 x, int16 y) { length = 30000; - for (i = 0; i < 40; i++) { + for (i = 0; i < _wayPointsCount; i++) { if (_wayPoints[i].x < 0 || - _wayPoints[i].x >= kMapWidth || - _wayPoints[i].y < 0 || _wayPoints[i].y >= kMapHeight) + _wayPoints[i].x >= _mapWidth || + _wayPoints[i].y < 0 || _wayPoints[i].y >= _mapHeight) return -1; tmp = ABS(x - _wayPoints[i].x) + ABS(y - _wayPoints[i].y); @@ -243,26 +248,24 @@ int16 Map::findNearestWayPoint(int16 x, int16 y) { return lnearestWayPoint; } -void Map::findNearestToGob(void) { - int16 wayPoint = findNearestWayPoint(_curGoblinX, _curGoblinY); - - if (wayPoint != -1) - _nearestWayPoint = wayPoint; -} - -void Map::findNearestToDest(void) { - int16 wayPoint = findNearestWayPoint(_destX, _destY); - - if (wayPoint != -1) - _nearestDest = wayPoint; -} - -int16 Map::checkDirectPath(int16 x0, int16 y0, int16 x1, int16 y1) { +int16 Map::checkDirectPath(int16 index, int16 x0, int16 y0, int16 x1, int16 y1) { + Mult::Mult_Object *obj = 0; uint16 dir; + if ((index >= 0) && (index < _vm->_mult->_objCount)) + obj = &_vm->_mult->_objects[index]; + while (1) { dir = getDirection(x0, y0, x1, y1); + if (obj) { + if (obj->nearestWayPoint < obj->nearestDest) + if (_wayPoints[obj->nearestWayPoint + 1].field_2 == 1) + return 3; + if (_wayPoints[obj->nearestDest - 1].field_2 == 1) + return 3; + } + if (x0 == x1 && y0 == y1) return 1; @@ -326,7 +329,7 @@ int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 nextLink = 1; if (nextLink != 0) { - if (checkDirectPath(x0, y0, x1, y1) == 1) + if (checkDirectPath(-1, x0, y0, x1, y1) == 1) return 1; nextLink = 0; @@ -345,7 +348,7 @@ int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 } if (i0 == i1 && _wayPoints[i0].x == x0 && _wayPoints[i0].y == y0) { - if (checkDirectPath(x0, y0, x1, y1) == 1) + if (checkDirectPath(-1, x0, y0, x1, y1) == 1) return 1; return 0; } @@ -393,24 +396,6 @@ int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 } } -void Map::optimizePoints(void) { - int16 i; - - if (_nearestWayPoint < _nearestDest) { - for (i = _nearestWayPoint; i <= _nearestDest; i++) { - if (checkDirectPath(_curGoblinX, _curGoblinY, - _wayPoints[i].x, _wayPoints[i].y) == 1) - _nearestWayPoint = i; - } - } else if (_nearestWayPoint > _nearestDest) { - for (i = _nearestWayPoint; i >= _nearestDest; i--) { - if (checkDirectPath(_curGoblinX, _curGoblinY, - _wayPoints[i].x, _wayPoints[i].y) == 1) - _nearestWayPoint = i; - } - } -} - void Map::loadDataFromAvo(char *dest, int16 size) { memcpy(dest, _avoDataPtr, size); _avoDataPtr += size; diff --git a/engines/gob/map.h b/engines/gob/map.h index 1b12f9280f..cb2dc625d1 100644 --- a/engines/gob/map.h +++ b/engines/gob/map.h @@ -23,6 +23,8 @@ #ifndef GOB_MAP_H #define GOB_MAP_H +#include "gob/util.h" + namespace Gob { // The same numeric values are also used for the arrow keys. @@ -39,16 +41,13 @@ public: kDirS = 0x5000, kDirSE = 0x5100 }; - enum { - kMapWidth = 26, - kMapHeight = 28 - }; #pragma START_PACK_STRUCTS struct Point { int16 x; int16 y; + int16 field_2; // Gob2 } GCC_PACK; #define szMap_ItemPos 3 @@ -61,13 +60,22 @@ public: #pragma END_PACK_STRUCTS - int8 _passMap[kMapHeight][kMapWidth]; // [y][x] - int16 _itemsMap[kMapHeight][kMapWidth]; // [y][x] - Point _wayPoints[40]; + int16 _mapWidth; + int16 _mapHeight; + int16 _screenWidth; + int16 _tilesWidth; + int16 _tilesHeight; + int16 _passWidth; + bool _bigTiles; + + int8 *_passMap; // [y * _mapWidth + x], getPass(x, y); + int16 **_itemsMap; // [y][x] + int16 _wayPointsCount; + Point *_wayPoints; int16 _nearestWayPoint; int16 _nearestDest; - int16 _curGoblinX; + int16 _curGoblinX; int16 _curGoblinY; int16 _destX; int16 _destY; @@ -79,16 +87,19 @@ public: void placeItem(int16 x, int16 y, int16 id); int16 getDirection(int16 x0, int16 y0, int16 x1, int16 y1); - void findNearestToGob(void); - void findNearestToDest(void); - int16 checkDirectPath(int16 x0, int16 y0, int16 x1, int16 y1); + int16 checkDirectPath(int16 index, int16 x0, int16 y0, int16 x1, int16 y1); int16 checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 i1); - void optimizePoints(void); void loadItemToObject(void); void loadDataFromAvo(char *dest, int16 size); void loadMapsInitGobs(void); + virtual int8 getPass(int x, int y, int heightOff = -1) = 0; + virtual void setPass(int x, int y, int8 pass, int heightOff = -1) = 0; + virtual void loadMapObjects(char *avjFile) = 0; + virtual void findNearestToGob(int16 index) = 0; + virtual void findNearestToDest(int16 index) = 0; + virtual void optimizePoints(int16 index, int16 x, int16 y) = 0; Map(GobEngine *vm); virtual ~Map() {}; @@ -104,14 +115,40 @@ protected: class Map_v1 : public Map { public: virtual void loadMapObjects(char *avjFile); + virtual void optimizePoints(int16 index, int16 x, int16 y); + virtual void findNearestToGob(int16 index); + virtual void findNearestToDest(int16 index); + + virtual inline int8 getPass(int x, int y, int heightOff = -1) { + return _passMap[y * _mapWidth + x]; + } + + virtual inline void setPass(int x, int y, int8 pass, int heightOff = -1) { + _passMap[y * _mapWidth + x] = pass; + } Map_v1(GobEngine *vm); - virtual ~Map_v1() {}; + virtual ~Map_v1(); }; class Map_v2 : public Map_v1 { public: virtual void loadMapObjects(char *avjFile); + virtual void optimizePoints(int16 index, int16 x, int16 y); + virtual void findNearestToGob(int16 index); + virtual void findNearestToDest(int16 index); + + virtual inline int8 getPass(int x, int y, int heightOff = -1) { + if (heightOff == -1) + heightOff = _passWidth; + return _vm->_util->readVariableByte((char *) (_passMap + y * heightOff + x)); + } + + virtual inline void setPass(int x, int y, int8 pass, int heightOff = -1) { + if (heightOff == -1) + heightOff = _passWidth; + _vm->_util->writeVariableByte((char *) (_passMap + y * heightOff + x) , pass); + } Map_v2(GobEngine *vm); virtual ~Map_v2() {}; diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp index 4e9859b89f..7b0da03f51 100644 --- a/engines/gob/map_v1.cpp +++ b/engines/gob/map_v1.cpp @@ -29,10 +29,39 @@ #include "gob/dataio.h" #include "gob/goblin.h" #include "gob/sound.h" +#include "gob/scenery.h" +#include "gob/mult.h" namespace Gob { Map_v1::Map_v1(GobEngine *vm) : Map(vm) { + int i; + int j; + + _mapWidth = 26; + _mapHeight = 28; + + _passMap = new int8[_mapHeight * _mapWidth]; + _itemsMap = new int16*[_mapHeight]; + for (i = 0; i < _mapHeight; i++) { + _itemsMap[i] = new int16[_mapWidth]; + for (j = 0; j < _mapWidth; j++) { + setPass(j, i, 0); + _itemsMap[i][j] = 0; + } + } + + _wayPointsCount = 40; + _wayPoints = new Point[40]; + for (i = 0; i < 40; i++) { + _wayPoints[i].x = 0; + _wayPoints[i].y = 0; + _wayPoints[i].field_2 = 0; + } +} + +Map_v1::~Map_v1() { + delete[] _passMap; } void Map_v1::loadMapObjects(char *avjFile) { @@ -66,10 +95,10 @@ void Map_v1::loadMapObjects(char *avjFile) { _vm->_dataio->closeData(handle); _avoDataPtr = _vm->_dataio->getData(avoName); dataBuf = _avoDataPtr; - loadDataFromAvo((char *)_passMap, kMapHeight * kMapWidth); + loadDataFromAvo((char *)_passMap, _mapHeight * _mapWidth); - for (y = 0; y < kMapHeight; y++) { - for (x = 0; x < kMapWidth; x++) { + for (y = 0; y < _mapHeight; y++) { + for (x = 0; x < _mapWidth; x++) { loadDataFromAvo(&item, 1); _itemsMap[y][x] = item; } @@ -343,4 +372,36 @@ void Map_v1::loadMapObjects(char *avjFile) { } } +void Map_v1::optimizePoints(int16 index, int16 x, int16 y) { + int16 i; + + if (_nearestWayPoint < _nearestDest) { + for (i = _nearestWayPoint; i <= _nearestDest; i++) { + if (checkDirectPath(-1, _curGoblinX, _curGoblinY, + _wayPoints[i].x, _wayPoints[i].y) == 1) + _nearestWayPoint = i; + } + } else if (_nearestWayPoint > _nearestDest) { + for (i = _nearestWayPoint; i >= _nearestDest; i--) { + if (checkDirectPath(-1, _curGoblinX, _curGoblinY, + _wayPoints[i].x, _wayPoints[i].y) == 1) + _nearestWayPoint = i; + } + } +} + +void Map_v1::findNearestToGob(int16 index) { + int16 wayPoint = findNearestWayPoint(_curGoblinX, _curGoblinY); + + if (wayPoint != -1) + _nearestWayPoint = wayPoint; +} + +void Map_v1::findNearestToDest(int16 index) { + int16 wayPoint = findNearestWayPoint(_destX, _destY); + + if (wayPoint != -1) + _nearestDest = wayPoint; +} + } // End of namespace Gob diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp index d8ef031cc9..6558cd27d9 100644 --- a/engines/gob/map_v2.cpp +++ b/engines/gob/map_v2.cpp @@ -33,6 +33,7 @@ #include "gob/game.h" #include "gob/parse.h" #include "gob/mult.h" +#include "gob/scenery.h" namespace Gob { @@ -43,11 +44,11 @@ void Map_v2::loadMapObjects(char *avjFile) { int i; int j; int k; + uint8 wayPointsCount; int16 var; int16 id; - int16 numChunks; - int16 chunkLength; - int16 offVar; + int16 mapHeight; + int16 mapWidth; int16 offData; int16 tmp; int16 numData; @@ -61,17 +62,13 @@ void Map_v2::loadMapObjects(char *avjFile) { char statesMask[102]; Goblin::Gob2_State *statesPtr; - uint8 var_9; - uint8 byte_2F2AA; - byte *off_2F2AB; - var = _vm->_parse->parseVarIndex(); variables = _vm->_global->_inter_variables + var; id = _vm->_inter->load16(); if (id == -1) { - _vm->_goblin->_dword_2F2A4 = _vm->_global->_inter_variables + var; + _passMap = (int8 *)(_vm->_global->_inter_variables + var); return; } @@ -79,51 +76,53 @@ void Map_v2::loadMapObjects(char *avjFile) { dataPtr = extData; if (*dataPtr++ == 3) { - _vm->_mult->_word_2F22A = 640; - _vm->_mult->_word_2CC84 = 65; + _vm->_map->_screenWidth = 640; + _vm->_map->_passWidth = 65; } else { - _vm->_mult->_word_2F22A = 320; - _vm->_mult->_word_2CC84 = 40; + _vm->_map->_screenWidth = 320; + _vm->_map->_passWidth = 40; } - byte_2F2AA = *dataPtr++; - _vm->_mult->_word_2F2B1 = READ_LE_UINT16(dataPtr); + _wayPointsCount = *dataPtr++; + _vm->_map->_tilesWidth = READ_LE_UINT16(dataPtr); dataPtr += 2; - _vm->_mult->_word_2F2AF = READ_LE_UINT16(dataPtr); + _vm->_map->_tilesHeight = READ_LE_UINT16(dataPtr); dataPtr += 2; - _vm->_mult->_word_2CC86 = _vm->_mult->_word_2F2AF & 0xFF00 ? 0 : 1; - _vm->_mult->_word_2F2AF &= 0xFF; + _vm->_map->_bigTiles = !(_vm->_map->_tilesHeight & 0xFF00); + _vm->_map->_tilesHeight &= 0xFF; - dataPtrBak = dataPtr; - dataPtr += (_vm->_mult->_word_2F22A / _vm->_mult->_word_2F2B1) * (200 / _vm->_mult->_word_2F2AF); + _mapWidth = _vm->_map->_screenWidth / _vm->_map->_tilesWidth; + _mapHeight = 200 / _vm->_map->_tilesHeight; - if (*extData == 1) { - byte_2F2AA = 40; - var_9 = 40; - } else { - if (byte_2F2AA == 0) { - var_9 = 1; - } else { - var_9 = byte_2F2AA; - } + dataPtrBak = dataPtr; + dataPtr += _mapWidth * _mapHeight; + + if (*extData == 1) + wayPointsCount = _wayPointsCount = 40; + else + wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount; + + _wayPoints = new Point[wayPointsCount]; + for (i = 0; i < wayPointsCount; i++) { + _wayPoints[i].x = -1; + _wayPoints[i].y = -1; + _wayPoints[i].field_2 = -1; + } + for (i = 0; i < _wayPointsCount; i++) { + _wayPoints[i].x = *dataPtr++; + _wayPoints[i].y = *dataPtr++; + _wayPoints[i].field_2 = *dataPtr++; } - - off_2F2AB = new byte[3 * var_9]; - memset(off_2F2AB, -1, 3 * var_9); - memcpy(off_2F2AB, dataPtr, 3 * byte_2F2AA); - dataPtr += 3 * byte_2F2AA; // In the original asm, this writes byte-wise into the variables-array if (variables != _vm->_global->_inter_variables) { - _vm->_goblin->_dword_2F2A4 = variables; - numChunks = 200 / _vm->_mult->_word_2F2AF; - chunkLength = _vm->_mult->_word_2F22A / _vm->_mult->_word_2F2B1; - for (i = 0; i < numChunks; i++) { - offVar = _vm->_mult->_word_2CC84 * i; - offData = (chunkLength * i); - for (j = 0; j < chunkLength; j++) { - _vm->_util->writeVariableByte(_vm->_goblin->_dword_2F2A4 + offVar + j, - *(dataPtrBak + offData + j)); + _passMap = (int8 *) variables; + mapHeight = 200 / _vm->_map->_tilesHeight; + mapWidth = _vm->_map->_screenWidth / _vm->_map->_tilesWidth; + for (i = 0; i < mapHeight; i++) { + offData = (mapWidth * i); + for (j = 0; j < mapWidth; j++) { + setPass(j, i, *(dataPtrBak + offData + j), _vm->_map->_passWidth); } } } @@ -189,4 +188,42 @@ void Map_v2::loadMapObjects(char *avjFile) { _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1); } +void Map_v2::findNearestToGob(int16 index) { + Mult::Mult_Object *obj = &_vm->_mult->_objects[index]; + int16 wayPoint = findNearestWayPoint(obj->goblinX, obj->goblinY); + + if (wayPoint != -1) + obj->nearestWayPoint = wayPoint; +} + +void Map_v2::findNearestToDest(int16 index) { + Mult::Mult_Object *obj = &_vm->_mult->_objects[index]; + int16 wayPoint = findNearestWayPoint(obj->destX, obj->destY); + + if (wayPoint != -1) + obj->nearestDest = wayPoint; +} + +void Map_v2::optimizePoints(int16 index, int16 x, int16 y) { + Mult::Mult_Object *obj; + int i; + + int16 var_2; + + obj = &_vm->_mult->_objects[index]; + + if (obj->nearestWayPoint < obj->nearestDest) { + var_2 = obj->nearestWayPoint; + for (i = obj->nearestWayPoint; i <= obj->nearestDest; i++) { + if (checkDirectPath(index, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1) + obj->nearestWayPoint = i; + } + } else { + for (i = obj->nearestWayPoint; i >= obj->nearestDest && _wayPoints[i].field_2 != 1; i--) { + if (checkDirectPath(index, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1) + obj->nearestWayPoint = i; + } + } +} + } // End of namespace Gob diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 9a8ba2c0ea..4841db606d 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -35,6 +35,8 @@ MODULE_OBJS := \ parse_v1.o \ parse_v2.o \ scenery.o \ + scenery_v1.o \ + scenery_v2.o \ sound.o \ timer.o \ util.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 3960cb2b6a..93233bc35c 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -120,12 +120,6 @@ Mult::Mult(GobEngine *vm) : _vm(vm) { } _orderArray = 0; - warning("GOB2 Stub! _word_2F2B1, _word_2F2AF, _word_2CC86, _word_2F22A, _word_2CC84"); - _word_2F2B1 = 0; - _word_2F2AF = 0; - _word_2CC86 = 0; - _word_2F22A = 0; - _word_2CC84 = 0; } void Mult::interGetObjAnimSize(void) { diff --git a/engines/gob/mult.h b/engines/gob/mult.h index d09260fa25..9afa65b447 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -23,6 +23,7 @@ #ifndef GOB_MULT_H #define GOB_MULT_H +#include "gob/gob.h" #include "gob/sound.h" #include "gob/video.h" #include "gob/goblin.h" @@ -77,10 +78,12 @@ public: int16 somethingBottom; // New in GOB2 int8 goblinX; // New in GOB2 int8 goblinY; // New in GOB2 - int8 field_1C; // New in GOB2 - int8 field_1D; // New in GOB2 - int8 field_1E; // New in GOB2 - int8 field_1F; // New in GOB2 + int8 destX; // New in GOB2 + int8 destY; // New in GOB2 + int8 gobDestX; // New in GOB2 + int8 gobDestY; // New in GOB2 + int8 nearestWayPoint; // New in GOB2 + int8 nearestDest; // New in GOB2 Goblin::Gob2_State **goblinStates; // New in GOB2 }; @@ -202,12 +205,6 @@ public: int8 *_orderArray; - uint16 _word_2F2B1; - uint16 _word_2F2AF; - uint16 _word_2CC86; - uint16 _word_2F22A; - uint16 _word_2CC84; - void zeroMultData(void); void checkFreeMult(void); void interGetObjAnimSize(void); diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 032f1702eb..79269a1100 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -816,6 +816,7 @@ char Mult_v2::doSoundAnim(char stop, int16 frame) { return stop; } +// "deplaceheros" void Mult_v2::sub_62DD(int16 index) { Mult_Object *animObj; Mult_AnimKey *animKey; @@ -952,6 +953,7 @@ void Mult_v2::sub_62DD(int16 index) { WRITE_VAR(18 + index, frame); } +// "avancerperso" void Mult_v2::sub_6A35(void) { int i; int j; @@ -1273,7 +1275,6 @@ void Mult_v2::animate(void) { void Mult_v2::playSound(Snd::SoundDesc * soundDesc, int16 repCount, int16 freq, int16 channel) { - warning("PlaySound(%p, %d, %d, %d), %d", (void *) soundDesc, repCount, freq, channel, soundDesc->frequency); if (soundDesc->frequency >= 0) { if (soundDesc->frequency == freq) _vm->_snd->playSample(soundDesc, repCount, -channel); @@ -1292,13 +1293,9 @@ void Mult_v2::freeMultKeys(void) { char animCount; char staticCount; - warning("GOB2 Stub! Mult_v2::freeMultKeys()"); - if (_multData2 == 0) return; - // loc_7323 - staticCount = (_multData2->staticCount + 1) && 0x7F; animCount = _multData2->animCount + 1; diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp index 52b37e7206..a65aaeb0d1 100644 --- a/engines/gob/music.cpp +++ b/engines/gob/music.cpp @@ -1,6 +1,6 @@ /* ScummVM - Scumm Interpreter * Copyright (C) 2006 The ScummVM project - * Original ADL-Player source Copyright (C) 2004 by Dorian Gray + * Original ADL-Player source Copyright (C) 2004 by Patrick Combet aka Dorian Gray * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -337,6 +337,12 @@ void Music::pollMusic(void) { setVolume(channel, *(_playPos++)); setKey(channel, note, true, false); break; + case 0x10: + warning("GOB2 Stub! ADL command 0x10"); + break; + case 0x50: + warning("GOB2 Stub! ADL command 0x50"); + break; // Note on case 0x90: note = *(_playPos++); @@ -364,17 +370,23 @@ void Music::pollMusic(void) { break; // Special case 0xF0: + switch (instr & 0x0F) { + case 0xF: // End instruction + _ended = true; + break; + default: + warning("Unknown special command in ADL, stopping playback: %X", instr & 0x0F); + _repCount = 0; + _ended = true; + break; + } break; default: - warning("Unknown command in ADL, stopping playback"); + warning("Unknown command in ADL, stopping playback: %X", instr & 0xF0); _repCount = 0; _ended = true; break; } - // End instruction - if (instr == 0xFF) { - _ended = true; - } // Temporization tempo = *(_playPos++); diff --git a/engines/gob/music.h b/engines/gob/music.h index d736bc9ff5..0079c8f8a2 100644 --- a/engines/gob/music.h +++ b/engines/gob/music.h @@ -1,6 +1,6 @@ /* ScummVM - Scumm Interpreter * Copyright (C) 2006 The ScummVM project - * Original ADL-Player source Copyright (C) 2004 by Dorian Gray + * Original ADL-Player source Copyright (C) 2004 by Patrick Combet aka Dorian Gray * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,6 +25,7 @@ #define GOB_MUSIC_H #include "sound/audiostream.h" +#include "sound/mixer.h" #include "sound/fmopl.h" #include "common/mutex.h" @@ -37,20 +38,20 @@ class GobEngine; class Music : public Audio::AudioStream { public: Music(GobEngine *vm); - ~Music(); + virtual ~Music(); void lock() { _mutex.lock(); } void unlock() { _mutex.unlock(); } bool playing() { return _playing; } bool getRepeating(void) { return _repCount != 0; } void setRepeating (int32 repCount) { _repCount = repCount; } - void startPlay(void); - void stopPlay(void) { _mutex.lock(); _playing = false; _mutex.unlock(); } - void playTrack(const char *trackname); - void playBgMusic(void); - bool loadMusic(const char *filename); - void loadFromMemory(byte *data); - void unloadMusic(void); + virtual void startPlay(void); + virtual void stopPlay(void) { _mutex.lock(); _playing = false; _mutex.unlock(); } + virtual void playTrack(const char *trackname); + virtual void playBgMusic(void); + virtual bool loadMusic(const char *filename); + virtual void loadFromMemory(byte *data); + virtual void unloadMusic(void); // AudioStream API int readBuffer(int16 *buffer, const int numSamples) { @@ -96,6 +97,24 @@ protected: void pollMusic(void); }; +class Music_Dummy: public Music { +public: + Music_Dummy(GobEngine *vm) : Music(vm) { + _vm->_mixer->setupPremix(0); + OPLDestroy(_opl); + } + + virtual void startPlay(void) {}; + virtual void stopPlay(void) {}; + virtual void playTrack(const char *trackname) {}; + virtual void playBgMusic(void) {}; + virtual bool loadMusic(const char *filename) { return true; }; + virtual void loadFromMemory(byte *data) {}; + virtual void unloadMusic(void) {}; + + virtual ~Music_Dummy() {}; +}; + } // End of namespace Gob #endif diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index 7079759a8e..328245e69e 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -32,7 +32,6 @@ #include "gob/game.h" #include "gob/global.h" #include "gob/util.h" -#include "gob/anim.h" #include "gob/parse.h" #include "gob/cdrom.h" @@ -489,212 +488,6 @@ int16 Scenery::loadAnim(char search) { return sceneryIndex + 100; } -// flags & 1 - do capture all area animation is occupying -// flags & 4 == 0 - calculate animation final size -// flags & 2 != 0 - don't check with "toRedraw"'s -// flags & 4 != 0 - checkk view toRedraw -void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, - int16 drawDeltaX, int16 drawDeltaY, char doDraw) { - AnimLayer *layerPtr; - PieceDesc **pictPtr; - AnimFramePiece *framePtr; - - uint16 pieceIndex; - uint16 pictIndex; - - int16 left; - int16 right; - int16 top; - int16 bottom; - - byte highX; - byte highY; - - int16 i; - int16 transp; - - int16 destX; - int16 destY; - - if (layer >= _animations[animation].layersCount) - return; - - layerPtr = _animations[animation].layers[layer]; - - if (frame >= layerPtr->framesCount) - return; - - if (flags & 1) // Do capture - { - updateAnim(layer, frame, animation, 0, drawDeltaX, - drawDeltaY, 0); - - if (_toRedrawLeft == -12345) // Some magic number? - return; - - _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, - _toRedrawRight - _toRedrawLeft + 1, - _toRedrawBottom - _toRedrawTop + 1); - - *_pCaptureCounter = *_pCaptureCounter + 1; - } - pictPtr = _animations[animation].pieces; - framePtr = layerPtr->frames; - - for (i = 0; i < frame; i++, framePtr++) { - while (framePtr->notFinal == 1) - framePtr++; - } - - if ((flags & 4) == 0) { - _toRedrawLeft = -12345; - } else { - _toRedrawLeft = - MAX(_toRedrawLeft, _vm->_anim->_areaLeft); - _toRedrawTop = - MAX(_toRedrawTop, _vm->_anim->_areaTop); - _toRedrawRight = - MIN(_toRedrawRight, - (int16)(_vm->_anim->_areaLeft + _vm->_anim->_areaWidth - 1)); - _toRedrawBottom = - MIN(_toRedrawBottom, - (int16)(_vm->_anim->_areaTop + _vm->_anim->_areaHeight - 1)); - } - - transp = layerPtr->transp ? 3 : 0; - - framePtr--; - do { - framePtr++; - - pieceIndex = framePtr->pieceIndex; - pictIndex = framePtr->pictIndex; - - destX = framePtr->destX; - destY = framePtr->destY; - - highX = pictIndex & 0xc0; - highY = pictIndex & 0x30; - highX >>= 6; - highY >>= 4; - if (destX >= 0) - destX += ((uint16)highX) << 7; - else - destX -= ((uint16)highX) << 7; - - if (destY >= 0) - destY += ((uint16)highY) << 7; - else - destY -= ((uint16)highY) << 7; - - if (drawDeltaX == 1000) - destX += layerPtr->posX; - else - destX += drawDeltaX; - - if (drawDeltaY == 1000) - destY += layerPtr->posY; - else - destY += drawDeltaY; - - pictIndex = (pictIndex & 15) - 1; - - left = FROM_LE_16(pictPtr[pictIndex][pieceIndex].left); - right = FROM_LE_16(pictPtr[pictIndex][pieceIndex].right); - top = FROM_LE_16(pictPtr[pictIndex][pieceIndex].top); - bottom = FROM_LE_16(pictPtr[pictIndex][pieceIndex].bottom); - - if (flags & 2) { - if (destX < _vm->_anim->_areaLeft) { - left += _vm->_anim->_areaLeft - destX; - destX = _vm->_anim->_areaLeft; - } - - if (left <= right - && destX + right - left >= - _vm->_anim->_areaLeft + _vm->_anim->_areaWidth) - right -= - (destX + right - left) - - (_vm->_anim->_areaLeft + _vm->_anim->_areaWidth) + - 1; - - if (destY < _vm->_anim->_areaTop) { - top += _vm->_anim->_areaTop - destY; - destY = _vm->_anim->_areaTop; - } - - if (top <= bottom - && destY + bottom - top >= - _vm->_anim->_areaTop + _vm->_anim->_areaHeight) - bottom -= - (destY + bottom - top) - - (_vm->_anim->_areaTop + _vm->_anim->_areaHeight) + - 1; - - } else if (flags & 4) { - if (destX < _toRedrawLeft) { - left += _toRedrawLeft - destX; - destX = _toRedrawLeft; - } - - if (left <= right - && destX + right - left > _toRedrawRight) - right -= - destX + right - left - _toRedrawRight; - - if (destY < _toRedrawTop) { - top += _toRedrawTop - destY; - destY = _toRedrawTop; - } - - if (top <= bottom - && destY + bottom - top > _toRedrawBottom) - bottom -= - destY + bottom - top - _toRedrawBottom; - } - - if (left > right || top > bottom) - continue; - - if (doDraw) { - _vm->_draw->_sourceSurface = - _animPictToSprite[animation * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; - - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_destSpriteX = destX; - _vm->_draw->_destSpriteY = destY; - _vm->_draw->_transparency = transp; - _vm->_draw->spriteOperation(DRAW_BLITSURF); - } - - if ((flags & 4) == 0) { - if (_toRedrawLeft == -12345) { - _toRedrawLeft = destX; - _animLeft = destX; - _toRedrawTop = destY; - _animTop = destY; - _toRedrawRight = destX + right - left; - _toRedrawBottom = destY + bottom - top; - } else { - _toRedrawLeft = - MIN(_toRedrawLeft, destX); - _toRedrawTop = - MIN(_toRedrawTop, destY); - _toRedrawRight = - MAX(_toRedrawRight, - (int16)(destX + right - left)); - _toRedrawBottom = - MAX(_toRedrawBottom, - (int16)(destY + bottom - top)); - } - } - } while (framePtr->notFinal == 1); -} - void Scenery::freeAnim(int16 animation) { int16 i; int16 spr; @@ -729,23 +522,6 @@ void Scenery::freeAnim(int16 animation) { _animPictCount[animation] = 0; } -void Scenery::interUpdateAnim(void) { - int16 deltaX; - int16 deltaY; - int16 flags; - int16 frame; - int16 layer; - int16 animation; - - _vm->_inter->evalExpr(&deltaX); - _vm->_inter->evalExpr(&deltaY); - _vm->_inter->evalExpr(&animation); - _vm->_inter->evalExpr(&layer); - _vm->_inter->evalExpr(&frame); - flags = _vm->_inter->load16(); - updateAnim(layer, frame, animation, flags, deltaX, deltaY, 1); -} - void Scenery::interStoreParams(void) { AnimLayer *layerPtr; int16 animation; diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h index d361d24eaa..9e36556aef 100644 --- a/engines/gob/scenery.h +++ b/engines/gob/scenery.h @@ -119,6 +119,8 @@ public: int16 _animTop; int16 _animLeft; + int16 _animBottom; + int16 _animRight; int16 *_pCaptureCounter; @@ -129,18 +131,37 @@ public: void renderStatic(int16 scenery, int16 layer); void updateStatic(int16 orderFrom); int16 loadAnim(char search); - void updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, - int16 drawDeltaX, int16 drawDeltaY, char doDraw); void freeAnim(int16 animation); - void interUpdateAnim(void); void interStoreParams(void); + virtual void updateAnim(int16 layer, int16 frame, int16 animation, + int16 flags, int16 drawDeltaX, int16 drawDeltaY, char doDraw) = 0; + Scenery(GobEngine *vm); + virtual ~Scenery() {}; protected: GobEngine *_vm; }; +class Scenery_v1 : public Scenery { +public: + virtual void updateAnim(int16 layer, int16 frame, int16 animation, + int16 flags, int16 drawDeltaX, int16 drawDeltaY, char doDraw); + + Scenery_v1(GobEngine *vm); + virtual ~Scenery_v1() {}; +}; + +class Scenery_v2 : public Scenery_v1 { +public: + virtual void updateAnim(int16 layer, int16 frame, int16 animation, + int16 flags, int16 drawDeltaX, int16 drawDeltaY, char doDraw); + + Scenery_v2(GobEngine *vm); + virtual ~Scenery_v2() {}; +}; + } // End of namespace Gob #endif /* __SCENERY_H */ diff --git a/engines/gob/scenery_v1.cpp b/engines/gob/scenery_v1.cpp new file mode 100644 index 0000000000..7904f0e3c4 --- /dev/null +++ b/engines/gob/scenery_v1.cpp @@ -0,0 +1,244 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * 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/scenery.h" +#include "gob/anim.h" +#include "gob/draw.h" +#include "gob/game.h" + +namespace Gob { + +Scenery_v1::Scenery_v1(GobEngine *vm) : Scenery(vm) { +} + +// flags & 1 - do capture all area animation is occupying +// flags & 4 == 0 - calculate animation final size +// flags & 2 != 0 - don't check with "toRedraw"'s +// flags & 4 != 0 - checkk view toRedraw +void Scenery_v1::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, + int16 drawDeltaX, int16 drawDeltaY, char doDraw) { + AnimLayer *layerPtr; + PieceDesc **pictPtr; + AnimFramePiece *framePtr; + + uint16 pieceIndex; + uint16 pictIndex; + + int16 left; + int16 right; + int16 top; + int16 bottom; + + byte highX; + byte highY; + + int16 i; + int16 transp; + + int16 destX; + int16 destY; + + if (layer >= _animations[animation].layersCount) + return; + + layerPtr = _animations[animation].layers[layer]; + + if (frame >= layerPtr->framesCount) + return; + + if (flags & 1) // Do capture + { + updateAnim(layer, frame, animation, 0, drawDeltaX, + drawDeltaY, 0); + + if (_toRedrawLeft == -12345) // Some magic number? + return; + + _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); + + *_pCaptureCounter = *_pCaptureCounter + 1; + } + pictPtr = _animations[animation].pieces; + framePtr = layerPtr->frames; + + for (i = 0; i < frame; i++, framePtr++) { + while (framePtr->notFinal == 1) + framePtr++; + } + + if ((flags & 4) == 0) { + _toRedrawLeft = -12345; + } else { + _toRedrawLeft = + MAX(_toRedrawLeft, _vm->_anim->_areaLeft); + _toRedrawTop = + MAX(_toRedrawTop, _vm->_anim->_areaTop); + _toRedrawRight = + MIN(_toRedrawRight, + (int16)(_vm->_anim->_areaLeft + _vm->_anim->_areaWidth - 1)); + _toRedrawBottom = + MIN(_toRedrawBottom, + (int16)(_vm->_anim->_areaTop + _vm->_anim->_areaHeight - 1)); + } + + transp = layerPtr->transp ? 3 : 0; + + framePtr--; + do { + framePtr++; + + pieceIndex = framePtr->pieceIndex; + pictIndex = framePtr->pictIndex; + + destX = framePtr->destX; + destY = framePtr->destY; + + highX = pictIndex & 0xc0; + highY = pictIndex & 0x30; + highX >>= 6; + highY >>= 4; + if (destX >= 0) + destX += ((uint16)highX) << 7; + else + destX -= ((uint16)highX) << 7; + + if (destY >= 0) + destY += ((uint16)highY) << 7; + else + destY -= ((uint16)highY) << 7; + + if (drawDeltaX == 1000) + destX += layerPtr->posX; + else + destX += drawDeltaX; + + if (drawDeltaY == 1000) + destY += layerPtr->posY; + else + destY += drawDeltaY; + + pictIndex = (pictIndex & 15) - 1; + + left = FROM_LE_16(pictPtr[pictIndex][pieceIndex].left); + right = FROM_LE_16(pictPtr[pictIndex][pieceIndex].right); + top = FROM_LE_16(pictPtr[pictIndex][pieceIndex].top); + bottom = FROM_LE_16(pictPtr[pictIndex][pieceIndex].bottom); + + if (flags & 2) { + if (destX < _vm->_anim->_areaLeft) { + left += _vm->_anim->_areaLeft - destX; + destX = _vm->_anim->_areaLeft; + } + + if (left <= right + && destX + right - left >= + _vm->_anim->_areaLeft + _vm->_anim->_areaWidth) + right -= + (destX + right - left) - + (_vm->_anim->_areaLeft + _vm->_anim->_areaWidth) + + 1; + + if (destY < _vm->_anim->_areaTop) { + top += _vm->_anim->_areaTop - destY; + destY = _vm->_anim->_areaTop; + } + + if (top <= bottom + && destY + bottom - top >= + _vm->_anim->_areaTop + _vm->_anim->_areaHeight) + bottom -= + (destY + bottom - top) - + (_vm->_anim->_areaTop + _vm->_anim->_areaHeight) + + 1; + + } else if (flags & 4) { + if (destX < _toRedrawLeft) { + left += _toRedrawLeft - destX; + destX = _toRedrawLeft; + } + + if (left <= right + && destX + right - left > _toRedrawRight) + right -= + destX + right - left - _toRedrawRight; + + if (destY < _toRedrawTop) { + top += _toRedrawTop - destY; + destY = _toRedrawTop; + } + + if (top <= bottom + && destY + bottom - top > _toRedrawBottom) + bottom -= + destY + bottom - top - _toRedrawBottom; + } + + if (left > right || top > bottom) + continue; + + if (doDraw) { + _vm->_draw->_sourceSurface = + _animPictToSprite[animation * 7 + pictIndex]; + _vm->_draw->_destSurface = 21; + + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_destSpriteX = destX; + _vm->_draw->_destSpriteY = destY; + _vm->_draw->_transparency = transp; + _vm->_draw->spriteOperation(DRAW_BLITSURF); + } + + if ((flags & 4) == 0) { + if (_toRedrawLeft == -12345) { + _toRedrawLeft = destX; + _animLeft = destX; + _toRedrawTop = destY; + _animTop = destY; + _toRedrawRight = destX + right - left; + _toRedrawBottom = destY + bottom - top; + } else { + _toRedrawLeft = + MIN(_toRedrawLeft, destX); + _toRedrawTop = + MIN(_toRedrawTop, destY); + _toRedrawRight = + MAX(_toRedrawRight, + (int16)(destX + right - left)); + _toRedrawBottom = + MAX(_toRedrawBottom, + (int16)(destY + bottom - top)); + } + } + } while (framePtr->notFinal == 1); +} + +} // End of namespace Gob diff --git a/engines/gob/scenery_v2.cpp b/engines/gob/scenery_v2.cpp new file mode 100644 index 0000000000..4c523522ed --- /dev/null +++ b/engines/gob/scenery_v2.cpp @@ -0,0 +1,251 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * 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/scenery.h" +#include "gob/anim.h" +#include "gob/draw.h" +#include "gob/game.h" + +namespace Gob { + +Scenery_v2::Scenery_v2(GobEngine *vm) : Scenery_v1(vm) { +} + +// flags & 1 - do capture all area animation is occupying +// flags & 4 == 0 - calculate animation final size +// flags & 2 != 0 - don't check with "toRedraw"'s +// flags & 4 != 0 - checkk view toRedraw +void Scenery_v2::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, + int16 drawDeltaX, int16 drawDeltaY, char doDraw) { + AnimLayer *layerPtr; + PieceDesc **pictPtr; + AnimFramePiece *framePtr; + + uint16 pieceIndex; + uint16 pictIndex; + + int16 left; + int16 right; + int16 top; + int16 bottom; + + byte highX; + byte highY; + + int16 i; + int16 transp; + + int16 destX; + int16 destY; + + if ((_animPictCount[animation] == 0) || (layer < 0)) + return; + if (layer >= _animations[animation].layersCount) + return; + + layerPtr = _animations[animation].layers[layer]; + + if (frame >= layerPtr->framesCount) + return; + + if (flags & 1) // Do capture + { + updateAnim(layer, frame, animation, 0, drawDeltaX, + drawDeltaY, 0); + + if (_toRedrawLeft == -12345) // Some magic number? + return; + + _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); + + *_pCaptureCounter = *_pCaptureCounter + 1; + } + + pictPtr = _animations[animation].pieces; + framePtr = layerPtr->frames; + + for (i = 0; i < frame; i++, framePtr++) { + while (framePtr->notFinal == 1) + framePtr++; + } + + if ((flags & 4) == 0) { + _toRedrawLeft = -12345; + } else { + _toRedrawLeft = + MAX(_toRedrawLeft, _vm->_anim->_areaLeft); + _toRedrawTop = + MAX(_toRedrawTop, _vm->_anim->_areaTop); + _toRedrawRight = + MIN(_toRedrawRight, + (int16)(_vm->_anim->_areaLeft + _vm->_anim->_areaWidth - 1)); + _toRedrawBottom = + MIN(_toRedrawBottom, + (int16)(_vm->_anim->_areaTop + _vm->_anim->_areaHeight - 1)); + } + + transp = layerPtr->transp ? 3 : 0; + + framePtr--; + do { + framePtr++; + + pieceIndex = framePtr->pieceIndex; + pictIndex = framePtr->pictIndex; + + destX = framePtr->destX; + destY = framePtr->destY; + + highX = pictIndex & 0xc0; + highY = pictIndex & 0x30; + highX >>= 6; + highY >>= 4; + if (destX >= 0) + destX += ((uint16)highX) << 7; + else + destX -= ((uint16)highX) << 7; + + if (destY >= 0) + destY += ((uint16)highY) << 7; + else + destY -= ((uint16)highY) << 7; + + if (drawDeltaX == 1000) + destX += layerPtr->posX; + else + destX += drawDeltaX; + + if (drawDeltaY == 1000) + destY += layerPtr->posY; + else + destY += drawDeltaY; + + pictIndex = (pictIndex & 15) - 1; + + left = FROM_LE_16(pictPtr[pictIndex][pieceIndex].left); + right = FROM_LE_16(pictPtr[pictIndex][pieceIndex].right); + top = FROM_LE_16(pictPtr[pictIndex][pieceIndex].top); + bottom = FROM_LE_16(pictPtr[pictIndex][pieceIndex].bottom); + + if (flags & 2) { + if (destX < _vm->_anim->_areaLeft) { + left += _vm->_anim->_areaLeft - destX; + destX = _vm->_anim->_areaLeft; + } + + if (left <= right + && destX + right - left >= + _vm->_anim->_areaLeft + _vm->_anim->_areaWidth) + right -= + (destX + right - left) - + (_vm->_anim->_areaLeft + _vm->_anim->_areaWidth) + + 1; + + if (destY < _vm->_anim->_areaTop) { + top += _vm->_anim->_areaTop - destY; + destY = _vm->_anim->_areaTop; + } + + if (top <= bottom + && destY + bottom - top >= + _vm->_anim->_areaTop + _vm->_anim->_areaHeight) + bottom -= + (destY + bottom - top) - + (_vm->_anim->_areaTop + _vm->_anim->_areaHeight) + + 1; + + } else if (flags & 4) { + if (destX < _toRedrawLeft) { + left += _toRedrawLeft - destX; + destX = _toRedrawLeft; + } + + if (left <= right + && destX + right - left > _toRedrawRight) + right -= + destX + right - left - _toRedrawRight; + + if (destY < _toRedrawTop) { + top += _toRedrawTop - destY; + destY = _toRedrawTop; + } + + if (top <= bottom + && destY + bottom - top > _toRedrawBottom) + bottom -= + destY + bottom - top - _toRedrawBottom; + } + + // --- + + if (left > right || top > bottom) + continue; + + if (doDraw) { + _vm->_draw->_sourceSurface = + _animPictToSprite[animation * 7 + pictIndex]; + _vm->_draw->_destSurface = 21; + + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_destSpriteX = destX; + _vm->_draw->_destSpriteY = destY; + _vm->_draw->_transparency = transp; + _vm->_draw->spriteOperation(DRAW_DRAWLETTER); + } + + if ((flags & 4) == 0) { + if (_toRedrawLeft == -12345) { + _toRedrawLeft = destX; + _animLeft = destX; + _toRedrawTop = destY; + _animTop = destY; + _toRedrawRight = destX + right - left; + _animRight = destX + right - left; + _toRedrawBottom = destY + bottom - top; + _animBottom = destY + bottom - top; + } else { + _toRedrawLeft = + MIN(_toRedrawLeft, destX); + _toRedrawTop = + MIN(_toRedrawTop, destY); + _toRedrawRight = + MAX(_toRedrawRight, + (int16)(destX + right - left)); + _toRedrawBottom = + MAX(_toRedrawBottom, + (int16)(destY + bottom - top)); + } + } + } while (framePtr->notFinal == 1); +} + +} // End of namespace Gob diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp index 6a7446d63d..0c1e612b9f 100644 --- a/engines/gob/sound.cpp +++ b/engines/gob/sound.cpp @@ -99,7 +99,7 @@ void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { frequency = sndDesc->frequency; if (frequency <= 0) { - warning("Attempted to play a sample with a frequency of %d", frequency); + warning("Attempted to play a sample with a frequency of %d (sndDesc->freq = %d)", frequency, sndDesc->frequency); return; } // assert(frequency > 0); diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index 64426c8fd5..f0caaf04a1 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -246,6 +246,7 @@ void Util::setFrameRate(int16 rate) { _vm->_global->_frameWaitTime = 1000 / rate; _vm->_global->_startFrameTime = getTimeKey(); + _vm->_game->_dword_2F2B6 = 0; } void Util::waitEndFrame() { @@ -256,12 +257,15 @@ void Util::waitEndFrame() { time = getTimeKey() - _vm->_global->_startFrameTime; if (time > 1000 || time < 0) { _vm->_global->_startFrameTime = getTimeKey(); + _vm->_game->_dword_2F2B6 = 0; return; } if (_vm->_global->_frameWaitTime - time > 0) { - delay(_vm->_global->_frameWaitTime - time); + _vm->_game->_dword_2F2B6 = 0; + delay(_vm->_global->_frameWaitTime - _vm->_game->_dword_2F2B6 - time); } _vm->_global->_startFrameTime = getTimeKey(); + _vm->_game->_dword_2F2B6 = time - _vm->_global->_frameWaitTime; } int16 joy_getState() { |