rem: ClearSubtitle = FALSE;
context: int ambient_anim_task(void* data){	SIZE TalkAlarm;	FRAME TalkFrame;	FRAME ResetTalkFrame = NULL;	FRAME TransitionFrame = NULL;	FRAME AnimFrame[MAX_ANIMATIONS];	COUNT i;	DWORD LastTime;	FRAME CommFrame;	SEQUENCE Sequencer[MAX_ANIMATIONS];	ANIMATION_DESC TalkBuffer = CommData.AlienTalkDesc;	PSEQUENCE pSeq;	ANIMATION_DESCPTR ADPtr;	DWORD ActiveMask;	DWORD LastOscillTime;	Task task = (Task) data;	BOOLEAN TransitionDone = FALSE;	BOOLEAN TalkFrameChanged = FALSE;	BOOLEAN FrameChanged[MAX_ANIMATIONS];	while ((CommFrame = CommData.AlienFrame) == 0 && !Task_ReadState (task, TASK_EXIT))		TaskSwitch ();	SetSemaphore (GraphicsSem);	memset ((PSTR)&DisplayArray[0], 0, sizeof (DisplayArray));	SetUpSequence (Sequencer);	ClearSemaphore (GraphicsSem);	ActiveMask = 0;	TalkAlarm = 0;	TalkFrame = 0;	LastTime = GetTimeCounter ();	LastOscillTime = LastTime;	memset (&FrameChanged[0], 0 , MAX_ANIMATIONS);	memset (&AnimFrame[0], 0, sizeof (FRAME) * MAX_ANIMATIONS);	for (i = 0; i <= CommData.NumAnimations; i++)		if (CommData.AlienAmbientArray[i].AnimFlags & YOYO_ANIM)			AnimFrame[i] =  SetAbsFrameIndex (					CommFrame,					CommData.AlienAmbientArray[i].StartIndex					);		else			AnimFrame[i] =  SetAbsFrameIndex (					CommFrame,					(COUNT)(CommData.AlienAmbientArray[i].StartIndex					+ CommData.AlienAmbientArray[i].NumFrames - 1)					);	while (!Task_ReadState (task, TASK_EXIT))	{		BOOLEAN Change, CanTalk;		DWORD CurTime, ElapsedTicks;		SleepThreadUntil (LastTime + ONE_SECOND / 120);		SetSemaphore (GraphicsSem);		BatchGraphics ();		CurTime = GetTimeCounter ();		ElapsedTicks = CurTime - LastTime;		LastTime = CurTime;		Change = FALSE;		i = CommData.NumAnimations;		if (CommData.AlienFrame)			CanTalk = TRUE;		else		{			i = 0;			CanTalk = FALSE;		}		pSeq = &Sequencer[i];		ADPtr = &CommData.AlienAmbientArray[i];		while (i-- && !Task_ReadState (task, TASK_EXIT))		{			--ADPtr;			--pSeq;			if (ADPtr->AnimFlags & ANIM_DISABLED)				continue;			if (pSeq->Direction == NO_DIR)			{				if (!(ADPtr->AnimFlags						& CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING))					pSeq->Direction = UP_DIR;			}			else if ((DWORD)pSeq->Alarm > ElapsedTicks)				pSeq->Alarm -= (COUNT)ElapsedTicks;			else			{				if (!(ActiveMask & ADPtr->BlockMask)						&& (--pSeq->FramesLeft						|| ((ADPtr->AnimFlags & YOYO_ANIM)						&& pSeq->Direction == UP_DIR)))				{					ActiveMask |= 1L << i;					pSeq->Alarm =							ADPtr->BaseFrameRate							+ ((COUNT)TFB_Random ()							% (ADPtr->RandomFrameRate + 1))							+ 1;				}				else				{					ActiveMask &= ~(1L << i);					pSeq->Alarm =							ADPtr->BaseRestartRate							+ ((COUNT)TFB_Random ()							% (ADPtr->RandomRestartRate + 1))							+ 1;					if (ActiveMask & ADPtr->BlockMask)						continue;				}				if (pSeq->AnimType == COLOR_ANIM)				{					XFormPLUT (							GetColorMapAddress (pSeq->AnimObj.CurCMap),							(COUNT) (pSeq->Alarm - 1)							);				}				else				{					Change = TRUE;					AnimFrame[i] = pSeq->AnimObj.CurFrame;					FrameChanged[i] = 1;				}				if (pSeq->FramesLeft == 0)				{					pSeq->FramesLeft = (BYTE)(ADPtr->NumFrames - 1);					if (pSeq->Direction == DOWN_DIR)						pSeq->Direction = UP_DIR;					else if (ADPtr->AnimFlags & YOYO_ANIM)						pSeq->Direction = DOWN_DIR;					else					{						++pSeq->FramesLeft;						if (pSeq->AnimType == COLOR_ANIM)							pSeq->AnimObj.CurCMap = SetRelColorMapIndex (									pSeq->AnimObj.CurCMap,									(SWORD) (-pSeq->FramesLeft)									);						else						{							pSeq->AnimObj.CurFrame = SetRelFrameIndex (									pSeq->AnimObj.CurFrame,									(SWORD) (-pSeq->FramesLeft)									);						}					}				}				if (ADPtr->AnimFlags & RANDOM_ANIM)				{					if (pSeq->AnimType == COLOR_ANIM)						pSeq->AnimObj.CurCMap =								SetAbsColorMapIndex (pSeq->AnimObj.CurCMap,								(COUNT) (ADPtr->StartIndex								+ ((COUNT)TFB_Random ()								% ADPtr->NumFrames)));					else						pSeq->AnimObj.CurFrame =								SetAbsFrameIndex (pSeq->AnimObj.CurFrame,								(COUNT) (ADPtr->StartIndex								+ ((COUNT)TFB_Random ()								% ADPtr->NumFrames)));				}				else if (pSeq->AnimType == COLOR_ANIM)				{					if (pSeq->Direction == UP_DIR)						pSeq->AnimObj.CurCMap = SetRelColorMapIndex (								pSeq->AnimObj.CurCMap, 1								);					else						pSeq->AnimObj.CurCMap = SetRelColorMapIndex (								pSeq->AnimObj.CurCMap, -1								);				}				else				{					if (pSeq->Direction == UP_DIR)						pSeq->AnimObj.CurFrame =								IncFrameIndex (pSeq->AnimObj.CurFrame);					else						pSeq->AnimObj.CurFrame =								DecFrameIndex (pSeq->AnimObj.CurFrame);				}			}			if (pSeq->AnimType == PICTURE_ANIM					&& (ADPtr->AnimFlags					& CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING)					&& pSeq->Direction != NO_DIR)			{				COUNT index;				CanTalk = FALSE;				if (!(pSeq->Direction != UP_DIR						|| (index = GetFrameIndex (pSeq->AnimObj.CurFrame)) >						ADPtr->StartIndex + 1						|| (index == ADPtr->StartIndex + 1						&& (ADPtr->AnimFlags & CIRCULAR_ANIM))))					pSeq->Direction = NO_DIR;			}		}		ADPtr = &CommData.AlienTalkDesc;		if (CanTalk				&& ADPtr->NumFrames				&& (ADPtr->AnimFlags & WAIT_TALKING)				&& !(CommData.AlienTransitionDesc.AnimFlags & PAUSE_TALKING))		{			BOOLEAN done = 0;			for (i = 0; i < CommData.NumAnimations; i++)				if (ActiveMask & (1L << i) 					&& CommData.AlienAmbientArray[i].AnimFlags & WAIT_TALKING)					done = 1;			if (! done)			{				if (ADPtr->StartIndex != TalkBuffer.StartIndex)				{					Change = TRUE;					ResetTalkFrame = SetAbsFrameIndex (CommFrame,							TalkBuffer.StartIndex);					TalkBuffer = CommData.AlienTalkDesc;				}				if ((long)TalkAlarm > (long)ElapsedTicks)					TalkAlarm -= (SIZE)ElapsedTicks;				else				{					BYTE AFlags;					SIZE FrameRate;					if (TalkAlarm > 0)						TalkAlarm = 0;					else						TalkAlarm = -1;					AFlags = ADPtr->AnimFlags;					if (!(AFlags & (TALK_INTRO | TALK_DONE)))					{						FrameRate =								ADPtr->BaseFrameRate								+ ((COUNT)TFB_Random ()								% (ADPtr->RandomFrameRate + 1));						if (TalkAlarm < 0								|| GetFrameIndex (TalkFrame) ==								ADPtr->StartIndex)						{							TalkFrame = SetAbsFrameIndex (CommFrame,									(COUNT) (ADPtr->StartIndex + 1									+ ((COUNT)TFB_Random ()									% (ADPtr->NumFrames - 1))));							FrameRate +=									ADPtr->BaseRestartRate									+ ((COUNT)TFB_Random ()									% (ADPtr->RandomRestartRate + 1));						}						else						{							TalkFrame = SetAbsFrameIndex (CommFrame,									ADPtr->StartIndex);							if (ADPtr->AnimFlags & PAUSE_TALKING)							{								if (!(CommData.AlienTransitionDesc.AnimFlags										& TALK_DONE))								{									CommData.AlienTransitionDesc.AnimFlags |=											PAUSE_TALKING;									ADPtr->AnimFlags &=											~PAUSE_TALKING;								}								else if (CommData.AlienTransitionDesc.NumFrames)									ADPtr->AnimFlags |=											TALK_DONE;								else									ADPtr->AnimFlags &=											~(WAIT_TALKING | PAUSE_TALKING);								FrameRate = 0;							}						}					}					else					{						ADPtr = &CommData.AlienTransitionDesc;						if (AFlags & TALK_INTRO)						{							FrameRate =									ADPtr->BaseFrameRate									+ ((COUNT)TFB_Random ()									% (ADPtr->RandomFrameRate + 1));							if (TalkAlarm < 0 || TransitionDone)							{								TalkFrame = SetAbsFrameIndex (CommFrame,										ADPtr->StartIndex);								TransitionDone = 0;							}							else								TalkFrame = IncFrameIndex (TalkFrame);							if ((BYTE)(GetFrameIndex (TalkFrame)									- ADPtr->StartIndex + 1) ==									ADPtr->NumFrames)							{								CommData.AlienTalkDesc.AnimFlags &= ~TALK_INTRO;								TransitionDone = 1;							}							TransitionFrame = TalkFrame;						}						else /* if (AFlags & TALK_DONE) */						{							FrameRate =									ADPtr->BaseFrameRate									+ ((COUNT)TFB_Random ()									% (ADPtr->RandomFrameRate + 1));							if (TalkAlarm < 0)								TalkFrame = SetAbsFrameIndex (CommFrame,										(COUNT) (ADPtr->StartIndex										+ ADPtr->NumFrames - 1));							else								TalkFrame = DecFrameIndex (TalkFrame);							if (GetFrameIndex (TalkFrame) ==									ADPtr->StartIndex)							{								CommData.AlienTalkDesc.AnimFlags &=										~(PAUSE_TALKING | TALK_DONE);								if (ADPtr->AnimFlags & TALK_INTRO)									CommData.AlienTalkDesc.AnimFlags &= ~WAIT_TALKING;								else								{									ADPtr->AnimFlags |=											PAUSE_TALKING;									ADPtr->AnimFlags &= ~TALK_DONE;								}								FrameRate = 0;							}							TransitionFrame = NULL;						}					}					TalkFrameChanged = TRUE;					Change = TRUE;					TalkAlarm = FrameRate;				}			}		}		{			CONTEXT OldContext;			BOOLEAN CheckSub = 0;			OldContext = SetContext (TaskContext);			if (ColorChange)			{				FRAME F;				F = CommData.AlienFrame;				CommData.AlienFrame = CommFrame;				DrawAlienFrame (TalkFrame, &Sequencer[CommData.NumAnimations - 1]);				CommData.AlienFrame = F;				ColorChange = FALSE;				ClearSubtitle = FALSE;				CheckSub = 1;			}			if (Change || ClearSubtitle)			{				STAMP s;				s.origin.x = -SAFE_X;				s.origin.y = 0;				if (ClearSubtitle)				{					s.frame = CommFrame;					DrawStamp (&s);				}				i = CommData.NumAnimations;				while (i--)				{					if ((ClearSubtitle || FrameChanged[i]))					{						s.frame = AnimFrame[i];						DrawStamp (&s);						FrameChanged[i] = 0;					}				}				if (ClearSubtitle && TransitionFrame)				{					s.frame = TransitionFrame;					DrawStamp (&s);				}				if (ResetTalkFrame)				{					s.frame = ResetTalkFrame;					DrawStamp (&s);					ResetTalkFrame = NULL;				}				if (TalkFrame && TalkFrameChanged)				{					s.frame = TalkFrame;					DrawStamp (&s);					TalkFrameChanged = FALSE;				}				ClearSubtitle = FALSE;				Change = FALSE;				CheckSub = 1;			}			if (CheckSub && subtitle_state >= SPACE_SUBTITLE)			{				TEXT t;				t = CommData.AlienTextTemplate;				add_text (1, &t);			}			SetContext (OldContext);		}		if (LastOscillTime + (ONE_SECOND / 32) < CurTime)		{			LastOscillTime = CurTime;			UpdateSpeechGraphics (FALSE);		}		UnbatchGraphics ();		ClearSemaphore (GraphicsSem);		xform_PLUT_step(ElapsedTicks);	}	FinishTask (task);	return(0);}