Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

mult.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 Ivan Dubrov
 * Copyright (C) 2004-2005 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.
 *
 * $Header: /cvsroot/scummvm/scummvm/gob/mult.cpp,v 1.12.2.1 2005/10/18 02:11:18 sev Exp $
 *
 */
#include "gob/gob.h"
#include "gob/video.h"
#include "gob/anim.h"
#include "gob/draw.h"
#include "gob/scenery.h"
#include "gob/mult.h"
#include "gob/util.h"
#include "gob/inter.h"
#include "gob/parse.h"
#include "gob/global.h"
#include "gob/sound.h"
#include "gob/palanim.h"
#include "gob/game.h"

namespace Gob {

Mult_Object *mult_objects;
int16 *mult_renderData;
int16 mult_objCount;
int16 mult_frame;

char *mult_multData;
char mult_doPalSubst;
int16 mult_counter;
int16 mult_frameRate;

int32 *mult_animArrayX;
int32 *mult_animArrayY;

Mult_AnimData *mult_animArrayData;

int16 mult_index;

// Static keys
int16 mult_staticKeysCount;
Mult_StaticKey *mult_staticKeys;
int16 mult_staticIndices[10];

// Anim keys
Mult_AnimKey *mult_animKeys[4];
int16 mult_animKeysCount[4];
int16 mult_animLayer;
int16 mult_animIndices[10];

// Text keys
int16 mult_textKeysCount;
Mult_TextKey *mult_textKeys;

int16 mult_frameStart;

// Palette keys
int16 mult_palKeyIndex;
int16 mult_palKeysCount;
Mult_PalKey *mult_palKeys;
Color *mult_oldPalette;
Color mult_palAnimPalette[256];
int16 mult_palAnimKey;
int16 mult_palAnimIndices[4];
int16 mult_palAnimRed[4];
int16 mult_palAnimGreen[4];
int16 mult_palAnimBlue[4];

// Palette fading
Mult_PalFadeKey *mult_palFadeKeys;
int16 mult_palFadeKeysCount;
char mult_palFadingRed;
char mult_palFadingGreen;
char mult_palFadingBlue;

Color mult_fadePal[5][16];

// Sounds
int16 mult_sndKeysCount;
Mult_SndKey *mult_sndKeys;

char mult_animDataAllocated;

char *mult_dataPtr;
int16 mult_staticLoaded[10];
int16 mult_animLoaded[10];
int16 mult_sndSlotsCount;

void mult_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 (mult_renderData == 0)
            return;

      pDirtyLefts = mult_renderData;
      pDirtyRights = pDirtyLefts + mult_objCount;
      pDirtyTops = pDirtyRights + mult_objCount;
      pDirtyBottoms = pDirtyTops + mult_objCount;
      pNeedRedraw = pDirtyBottoms + mult_objCount;
      pCurLefts = pNeedRedraw + mult_objCount;
      pCurRights = pCurLefts + mult_objCount;
      pCurTops = pCurRights + mult_objCount;
      pCurBottoms = pCurTops + mult_objCount;
      minOrder = 100;
      maxOrder = 0;

