scummvm/gob/mult.cpp
Joost Peters f35ac50111 Some inter_variables cleanup.
Now it should store all variables in the native endianness, instead of storing half in LE and the other half in the native endianness.
Addresses and assignments can be tracked by modifying the macros if necessary.
Also, meaningful constants can now be assigned to script variable numbers (if one were so inclined)

svn-id: r17523
2005-04-10 17:13:17 +00:00

1218 lines
31 KiB
C++

/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#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(0, "mult_interInitMult: x = %d, y = %d, w = %d, h = %d",
anim_animAreaLeft, anim_animAreaTop, anim_animAreaWidth, anim_animAreaHeight);
debug(0, " objCount = %d, animation data size = %d", mult_objCount, inter_animDataSize);
}
void mult_freeMult(void) {
if (anim_underAnimSurf != 0)
vid_freeSurfDesc(anim_underAnimSurf);
if (mult_objects != 0)
free(mult_objects);
if (mult_renderData != 0)
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(0, "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 negFreq) {
if (soundDesc->frequency == freq)
snd_playSample(soundDesc, repCount, -negFreq);
else
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) {
if (mult_objects)
free(mult_objects);
mult_objects = 0;
if (mult_renderData)
free(mult_renderData);
mult_renderData = 0;
if (mult_animArrayX)
free(mult_animArrayX);
mult_animArrayX = 0;
if (mult_animArrayY)
free(mult_animArrayY);
mult_animArrayY = 0;
if (mult_animArrayData)
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) {
if (mult_objects)
free(mult_objects);
mult_objects = 0;
if (mult_renderData)
free(mult_renderData);
mult_renderData = 0;
if (mult_animArrayX)
free(mult_animArrayX);
mult_animArrayX = 0;
if (mult_animArrayY)
free(mult_animArrayY);
mult_animArrayY = 0;
if (mult_animArrayData)
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