diff options
Diffstat (limited to 'engines/gob/mult_v1.cpp')
-rw-r--r-- | engines/gob/mult_v1.cpp | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index a35ca3f321..a3d1c82b66 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -30,6 +30,9 @@ #include "gob/scenery.h" #include "gob/global.h" #include "gob/inter.h" +#include "gob/anim.h" +#include "gob/draw.h" +#include "gob/palanim.h" namespace Gob { @@ -204,4 +207,702 @@ void Mult_v1::setMultData(uint16 multindex) { error("Switching mults not supported for Gob1"); } +void Mult_v1::playMult(int16 startFrame, int16 endFrame, char checkEscape, + char handleMouse) { + char stopNoClear; + char stop; + Mult_Object *multObj; + Mult_AnimData *animData; + + if (_multData == 0) + return; + + stopNoClear = 0; + _frame = startFrame; + if (endFrame == -1) + endFrame = 32767; + + if (_frame == -1) { + _doPalSubst = 0; + _palFadingRed = 0; + _palFadingGreen = 0; + _palFadingBlue = 0; + + _oldPalette = _vm->_global->_pPaletteDesc->vgaPal; + memcpy((char *)_palAnimPalette, (char *)_vm->_global->_pPaletteDesc->vgaPal, 768); + + if (_vm->_anim->_animSurf == 0) { + _vm->_util->setFrameRate(_frameRate); + _vm->_anim->_areaTop = 0; + _vm->_anim->_areaLeft = 0; + _vm->_anim->_areaWidth = 320; + _vm->_anim->_areaHeight = 200; + _objCount = 4; + + _objects = new Mult_Object[_objCount]; + _renderData = new int16[9 * _objCount]; + + _animArrayX = new int32[_objCount]; + _animArrayY = new int32[_objCount]; + + _animArrayData = new Mult_AnimData[_objCount]; + + for (_counter = 0; _counter < _objCount; _counter++) { + multObj = &_objects[_counter]; + + multObj->pPosX = (int32 *)&_animArrayX[_counter]; + multObj->pPosY = (int32 *)&_animArrayY[_counter]; + + multObj->pAnimData = &_animArrayData[_counter]; + + animData = multObj->pAnimData; + animData->isStatic = 1; + + multObj->tick = 0; + multObj->lastLeft = -1; + multObj->lastTop = -1; + multObj->lastRight = -1; + multObj->lastBottom = -1; + } + + _vm->_anim->_animSurf = + _vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, 0); + _vm->_draw->_spritesArray[22] = _vm->_anim->_animSurf; + + _vm->_video->drawSprite(_vm->_draw->_backSurface, _vm->_anim->_animSurf, + 0, 0, 319, 199, 0, 0, 0); + + _animDataAllocated = 1; + } else + _animDataAllocated = 0; + _frame = 0; + } + + do { + stop = 1; + + if (VAR(58) == 0) { + stop = drawStatics(stop); + stop = drawAnims(stop); + } + + animate(); + if (handleMouse) { + _vm->_draw->animateCursor(-1); + } else { + _vm->_draw->blitInvalidated(); + } + + if (VAR(58) == 0) { + drawText(&stop, &stopNoClear); + } + + stop = prepPalAnim(stop); + doPalAnim(); + + stop = doFadeAnim(stop); + stop = doSoundAnim(stop); + + if (_frame >= endFrame) + stopNoClear = 1; + + if (_vm->_snd->_playingSound) + stop = 0; + + _vm->_util->processInput(); + if (checkEscape && _vm->_util->checkKey() == 0x11b) // Esc + stop = 1; + + _frame++; + _vm->_util->waitEndFrame(); + } while (stop == 0 && stopNoClear == 0); + + if (stopNoClear == 0) { + if (_animDataAllocated) { + delete[] _objects; + _objects = 0; + + delete[] _renderData; + _renderData = 0; + + delete[] _animArrayX; + _animArrayX = 0; + + delete[] _animArrayY; + _animArrayY = 0; + + delete[] _animArrayData; + _animArrayData = 0; + + if (_vm->_anim->_animSurf) + _vm->_video->freeSurfDesc(_vm->_anim->_animSurf); + _vm->_anim->_animSurf = 0; + + _animDataAllocated = 0; + } + + if (_vm->_snd->_playingSound != 0) + _vm->_snd->stopSound(10); + + WRITE_VAR(57, (uint32)-1); + } else { + WRITE_VAR(57, _frame - 1 - _frameStart); + } +} + +char Mult_v1::drawStatics(char stop) { + if (_staticKeys[_staticKeysCount - 1].frame > _frame) + stop = 0; + + for (_counter = 0; _counter < _staticKeysCount; + _counter++) { + if (_staticKeys[_counter].frame != _frame + || _staticKeys[_counter].layer == -1) + continue; + + for (_vm->_scenery->_curStatic = 0, _vm->_scenery->_curStaticLayer = _staticKeys[_counter].layer; + _vm->_scenery->_curStaticLayer >= _vm->_scenery->_statics[_staticIndices[_vm->_scenery->_curStatic]].layersCount; + _vm->_scenery->_curStatic++) { + _vm->_scenery->_curStaticLayer -= + _vm->_scenery->_statics[_staticIndices[_vm->_scenery->_curStatic]].layersCount; + } + + _vm->_scenery->_curStatic = _staticIndices[_vm->_scenery->_curStatic]; + _vm->_scenery->renderStatic(_vm->_scenery->_curStatic, _vm->_scenery->_curStaticLayer); + _vm->_video->drawSprite(_vm->_draw->_backSurface, _vm->_anim->_animSurf, + 0, 0, 319, 199, 0, 0, 0); + } + return stop; +} + +char Mult_v1::drawAnims(char stop) { + Mult_AnimKey *key; + Mult_Object *animObj; + int16 i; + int16 count; + + for (_index = 0; _index < 4; _index++) { + for (_counter = 0; _counter < _animKeysCount[_index]; _counter++) { + key = &_animKeys[_index][_counter]; + animObj = &_objects[_index]; + if (key->frame != _frame) + continue; + + if (key->layer != -1) { + (*animObj->pPosX) = key->posX; + (*animObj->pPosY) = key->posY; + + animObj->pAnimData->frame = 0; + animObj->pAnimData->order = key->order; + animObj->pAnimData->animType = 1; + + animObj->pAnimData->isPaused = 0; + animObj->pAnimData->isStatic = 0; + animObj->pAnimData->maxTick = 0; + animObj->tick = 0; + animObj->pAnimData->layer = key->layer; + + count = _vm->_scenery->_animations[_animIndices[0]].layersCount; + i = 0; + while (animObj->pAnimData->layer >= count) { + animObj->pAnimData->layer -= count; + i++; + + count = _vm->_scenery->_animations[_animIndices[i]].layersCount; + } + animObj->pAnimData->animation = _animIndices[i]; + } else { + animObj->pAnimData->isStatic = 1; + } + } + } + return stop; +} + +void Mult_v1::drawText(char *pStop, char *pStopNoClear) { + char *savedIP; + + int16 cmd; + for (_index = 0; _index < _textKeysCount; _index++) { + if (_textKeys[_index].frame != _frame) + continue; + + cmd = _textKeys[_index].cmd; + if (cmd == 0) { + *pStop = 0; + } else if (cmd == 1) { + *pStopNoClear = 1; + _frameStart = 0; + } else if (cmd == 3) { + *pStop = 0; + savedIP = _vm->_global->_inter_execPtr; + _vm->_global->_inter_execPtr = (char *)(&_textKeys[_index].index); + _vm->_global->_inter_execPtr = savedIP; + } + } +} + +char Mult_v1::prepPalAnim(char stop) { + _palKeyIndex = -1; + do { + _palKeyIndex++; + if (_palKeyIndex >= _palKeysCount) + return stop; + } while (_palKeys[_palKeyIndex].frame != _frame); + + if (_palKeys[_palKeyIndex].cmd == -1) { + stop = 0; + _doPalSubst = 0; + _vm->_global->_pPaletteDesc->vgaPal = _oldPalette; + + memcpy((char *)_palAnimPalette, (char *)_vm->_global->_pPaletteDesc->vgaPal, 768); + + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + } else { + stop = 0; + _doPalSubst = 1; + _palAnimKey = _palKeyIndex; + + _palAnimIndices[0] = 0; + _palAnimIndices[1] = 0; + _palAnimIndices[2] = 0; + _palAnimIndices[3] = 0; + + _vm->_global->_pPaletteDesc->vgaPal = _palAnimPalette; + } + return stop; +} + +void Mult_v1::doPalAnim(void) { + int16 off; + int16 off2; + Video::Color *palPtr; + Mult_PalKey *palKey; + + if (_doPalSubst == 0) + return; + + for (_index = 0; _index < 4; _index++) { + palKey = &_palKeys[_palAnimKey]; + + if ((_frame % palKey->rates[_index]) != 0) + continue; + + _palAnimRed[_index] = + _vm->_global->_pPaletteDesc->vgaPal[palKey->subst[0][_index] - 1].red; + _palAnimGreen[_index] = + _vm->_global->_pPaletteDesc->vgaPal[palKey->subst[0][_index] - 1].green; + _palAnimBlue[_index] = + _vm->_global->_pPaletteDesc->vgaPal[palKey->subst[0][_index] - 1].blue; + + while (1) { + off = palKey->subst[(_palAnimIndices[_index] + 1) % 16][_index]; + if (off == 0) { + off = palKey->subst[_palAnimIndices[_index]][_index] - 1; + + _vm->_global->_pPaletteDesc->vgaPal[off].red = _palAnimRed[_index]; + _vm->_global->_pPaletteDesc->vgaPal[off].green = _palAnimGreen[_index]; + _vm->_global->_pPaletteDesc->vgaPal[off].blue = _palAnimBlue[_index]; + } else { + off = palKey->subst[(_palAnimIndices[_index] + 1) % 16][_index] - 1; + off2 = palKey->subst[_palAnimIndices[_index]][_index] - 1; + + _vm->_global->_pPaletteDesc->vgaPal[off2].red = _vm->_global->_pPaletteDesc->vgaPal[off].red; + _vm->_global->_pPaletteDesc->vgaPal[off2].green = _vm->_global->_pPaletteDesc->vgaPal[off].green; + _vm->_global->_pPaletteDesc->vgaPal[off2].blue = _vm->_global->_pPaletteDesc->vgaPal[off].blue; + } + + _palAnimIndices[_index] = (_palAnimIndices[_index] + 1) % 16; + + off = palKey->subst[_palAnimIndices[_index]][_index]; + + if (off == 0) { + _palAnimIndices[_index] = 0; + off = palKey->subst[0][_index] - 1; + + _palAnimRed[_index] = _vm->_global->_pPaletteDesc->vgaPal[off].red; + _palAnimGreen[_index] = _vm->_global->_pPaletteDesc->vgaPal[off].green; + _palAnimBlue[_index] = _vm->_global->_pPaletteDesc->vgaPal[off].blue; + } + if (_palAnimIndices[_index] == 0) + break; + } + } + + if (_vm->_global->_colorCount == 256) { + _vm->_video->waitRetrace(_vm->_global->_videoMode); + + palPtr = _vm->_global->_pPaletteDesc->vgaPal; + for (_counter = 0; _counter < 16; _counter++) { + _vm->_video->setPalElem(_counter, palPtr->red, palPtr->green, palPtr->blue, 0, 0x13); + palPtr++; + } + + palPtr = _vm->_global->_pPaletteDesc->vgaPal; + for (_counter = 0; _counter < 16; _counter++) { + _vm->_global->_redPalette[_counter] = palPtr->red; + _vm->_global->_greenPalette[_counter] = palPtr->green; + _vm->_global->_bluePalette[_counter] = palPtr->blue; + palPtr++; + } + } else { + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + } +} + +char Mult_v1::doFadeAnim(char stop) { + Mult_PalFadeKey *fadeKey; + + for (_index = 0; _index < _palFadeKeysCount; _index++) { + fadeKey = &_palFadeKeys[_index]; + + if (fadeKey->frame != _frame) + continue; + + stop = 0; + if ((fadeKey->flag & 1) == 0) { + if (fadeKey->fade == 0) { + _vm->_global->_pPaletteDesc->vgaPal = _fadePal[fadeKey->palIndex]; + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + } else { + _vm->_global->_pPaletteDesc->vgaPal = _fadePal[fadeKey->palIndex]; + _vm->_palanim->fade(_vm->_global->_pPaletteDesc, fadeKey->fade, 0); + } + } else { + _vm->_global->_pPaletteDesc->vgaPal = _fadePal[fadeKey->palIndex]; + _vm->_palanim->fade(_vm->_global->_pPaletteDesc, fadeKey->fade, -1); + + _palFadingRed = (fadeKey->flag >> 1) & 1; + _palFadingGreen = (fadeKey->flag >> 2) & 1; + _palFadingBlue = (fadeKey->flag >> 3) & 1; + } + } + + if (_palFadingRed) { + _palFadingRed = !_vm->_palanim->fadeStep(1); + stop = 0; + } + if (_palFadingGreen) { + _palFadingGreen = !_vm->_palanim->fadeStep(2); + stop = 0; + } + if (_palFadingBlue) { + _palFadingBlue = !_vm->_palanim->fadeStep(3); + stop = 0; + } + return stop; +} + +char Mult_v1::doSoundAnim(char stop) { + Mult_SndKey *sndKey; + for (_index = 0; _index < _sndKeysCount; _index++) { + sndKey = &_sndKeys[_index]; + if (sndKey->frame != _frame) + continue; + + if (sndKey->cmd != -1) { + if (sndKey->cmd == 1) { + _vm->_snd->stopSound(0); + stop = 0; + playSound(_vm->_game->_soundSamples[sndKey->soundIndex], sndKey->repCount, + sndKey->freq, sndKey->channel); + + } else if (sndKey->cmd == 4) { + _vm->_snd->stopSound(0); + stop = 0; + playSound(_vm->_game->_soundSamples[sndKey->soundIndex], sndKey->repCount, + sndKey->freq, sndKey->channel); + } + } else { + if (_vm->_snd->_playingSound) + _vm->_snd->stopSound(sndKey->channel); + } + } + return stop; +} + +void Mult_v1::animate(void) { + int16 minOrder; + int16 maxOrder; + int16 *pCurLefts; + int16 *pCurRights; + int16 *pCurTops; + int16 *pCurBottoms; + int16 *pDirtyLefts; + int16 *pDirtyRights; + int16 *pDirtyTops; + int16 *pDirtyBottoms; + int16 *pNeedRedraw; + Mult_AnimData *pAnimData; + int16 i, j; + int16 order; + + if (_renderData == 0) + return; + + pDirtyLefts = _renderData; + pDirtyRights = pDirtyLefts + _objCount; + pDirtyTops = pDirtyRights + _objCount; + pDirtyBottoms = pDirtyTops + _objCount; + pNeedRedraw = pDirtyBottoms + _objCount; + pCurLefts = pNeedRedraw + _objCount; + pCurRights = pCurLefts + _objCount; + pCurTops = pCurRights + _objCount; + pCurBottoms = pCurTops + _objCount; + minOrder = 100; + maxOrder = 0; + + //Find dirty areas + for (i = 0; i < _objCount; i++) { + pNeedRedraw[i] = 0; + pDirtyTops[i] = 1000; + pDirtyLefts[i] = 1000; + pDirtyBottoms[i] = 1000; + pDirtyRights[i] = 1000; + pAnimData = _objects[i].pAnimData; + + if (pAnimData->isStatic == 0 && pAnimData->isPaused == 0 && + _objects[i].tick == pAnimData->maxTick) { + if (pAnimData->order < minOrder) + minOrder = pAnimData->order; + + if (pAnimData->order > maxOrder) + maxOrder = pAnimData->order; + + pNeedRedraw[i] = 1; + _vm->_scenery->updateAnim(pAnimData->layer, pAnimData->frame, + pAnimData->animation, 0, + *(_objects[i].pPosX), *(_objects[i].pPosY), + 0); + + if (_objects[i].lastLeft != -1) { + pDirtyLefts[i] = + MIN(_objects[i].lastLeft, + _vm->_scenery->_toRedrawLeft); + pDirtyTops[i] = + MIN(_objects[i].lastTop, + _vm->_scenery->_toRedrawTop); + pDirtyRights[i] = + MAX(_objects[i].lastRight, + _vm->_scenery->_toRedrawRight); + pDirtyBottoms[i] = + MAX(_objects[i].lastBottom, + _vm->_scenery->_toRedrawBottom); + } else { + pDirtyLefts[i] = _vm->_scenery->_toRedrawLeft; + pDirtyTops[i] = _vm->_scenery->_toRedrawTop; + pDirtyRights[i] = _vm->_scenery->_toRedrawRight; + pDirtyBottoms[i] = _vm->_scenery->_toRedrawBottom; + } + pCurLefts[i] = _vm->_scenery->_toRedrawLeft; + pCurRights[i] = _vm->_scenery->_toRedrawRight; + pCurTops[i] = _vm->_scenery->_toRedrawTop; + pCurBottoms[i] = _vm->_scenery->_toRedrawBottom; + } else { + if (_objects[i].lastLeft != -1) { + if (pAnimData->order < minOrder) + minOrder = pAnimData->order; + + if (pAnimData->order > maxOrder) + maxOrder = pAnimData->order; + + if (pAnimData->isStatic) + *pNeedRedraw = 1; + + pCurLefts[i] = _objects[i].lastLeft; + pDirtyLefts[i] = _objects[i].lastLeft; + + pCurTops[i] = _objects[i].lastTop; + pDirtyTops[i] = _objects[i].lastTop; + + pCurRights[i] = _objects[i].lastRight; + pDirtyRights[i] = _objects[i].lastRight; + + pCurBottoms[i] = _objects[i].lastBottom; + pDirtyBottoms[i] = _objects[i].lastBottom; + } + } + } + + // Find intersections + for (i = 0; i < _objCount; i++) { + pAnimData = _objects[i].pAnimData; + pAnimData->intersected = 200; + + if (pAnimData->isStatic) + continue; + + for (j = 0; j < _objCount; j++) { + if (i == j) + continue; + + if (_objects[j].pAnimData->isStatic) + continue; + + if (pCurRights[i] < pCurLefts[j]) + continue; + + if (pCurRights[j] < pCurLefts[i]) + continue; + + if (pCurBottoms[i] < pCurTops[j]) + continue; + + if (pCurBottoms[j] < pCurTops[i]) + continue; + + pAnimData->intersected = j; + break; + } + } + + // Restore dirty areas + for (i = 0; i < _objCount; i++) { + + if (pNeedRedraw[i] == 0 || _objects[i].lastLeft == -1) + continue; + + _vm->_draw->_sourceSurface = 22; + _vm->_draw->_destSurface = 21; + _vm->_draw->_spriteLeft = pDirtyLefts[i] - _vm->_anim->_areaLeft; + _vm->_draw->_spriteTop = pDirtyTops[i] - _vm->_anim->_areaTop; + _vm->_draw->_spriteRight = pDirtyRights[i] - pDirtyLefts[i] + 1; + _vm->_draw->_spriteBottom = pDirtyBottoms[i] - pDirtyTops[i] + 1; + _vm->_draw->_destSpriteX = pDirtyLefts[i]; + _vm->_draw->_destSpriteY = pDirtyTops[i]; + _vm->_draw->_transparency = 0; + _vm->_draw->spriteOperation(DRAW_BLITSURF); + _objects[i].lastLeft = -1; + } + + // Update view + for (order = minOrder; order <= maxOrder; order++) { + for (i = 0; i < _objCount; i++) { + pAnimData = _objects[i].pAnimData; + if (pAnimData->order != order) + continue; + + if (pNeedRedraw[i]) { + if (pAnimData->isStatic == 0) { + + _vm->_scenery->updateAnim(pAnimData->layer, + pAnimData->frame, + pAnimData->animation, 2, + *(_objects[i].pPosX), + *(_objects[i].pPosY), 1); + + if (_vm->_scenery->_toRedrawLeft != -12345) { + _objects[i].lastLeft = + _vm->_scenery->_toRedrawLeft; + _objects[i].lastTop = + _vm->_scenery->_toRedrawTop; + _objects[i].lastRight = + _vm->_scenery->_toRedrawRight; + _objects[i].lastBottom = + _vm->_scenery->_toRedrawBottom; + } else { + _objects[i].lastLeft = -1; + } + } + _vm->_scenery->updateStatic(order + 1); + } else if (pAnimData->isStatic == 0) { + for (j = 0; j < _objCount; j++) { + if (pNeedRedraw[j] == 0) + continue; + + if (pDirtyRights[i] < pDirtyLefts[j]) + continue; + + if (pDirtyRights[j] < pDirtyLefts[i]) + continue; + + if (pDirtyBottoms[i] < pDirtyTops[j]) + continue; + + if (pDirtyBottoms[j] < pDirtyTops[i]) + continue; + + _vm->_scenery->_toRedrawLeft = pDirtyLefts[j]; + _vm->_scenery->_toRedrawRight = pDirtyRights[j]; + _vm->_scenery->_toRedrawTop = pDirtyTops[j]; + _vm->_scenery->_toRedrawBottom = pDirtyBottoms[j]; + + _vm->_scenery->updateAnim(pAnimData->layer, + pAnimData->frame, + pAnimData->animation, 4, + *(_objects[i].pPosX), + *(_objects[i].pPosY), 1); + + _vm->_scenery->updateStatic(order + 1); + } + } + } + } + + // Advance animations + for (i = 0; i < _objCount; i++) { + pAnimData = _objects[i].pAnimData; + if (pAnimData->isStatic || pAnimData->isPaused) + continue; + + if (_objects[i].tick == pAnimData->maxTick) { + _objects[i].tick = 0; + if (pAnimData->animType == 4) { + pAnimData->isPaused = 1; + pAnimData->frame = 0; + } else { + pAnimData->frame++; + if (pAnimData->frame >= + _vm->_scenery->_animations[(int)pAnimData->animation].layers[pAnimData->layer]->framesCount) { + switch (pAnimData->animType) { + case 0: + pAnimData->frame = 0; + break; + + case 1: + pAnimData->frame = 0; + + *(_objects[i].pPosX) = + *(_objects[i].pPosX) + + _vm->_scenery->_animations[(int)pAnimData->animation].layers[pAnimData->layer]->animDeltaX; + + *(_objects[i].pPosY) = + *(_objects[i].pPosY) + + _vm->_scenery->_animations[(int)pAnimData->animation].layers[pAnimData->layer]->animDeltaY; + break; + + case 2: + pAnimData->frame = 0; + pAnimData->animation = + pAnimData->newAnimation; + pAnimData->layer = + pAnimData->newLayer; + break; + + case 3: + pAnimData->animType = 4; + pAnimData->frame = 0; + break; + + case 5: + pAnimData->isStatic = 1; + pAnimData->frame = 0; + break; + + case 6: + pAnimData->frame--; + pAnimData->isPaused = 1; + break; + } + pAnimData->newCycle = 1; + } else { + pAnimData->newCycle = 0; + } + } + } else { + _objects[i].tick++; + } + } +} + } // End of namespace Gob |