      //Find dirty areas
      for (i = 0; i < mult_objCount; i++) {
            pNeedRedraw[i] = 0;
            pDirtyTops[i] = 1000;
            pDirtyLefts[i] = 1000;
            pDirtyBottoms[i] = 1000;
            pDirtyRights[i] = 1000;
            pAnimData = mult_objects[i].pAnimData;

            if (pAnimData->isStatic == 0 && pAnimData->isPaused == 0 &&
                mult_objects[i].tick == pAnimData->maxTick) {
                  if (pAnimData->order < minOrder)
                        minOrder = pAnimData->order;

                  if (pAnimData->order > maxOrder)
                        maxOrder = pAnimData->order;

                  pNeedRedraw[i] = 1;
                  scen_updateAnim(pAnimData->layer, pAnimData->frame,
                      pAnimData->animation, 0,
                      *(mult_objects[i].pPosX), *(mult_objects[i].pPosY),
                      0);

                  if (mult_objects[i].lastLeft != -1) {
                        pDirtyLefts[i] =
                            MIN(mult_objects[i].lastLeft,
                            scen_toRedrawLeft);
                        pDirtyTops[i] =
                            MIN(mult_objects[i].lastTop,
                            scen_toRedrawTop);
                        pDirtyRights[i] =
                            MAX(mult_objects[i].lastRight,
                            scen_toRedrawRight);
                        pDirtyBottoms[i] =
                            MAX(mult_objects[i].lastBottom,
                            scen_toRedrawBottom);
                  } else {
                        pDirtyLefts[i] = scen_toRedrawLeft;
                        pDirtyTops[i] = scen_toRedrawTop;
                        pDirtyRights[i] = scen_toRedrawRight;
                        pDirtyBottoms[i] = scen_toRedrawBottom;
                  }
                  pCurLefts[i] = scen_toRedrawLeft;
                  pCurRights[i] = scen_toRedrawRight;
                  pCurTops[i] = scen_toRedrawTop;
                  pCurBottoms[i] = scen_toRedrawBottom;
            } else {
                  if (mult_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] = mult_objects[i].lastLeft;
                        pDirtyLefts[i] = mult_objects[i].lastLeft;

                        pCurTops[i] = mult_objects[i].lastTop;
                        pDirtyTops[i] = mult_objects[i].lastTop;

                        pCurRights[i] = mult_objects[i].lastRight;
                        pDirtyRights[i] = mult_objects[i].lastRight;

                        pCurBottoms[i] = mult_objects[i].lastBottom;
                        pDirtyBottoms[i] = mult_objects[i].lastBottom;
                  }
            }
      }

      // Find intersections
      for (i = 0; i < mult_objCount; i++) {
            pAnimData = mult_objects[i].pAnimData;
            pAnimData->intersected = 200;

            if (pAnimData->isStatic)
                  continue;

            for (j = 0; j < mult_objCount; j++) {
                  if (i == j)
                        continue;

                  if (mult_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 < mult_objCount; i++) {

            if (pNeedRedraw[i] == 0 || mult_objects[i].lastLeft == -1)
                  continue;

            draw_sourceSurface = 22;
            draw_destSurface = 21;
            draw_spriteLeft = pDirtyLefts[i] - anim_animAreaLeft;
            draw_spriteTop = pDirtyTops[i] - anim_animAreaTop;
            draw_spriteRight = pDirtyRights[i] - pDirtyLefts[i] + 1;
            draw_spriteBottom = pDirtyBottoms[i] - pDirtyTops[i] + 1;
            draw_destSpriteX = pDirtyLefts[i];
            draw_destSpriteY = pDirtyTops[i];
            draw_transparency = 0;
            draw_spriteOperation(DRAW_BLITSURF);
            mult_objects[i].lastLeft = -1;
      }

      // Update view
      for (order = minOrder; order <= maxOrder; order++) {
            for (i = 0; i < mult_objCount; i++) {
                  pAnimData = mult_objects[i].pAnimData;
                  if (pAnimData->order != order)
                        continue;

                  if (pNeedRedraw[i]) {
                        if (pAnimData->isStatic == 0) {

                              scen_updateAnim(pAnimData->layer,
                                  pAnimData->frame,
                                  pAnimData->animation, 2,
                                  *(mult_objects[i].pPosX),
                                  *(mult_objects[i].pPosY), 1);

                              if (scen_toRedrawLeft != -12345) {
                                    mult_objects[i].lastLeft =
                                        scen_toRedrawLeft;
                                    mult_objects[i].lastTop =
                                        scen_toRedrawTop;
                                    mult_objects[i].lastRight =
                                        scen_toRedrawRight;
                                    mult_objects[i].lastBottom =
                                        scen_toRedrawBottom;
                              } else {
                                    mult_objects[i].lastLeft = -1;
                              }
                        }
                        scen_updateStatic(order + 1);
                  } else if (pAnimData->isStatic == 0) {
                        for (j = 0; j < mult_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;

                              scen_toRedrawLeft = pDirtyLefts[j];
                              scen_toRedrawRight = pDirtyRights[j];
                              scen_toRedrawTop = pDirtyTops[j];
                              scen_toRedrawBottom = pDirtyBottoms[j];

                              scen_updateAnim(pAnimData->layer,
                                  pAnimData->frame,
                                  pAnimData->animation, 4,
                                  *(mult_objects[i].pPosX),
                                  *(mult_objects[i].pPosY), 1);

                              scen_updateStatic(order + 1);
                        }
                  }
            }
      }

      // Advance animations
      for (i = 0; i < mult_objCount; i++) {
            pAnimData = mult_objects[i].pAnimData;
            if (pAnimData->isStatic || pAnimData->isPaused)
                  continue;

            if (mult_objects[i].tick == pAnimData->maxTick) {
                  mult_objects[i].tick = 0;
                  if (pAnimData->animType == 4) {
                        pAnimData->isPaused = 1;
                        pAnimData->frame = 0;
                  } else {
                        pAnimData->frame++;
                        if (pAnimData->frame >=
                            scen_animations[(int)pAnimData->animation].layers[pAnimData->layer]->framesCount) {
                              switch (pAnimData->animType) {
                              case 0:
                                    pAnimData->frame = 0;
                                    break;

                              case 1:
                                    pAnimData->frame = 0;

                                    *(mult_objects[i].pPosX) =
                                        *(mult_objects[i].pPosX) +
                                        scen_animations[(int)pAnimData->animation].layers[pAnimData->layer]->animDeltaX;

                                    *(mult_objects[i].pPosY) =
                                        *(mult_objects[i].pPosY) +
                                        scen_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 {
                  mult_objects[i].tick++;
            }
      }
}

void mult_interGetObjAnimSize(void) {
      Mult_AnimData *pAnimData;
      int16 objIndex;

      inter_evalExpr(&objIndex);
      pAnimData = mult_objects[objIndex].pAnimData;
      if (pAnimData->isStatic == 0) {
            scen_updateAnim(pAnimData->layer, pAnimData->frame,
                pAnimData->animation, 0, *(mult_objects[objIndex].pPosX),
                *(mult_objects[objIndex].pPosY), 0);
      }
      WRITE_VAR_OFFSET(parse_parseVarIndex(), scen_toRedrawLeft);
      WRITE_VAR_OFFSET(parse_parseVarIndex(), scen_toRedrawTop);
      WRITE_VAR_OFFSET(parse_parseVarIndex(), scen_toRedrawRight);
      WRITE_VAR_OFFSET(parse_parseVarIndex(), scen_toRedrawBottom);
}

void mult_interInitMult(void) {
      int16 oldAnimHeight;
      int16 oldAnimWidth;
      int16 oldObjCount;
      int16 i;
      int16 posXVar;
      int16 posYVar;
      int16 animDataVar;

      oldAnimWidth = anim_animAreaWidth;
      oldAnimHeight = anim_animAreaHeight;
      oldObjCount = mult_objCount;

      anim_animAreaLeft = inter_load16();
      anim_animAreaTop = inter_load16();
      anim_animAreaWidth = inter_load16();
      anim_animAreaHeight = inter_load16();
      mult_objCount = inter_load16();
      posXVar = parse_parseVarIndex();
      posYVar = parse_parseVarIndex();
      animDataVar = parse_parseVarIndex();

      if (mult_objects == 0) {
            mult_renderData = (int16 *)malloc(sizeof(int16) * mult_objCount * 9);
            mult_objects = (Mult_Object *)malloc(sizeof(Mult_Object) * mult_objCount);

            for (i = 0; i < mult_objCount; i++) {
                  mult_objects[i].pPosX = (int32 *)(inter_variables + i * 4 + (posXVar / 4) * 4);
                  mult_objects[i].pPosY = (int32 *)(inter_variables + i * 4 + (posYVar / 4) * 4);
                  mult_objects[i].pAnimData =
                      (Mult_AnimData *) (inter_variables + animDataVar +
                      i * 4 * inter_animDataSize);

                  mult_objects[i].pAnimData->isStatic = 1;
                  mult_objects[i].tick = 0;
                  mult_objects[i].lastLeft = -1;
                  mult_objects[i].lastRight = -1;
                  mult_objects[i].lastTop = -1;
                  mult_objects[i].lastBottom = -1;
            }
      } else if (oldObjCount != mult_objCount) {
            error("mult_interInitMult: Object count changed, but storage didn't (old count = %d, new count = %d)",
                oldObjCount, mult_objCount);
      }

      if (anim_underAnimSurf != 0 &&
          (oldAnimWidth != anim_animAreaWidth
            || oldAnimHeight != anim_animAreaHeight)) {
            vid_freeSurfDesc(anim_underAnimSurf);
            anim_underAnimSurf = 0;
      }

      if (anim_underAnimSurf == 0) {
            anim_underAnimSurf = vid_initSurfDesc(videoMode,
                anim_animAreaWidth, anim_animAreaHeight, 0);

            draw_spritesArray[22] = anim_underAnimSurf;
      }

      vid_drawSprite(draw_backSurface, anim_underAnimSurf,
          anim_animAreaLeft, anim_animAreaTop,
          anim_animAreaLeft + anim_animAreaWidth - 1,
          anim_animAreaTop + anim_animAreaHeight - 1, 0, 0, 0);

      debug(4, "mult_interInitMult: x = %d, y = %d, w = %d, h = %d",
              anim_animAreaLeft, anim_animAreaTop, anim_animAreaWidth, anim_animAreaHeight);
      debug(4, "    objCount = %d, animation data size = %d", mult_objCount, inter_animDataSize);
}

void mult_freeMult(void) {
      if (anim_underAnimSurf != 0)
            vid_freeSurfDesc(anim_underAnimSurf);

      free(mult_objects);
      free(mult_renderData);

      mult_objects = 0;
      mult_renderData = 0;
      anim_underAnimSurf = 0;
}

void mult_interLoadMult(void) {
      int16 val;
      int16 objIndex;
      int16 i;
      char *multData;

      debug(4, "mult_interLoadMult: Loading...");

      inter_evalExpr(&objIndex);
      inter_evalExpr(&val);
      *mult_objects[objIndex].pPosX = val;
      inter_evalExpr(&val);
      *mult_objects[objIndex].pPosY = val;

      multData = (char *)mult_objects[objIndex].pAnimData;
      for (i = 0; i < 11; i++) {
            if ((char)READ_LE_UINT16(inter_execPtr) == (char)99) {
                  inter_evalExpr(&val);
                  multData[i] = val;
            } else {
                  inter_execPtr++;
            }
      }
}

void mult_freeAll(void) {
      int16 i;

      mult_freeMult();
      for (i = 0; i < 10; i++)
            scen_freeAnim(i);

      for (i = 0; i < 10; i++)
            scen_freeStatic(i);
}

void mult_initAll(void) {
      int16 i;

      mult_objects = 0;
      anim_underAnimSurf = 0;
      mult_renderData = 0;

      for (i = 0; i < 10; i++)
            scen_animPictCount[i] = 0;

      for (i = 0; i < 20; i++) {
            scen_spriteRefs[i] = 0;
            scen_spriteResId[i] = -1;
      }

      for (i = 0; i < 10; i++)
            scen_staticPictCount[i] = -1;

      scen_curStaticLayer = -1;
      scen_curStatic = -1;
}

void mult_playSound(Snd_SoundDesc * soundDesc, int16 repCount, int16 freq,
          int16 channel) {
      snd_playSample(soundDesc, repCount, freq);
}

char mult_drawStatics(char stop) {
      if (mult_staticKeys[mult_staticKeysCount - 1].frame > mult_frame)
            stop = 0;

      for (mult_counter = 0; mult_counter < mult_staticKeysCount;
          mult_counter++) {
            if (mult_staticKeys[mult_counter].frame != mult_frame
                || mult_staticKeys[mult_counter].layer == -1)
                  continue;

            for (scen_curStatic = 0, scen_curStaticLayer = mult_staticKeys[mult_counter].layer;
                   scen_curStaticLayer >= scen_statics[mult_staticIndices[scen_curStatic]].layersCount;
                   scen_curStatic++) {
                  scen_curStaticLayer -=
                      scen_statics[mult_staticIndices[scen_curStatic]].layersCount;
            }

            scen_curStatic = mult_staticIndices[scen_curStatic];
            scen_renderStatic(scen_curStatic, scen_curStaticLayer);
            vid_drawSprite(draw_backSurface, anim_underAnimSurf,
                0, 0, 319, 199, 0, 0, 0);
      }
      return stop;
}

void mult_drawAnims(void) {
      Mult_AnimKey *key;
      Mult_Object *animObj;
      int16 i;
      int16 count;

      for (mult_index = 0; mult_index < 4; mult_index++) {
            for (mult_counter = 0; mult_counter < mult_animKeysCount[mult_index]; mult_counter++) {
                  key = &mult_animKeys[mult_index][mult_counter];
                  animObj = &mult_objects[mult_index];
                  if (key->frame != mult_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 = scen_animations[mult_animIndices[0]].layersCount;
                        i = 0;
                        while (animObj->pAnimData->layer >= count) {
                              animObj->pAnimData->layer -= count;
                              i++;

                              count = scen_animations[mult_animIndices[i]].layersCount;
                        }
                        animObj->pAnimData->animation = mult_animIndices[i];
                  } else {
                        animObj->pAnimData->isStatic = 1;
                  }
            }
      }
}

void mult_drawText(char *pStop, char *pStopNoClear) {
      char *savedIP;

      int16 cmd;
      for (mult_index = 0; mult_index < mult_textKeysCount; mult_index++) {
            if (mult_textKeys[mult_index].frame != mult_frame)
                  continue;

            cmd = mult_textKeys[mult_index].cmd;
            if (cmd == 0) {
                  *pStop = 0;
            } else if (cmd == 1) {
                  *pStopNoClear = 1;
                  mult_frameStart = 0;
            } else if (cmd == 3) {
                  *pStop = 0;
                  savedIP = inter_execPtr;
                  inter_execPtr = (char *)(&mult_textKeys[mult_index].index);
                  inter_execPtr = savedIP;
            }
      }
}

char mult_prepPalAnim(char stop) {
      mult_palKeyIndex = -1;
      do {
            mult_palKeyIndex++;
            if (mult_palKeyIndex >= mult_palKeysCount)
                  return stop;
      } while (mult_palKeys[mult_palKeyIndex].frame != mult_frame);

      if (mult_palKeys[mult_palKeyIndex].cmd == -1) {
            stop = 0;
            mult_doPalSubst = 0;
            pPaletteDesc->vgaPal = mult_oldPalette;

            memcpy((char *)mult_palAnimPalette, (char *)pPaletteDesc->vgaPal, 768);

            vid_setFullPalette(pPaletteDesc);
      } else {
            stop = 0;
            mult_doPalSubst = 1;
            mult_palAnimKey = mult_palKeyIndex;

            mult_palAnimIndices[0] = 0;
            mult_palAnimIndices[1] = 0;
            mult_palAnimIndices[2] = 0;
            mult_palAnimIndices[3] = 0;

            pPaletteDesc->vgaPal = mult_palAnimPalette;
      }
      return stop;
}

void mult_doPalAnim(void) {
      int16 off;
      int16 off2;
      Color *palPtr;
      Mult_PalKey *palKey;

      if (mult_doPalSubst == 0)
            return;

      for (mult_index = 0; mult_index < 4; mult_index++) {
            palKey = &mult_palKeys[mult_palAnimKey];

            if ((mult_frame % palKey->rates[mult_index]) != 0)
                  continue;

            mult_palAnimRed[mult_index] =
                pPaletteDesc->vgaPal[palKey->subst[0][mult_index] - 1].red;
            mult_palAnimGreen[mult_index] =
                pPaletteDesc->vgaPal[palKey->subst[0][mult_index] - 1].green;
            mult_palAnimBlue[mult_index] =
                pPaletteDesc->vgaPal[palKey->subst[0][mult_index] - 1].blue;

            while (1) {
                  off = palKey->subst[(mult_palAnimIndices[mult_index] + 1) % 16][mult_index];
                  if (off == 0) {
                        off = palKey->subst[mult_palAnimIndices[mult_index]][mult_index] - 1;

                        pPaletteDesc->vgaPal[off].red = mult_palAnimRed[mult_index];
                        pPaletteDesc->vgaPal[off].green = mult_palAnimGreen[mult_index];
                        pPaletteDesc->vgaPal[off].blue = mult_palAnimBlue[mult_index];
                  } else {
                        off = palKey->subst[(mult_palAnimIndices[mult_index] + 1) % 16][mult_index] - 1;
                        off2 = palKey->subst[mult_palAnimIndices[mult_index]][mult_index] - 1;

                        pPaletteDesc->vgaPal[off2].red = pPaletteDesc->vgaPal[off].red;
                        pPaletteDesc->vgaPal[off2].green = pPaletteDesc->vgaPal[off].green;
                        pPaletteDesc->vgaPal[off2].blue = pPaletteDesc->vgaPal[off].blue;
                  }

                  mult_palAnimIndices[mult_index] = (mult_palAnimIndices[mult_index] + 1) % 16;

                  off = palKey->subst[mult_palAnimIndices[mult_index]][mult_index];

                  if (off == 0) {
                        mult_palAnimIndices[mult_index] = 0;
                        off = palKey->subst[0][mult_index] - 1;

                        mult_palAnimRed[mult_index] = pPaletteDesc->vgaPal[off].red;
                        mult_palAnimGreen[mult_index] = pPaletteDesc->vgaPal[off].green;
                        mult_palAnimBlue[mult_index] = pPaletteDesc->vgaPal[off].blue;
                  }
                  if (mult_palAnimIndices[mult_index] == 0)
                        break;
            }
      }

      if (colorCount == 256) {
            vid_waitRetrace(videoMode);

            palPtr = pPaletteDesc->vgaPal;
            for (mult_counter = 0; mult_counter < 16; mult_counter++) {
                  vid_setPalElem(mult_counter, palPtr->red, palPtr->green, palPtr->blue, 0, 0x13);
                  palPtr++;
            }

            palPtr = pPaletteDesc->vgaPal;
            for (mult_counter = 0; mult_counter < 16; mult_counter++) {
                  redPalette[mult_counter] = palPtr->red;
                  greenPalette[mult_counter] = palPtr->green;
                  bluePalette[mult_counter] = palPtr->blue;
                  palPtr++;
            }
      } else {
            vid_setFullPalette(pPaletteDesc);
      }
}

char mult_doFadeAnim(char stop) {
      Mult_PalFadeKey *fadeKey;

      for (mult_index = 0; mult_index < mult_palFadeKeysCount; mult_index++) {
            fadeKey = &mult_palFadeKeys[mult_index];

            if (fadeKey->frame != mult_frame)
                  continue;

            stop = 0;
            if ((fadeKey->flag & 1) == 0) {
                  if (fadeKey->fade == 0) {
                        pPaletteDesc->vgaPal = mult_fadePal[fadeKey->palIndex];
                        vid_setFullPalette(pPaletteDesc);
                  } else {
                        pPaletteDesc->vgaPal = mult_fadePal[fadeKey->palIndex];
                        pal_fade(pPaletteDesc, fadeKey->fade, 0);
                  }
            } else {
                  pPaletteDesc->vgaPal = mult_fadePal[fadeKey->palIndex];
                  pal_fade(pPaletteDesc, fadeKey->fade, -1);

                  mult_palFadingRed = (fadeKey->flag >> 1) & 1;
                  mult_palFadingGreen = (fadeKey->flag >> 2) & 1;
                  mult_palFadingBlue = (fadeKey->flag >> 3) & 1;
            }
      }

      if (mult_palFadingRed) {
            mult_palFadingRed = !pal_fadeStep(1);
            stop = 0;
      }
      if (mult_palFadingGreen) {
            mult_palFadingGreen = !pal_fadeStep(2);
            stop = 0;
      }
      if (mult_palFadingBlue) {
            mult_palFadingBlue = !pal_fadeStep(3);
            stop = 0;
      }
      return stop;
}

char mult_doSoundAnim(char stop) {
      Mult_SndKey *sndKey;
      for (mult_index = 0; mult_index < mult_sndKeysCount; mult_index++) {
            sndKey = &mult_sndKeys[mult_index];
            if (sndKey->frame != mult_frame)
                  continue;

            if (sndKey->cmd != -1) {
                  if (sndKey->cmd == 1) {
                        snd_stopSound(0);
                        stop = 0;
                        mult_playSound(game_soundSamples[sndKey->soundIndex], sndKey->repCount,
                            sndKey->freq, sndKey->channel);

                  } else if (sndKey->cmd == 4) {
                        snd_stopSound(0);
                        stop = 0;
                        mult_playSound(game_soundSamples[sndKey->soundIndex], sndKey->repCount,
                            sndKey->freq, sndKey->channel);
                  }
            } else {
                  if (snd_playingSound)
                        snd_stopSound(sndKey->channel);
            }
      }
      return stop;
}

void mult_playMult(int16 startFrame, int16 endFrame, char checkEscape,
          char handleMouse) {
      char stopNoClear;
      char stop;
      Mult_Object *multObj;
      Mult_AnimData *animData;

      if (mult_multData == 0)
            return;

      stopNoClear = 0;
      mult_frame = startFrame;
      if (endFrame == -1)
            endFrame = 32767;

      if (mult_frame == -1) {
            mult_doPalSubst = 0;
            mult_palFadingRed = 0;
            mult_palFadingGreen = 0;
            mult_palFadingBlue = 0;

            mult_oldPalette = pPaletteDesc->vgaPal;
            memcpy((char *)mult_palAnimPalette, (char *)pPaletteDesc->vgaPal, 768);

            if (anim_underAnimSurf == 0) {
                  util_setFrameRate(mult_frameRate);
                  anim_animAreaTop = 0;
                  anim_animAreaLeft = 0;
                  anim_animAreaWidth = 320;
                  anim_animAreaHeight = 200;
                  mult_objCount = 4;

                  mult_objects = (Mult_Object *)malloc(sizeof(Mult_Object) * mult_objCount);
                  mult_renderData = (int16 *)malloc(sizeof(int16) * 9 * mult_objCount);

                  mult_animArrayX = (int32 *)malloc(sizeof(int32) * mult_objCount);
                  mult_animArrayY = (int32 *)malloc(sizeof(int32) * mult_objCount);

                  mult_animArrayData = (Mult_AnimData *)malloc(sizeof(Mult_AnimData) * mult_objCount);

                  for (mult_counter = 0; mult_counter < mult_objCount; mult_counter++) {
                        multObj = &mult_objects[mult_counter];

                        multObj->pPosX = (int32 *)&mult_animArrayX[mult_counter];
                        multObj->pPosY = (int32 *)&mult_animArrayY[mult_counter];

                        multObj->pAnimData = &mult_animArrayData[mult_counter];

                        animData = multObj->pAnimData;
                        animData->isStatic = 1;

                        multObj->tick = 0;
                        multObj->lastLeft = -1;
                        multObj->lastTop = -1;
                        multObj->lastRight = -1;
                        multObj->lastBottom = -1;
                  }

                  anim_underAnimSurf =
                      vid_initSurfDesc(videoMode, 320, 200, 0);
                  draw_spritesArray[22] = anim_underAnimSurf;

                  vid_drawSprite(draw_backSurface, anim_underAnimSurf,
                      0, 0, 319, 199, 0, 0, 0);

                  mult_animDataAllocated = 1;
            } else
                  mult_animDataAllocated = 0;
            mult_frame = 0;
      }

      do {
            stop = 1;

            if (VAR(58) == 0) {
                  stop = mult_drawStatics(stop);
                  mult_drawAnims();
            }

            mult_animate();
            if (handleMouse) {
                  draw_animateCursor(-1);
            } else {
                  draw_blitInvalidated();
            }

            if (VAR(58) == 0) {
                  mult_drawText(&stop, &stopNoClear);
            }

            stop = mult_prepPalAnim(stop);
            mult_doPalAnim();

            stop = mult_doFadeAnim(stop);
            stop = mult_doSoundAnim(stop);

            if (mult_frame >= endFrame)
                  stopNoClear = 1;

            if (snd_playingSound)
                  stop = 0;

            util_processInput();
            if (checkEscape && util_checkKey() == 0x11b)    // Esc
                  stop = 1;

            mult_frame++;
            util_waitEndFrame();
      } while (stop == 0 && stopNoClear == 0);

      if (stopNoClear == 0) {
            if (mult_animDataAllocated) {
                  free(mult_objects);
                  mult_objects = 0;

                  free(mult_renderData);
                  mult_renderData = 0;

                  free(mult_animArrayX);
                  mult_animArrayX = 0;

                  free(mult_animArrayY);
                  mult_animArrayY = 0;

                  free(mult_animArrayData);
                  mult_animArrayData = 0;

                  if (anim_underAnimSurf)
                        vid_freeSurfDesc(anim_underAnimSurf);
                  anim_underAnimSurf = 0;

                  mult_animDataAllocated = 0;
            }

            if (snd_playingSound != 0)
                  snd_stopSound(10);

            WRITE_VAR(57, (uint32)-1);
      } else {
            WRITE_VAR(57, mult_frame - 1 - mult_frameStart);
      }
}

void mult_zeroMultData(void) {
      mult_multData = 0;
}

void mult_loadMult(int16 resId) {
      char animCount;
      char staticCount;
      int16 palIndex;
      int16 i, j;

      mult_sndSlotsCount = 0;
      mult_frameStart = 0;
      mult_multData = game_loadExtData(resId, 0, 0);
      mult_dataPtr = mult_multData;

      staticCount = mult_dataPtr[0];
      animCount = mult_dataPtr[1];
      mult_dataPtr += 2;
      staticCount++;
      animCount++;

      for (i = 0; i < staticCount; i++, mult_dataPtr += 14) {
            mult_staticIndices[i] = scen_loadStatic(1);

            if (mult_staticIndices[i] >= 100) {
                  mult_staticIndices[i] -= 100;
                  mult_staticLoaded[i] = 1;
            } else {
                  mult_staticLoaded[i] = 0;
            }
      }

      for (i = 0; i < animCount; i++, mult_dataPtr += 14) {
            mult_animIndices[i] = scen_loadAnim(1);

            if (mult_animIndices[i] >= 100) {
                  mult_animIndices[i] -= 100;
                  mult_animLoaded[i] = 1;
            } else {
                  mult_animLoaded[i] = 0;
            }
      }

      mult_frameRate = READ_LE_UINT16(mult_dataPtr);
      mult_dataPtr += 2;

      mult_staticKeysCount = READ_LE_UINT16(mult_dataPtr);
      mult_dataPtr += 2;

      mult_staticKeys = (Mult_StaticKey *)malloc(sizeof(Mult_StaticKey) *
          mult_staticKeysCount);
      for (i = 0; i < mult_staticKeysCount; i++, mult_dataPtr += 4) {
            mult_staticKeys[i].frame = (int16)READ_LE_UINT16(mult_dataPtr);
            mult_staticKeys[i].layer = (int16)READ_LE_UINT16(mult_dataPtr + 2);
      }

      for (j = 0; j < 4; j++) {
            mult_animKeysCount[j] = READ_LE_UINT16(mult_dataPtr);
            mult_dataPtr += 2;

            mult_animKeys[j] = (Mult_AnimKey *) malloc(sizeof(Mult_AnimKey) * mult_animKeysCount[j]);
            for (i = 0; i < mult_animKeysCount[j]; i++, mult_dataPtr += 10) {
                  mult_animKeys[j][i].frame = (int16)READ_LE_UINT16(mult_dataPtr);
                  mult_animKeys[j][i].layer = (int16)READ_LE_UINT16(mult_dataPtr + 2);
                  mult_animKeys[j][i].posX = (int16)READ_LE_UINT16(mult_dataPtr + 4);
                  mult_animKeys[j][i].posY = (int16)READ_LE_UINT16(mult_dataPtr + 6);
                  mult_animKeys[j][i].order = (int16)READ_LE_UINT16(mult_dataPtr + 8);
            }
      }

      for (palIndex = 0; palIndex < 5; palIndex++) {
            for (i = 0; i < 16; i++) {
                  mult_fadePal[palIndex][i].red = mult_dataPtr[0];
                  mult_fadePal[palIndex][i].green = mult_dataPtr[1];
                  mult_fadePal[palIndex][i].blue = mult_dataPtr[2];
                  mult_dataPtr += 3;
            }
      }

      mult_palFadeKeysCount = READ_LE_UINT16(mult_dataPtr);
      mult_dataPtr += 2;
      mult_palFadeKeys = (Mult_PalFadeKey *)malloc(sizeof(Mult_PalFadeKey) * mult_palFadeKeysCount);

      for (i = 0; i < mult_palFadeKeysCount; i++, mult_dataPtr += 7) {
            mult_palFadeKeys[i].frame = (int16)READ_LE_UINT16(mult_dataPtr);
            mult_palFadeKeys[i].fade = (int16)READ_LE_UINT16(mult_dataPtr + 2);
            mult_palFadeKeys[i].palIndex = (int16)READ_LE_UINT16(mult_dataPtr + 4);
            mult_palFadeKeys[i].flag = *(mult_dataPtr + 6);
      }

      mult_palKeysCount = READ_LE_UINT16(mult_dataPtr);
      mult_dataPtr += 2;

      mult_palKeys = (Mult_PalKey *)malloc(sizeof(Mult_PalKey) * mult_palKeysCount);
      for (i = 0; i < mult_palKeysCount; i++, mult_dataPtr += 80) {
            mult_palKeys[i].frame = (int16)READ_LE_UINT16(mult_dataPtr);
            mult_palKeys[i].cmd = (int16)READ_LE_UINT16(mult_dataPtr + 2);
            mult_palKeys[i].rates[0] = (int16)READ_LE_UINT16(mult_dataPtr + 4);
            mult_palKeys[i].rates[1] = (int16)READ_LE_UINT16(mult_dataPtr + 6);
            mult_palKeys[i].rates[2] = (int16)READ_LE_UINT16(mult_dataPtr + 8);
            mult_palKeys[i].rates[3] = (int16)READ_LE_UINT16(mult_dataPtr + 10);
            mult_palKeys[i].unknown0 = (int16)READ_LE_UINT16(mult_dataPtr + 12);
            mult_palKeys[i].unknown1 = (int16)READ_LE_UINT16(mult_dataPtr + 14);
            memcpy(mult_palKeys[i].subst, mult_dataPtr + 16, 64);
      }

      mult_textKeysCount = READ_LE_UINT16(mult_dataPtr);
      mult_dataPtr += 2;
      mult_textKeys = (Mult_TextKey *) malloc(sizeof(Mult_TextKey) * mult_textKeysCount);

      for (i = 0; i < mult_textKeysCount; i++, mult_dataPtr += 28) {
            mult_textKeys[i].frame = (int16)READ_LE_UINT16(mult_dataPtr);
            mult_textKeys[i].cmd = (int16)READ_LE_UINT16(mult_dataPtr + 2);
            for (int k = 0; k < 9; ++k)
                  mult_textKeys[i].unknown0[k] = (int16)READ_LE_UINT16(mult_dataPtr + 4 + (k * 2));
            mult_textKeys[i].index = (int16)READ_LE_UINT16(mult_dataPtr + 22);
            mult_textKeys[i].unknown1[0] = (int16)READ_LE_UINT16(mult_dataPtr + 24);
            mult_textKeys[i].unknown1[1] = (int16)READ_LE_UINT16(mult_dataPtr + 26);
      }

      mult_sndKeysCount = READ_LE_UINT16(mult_dataPtr);
      mult_dataPtr += 2;

      mult_sndKeys = (Mult_SndKey *)malloc(sizeof(Mult_SndKey) * mult_sndKeysCount);
      for (i = 0; i < mult_sndKeysCount; i++) {
            mult_sndKeys[i].frame = (int16)READ_LE_UINT16(mult_dataPtr);
            mult_sndKeys[i].cmd = (int16)READ_LE_UINT16(mult_dataPtr + 2);
            mult_sndKeys[i].freq = (int16)READ_LE_UINT16(mult_dataPtr + 4);
            mult_sndKeys[i].channel = (int16)READ_LE_UINT16(mult_dataPtr + 6);
            mult_sndKeys[i].repCount = (int16)READ_LE_UINT16(mult_dataPtr + 8);
            mult_sndKeys[i].resId = (int16)READ_LE_UINT16(mult_dataPtr + 10);
            mult_sndKeys[i].soundIndex = (int16)READ_LE_UINT16(mult_dataPtr + 12);

            mult_sndKeys[i].soundIndex = -1;
            mult_sndKeys[i].resId = -1;
            mult_dataPtr += 36;
            switch (mult_sndKeys[i].cmd) {
            case 1:
            case 4:
                  mult_sndKeys[i].resId = READ_LE_UINT16(inter_execPtr);

                  for (j = 0; j < i; j++) {
                        if (mult_sndKeys[i].resId ==
                            mult_sndKeys[j].resId) {
                              mult_sndKeys[i].soundIndex =
                                  mult_sndKeys[j].soundIndex;
                              inter_execPtr += 2;
                              break;
                        }
                  }
                  if (i == j) {
                        game_interLoadSound(19 - mult_sndSlotsCount);
                        mult_sndKeys[i].soundIndex =
                            19 - mult_sndSlotsCount;
                        mult_sndSlotsCount++;
                  }
                  break;

            case 3:
                  inter_execPtr += 6;
                  break;

            case 5:
                  inter_execPtr += mult_sndKeys[i].freq * 2;
                  break;
            }
      }
}

void mult_freeMultKeys(void) {
      int i;
      char animCount;
      char staticCount;

      mult_dataPtr = mult_multData;
      staticCount = mult_dataPtr[0];
      animCount = mult_dataPtr[1];

      free(mult_dataPtr);

      staticCount++;
      animCount++;
      for (i = 0; i < staticCount; i++) {

            if (mult_staticLoaded[i] != 0)
                  scen_freeStatic(mult_staticIndices[i]);
      }

      for (i = 0; i < animCount; i++) {
            if (mult_animLoaded[i] != 0)
                  scen_freeAnim(mult_animIndices[i]);
      }

      free(mult_staticKeys);

      for (i = 0; i < 4; i++)
            free(mult_animKeys[i]);

      free(mult_palFadeKeys);
      free(mult_palKeys);
      free(mult_textKeys);

      for (i = 0; i < mult_sndSlotsCount; i++) {
            game_freeSoundSlot(19 - i);
      }

      free(mult_sndKeys);

      mult_multData = 0;

      if (mult_animDataAllocated != 0) {
            free(mult_objects);
            mult_objects = 0;

            free(mult_renderData);
            mult_renderData = 0;

            free(mult_animArrayX);
            mult_animArrayX = 0;

            free(mult_animArrayY);
            mult_animArrayY = 0;

            free(mult_animArrayData);
            mult_animArrayData = 0;

            if (anim_underAnimSurf)
                  vid_freeSurfDesc(anim_underAnimSurf);
            anim_underAnimSurf = 0;

            mult_animDataAllocated = 0;
      }
}

void mult_checkFreeMult(void) {
      if (mult_multData != 0)
            mult_freeMultKeys();
}

}                       // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index