//Copyright Paul Reiche, Fred Ford. 1992-2002

/*
 *  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.
 */

#include "controls.h"
#include "options.h"
#include "settings.h"
#include "setup.h"
#include "sounds.h"
#include "fmv.h"
#include "resinst.h"
#include "nameref.h"
#include "libs/graphics/gfx_common.h"
#include "libs/graphics/drawable.h"
#include "libs/sound/sound.h"
//#include "libs/vidlib.h"
#include "libs/inplib.h"
#include "libs/log.h"

#include <ctype.h>


typedef struct
{
	/* standard state required by DoInput */
	BOOLEAN (*InputFunc) (PVOID pInputState);
	COUNT MenuRepeatDelay;

	/* Presentation state */
	TimeCount StartTime;
	TimeCount LastSyncTime;
	TimeCount TimeOut;
	int TimeOutOnSkip;
	STRING SlideShow;
	FONT Font;
	FRAME Frame;
	MUSIC_REF MusicRef;
	BOOLEAN Batched;
	FRAME SisFrame;
	FRAME RotatedFrame;
	int LastDrawKind;
	int LastAngle;
	COUNT OperIndex;
	COLOR TextFadeColor;
	COLOR TextColor;
	COLOR TextBackColor;
	int TextVPos;
	RECT clip_r;
	RECT tfade_r;
#define MAX_TEXT_LINES 15
	TEXT TextLines[MAX_TEXT_LINES];
	COUNT LinesCount;
	char Buffer[512];

} PRESENTATION_INPUT_STATE, *PPRESENTATION_INPUT_STATE;


static BOOLEAN DoPresentation (PVOID pIS);


BOOLEAN
DoFMV (const char *name, const char *loopname, BOOLEAN uninit)
{
	VIDEO_REF VidRef;

	VidRef = LoadVideoFile (name);
	if (!VidRef)
		return FALSE;
	VidPlay (VidRef, loopname, uninit);
	VidDoInput ();
	VidStop ();
	DestroyVideo (VidRef);
	
	return TRUE;
}

static BOOLEAN
ParseColorString (const char *Src, COLOR* pColor)
{
	unsigned clr;
	if (1 != sscanf (Src, "%x", &clr))
		return FALSE;

	*pColor = BUILD_COLOR (MAKE_RGB15 (
			(clr >> 19) & 0x1f, (clr >> 11) & 0x1f, (clr >> 3) & 0x1f), 0);
	return TRUE;
}

static BOOLEAN
DoFadeScreen (PRESENTATION_INPUT_STATE* pPIS, const char *Src, BYTE FadeType)
{
	BYTE xform_buf[1] = {FadeType};
	int msecs;
	if (1 == sscanf (Src, "%d", &msecs))
	{
		pPIS->TimeOut = XFormColorMap ((COLORMAPPTR) xform_buf,
				(SIZE)(msecs * ONE_SECOND / 1000)) + ONE_SECOND / 10;
		pPIS->TimeOutOnSkip = FALSE;
	}
	return TRUE;
}

static void
DrawTracedText (TEXT *pText, COLOR Fore, COLOR Back)
{
	SetContextForeGroundColor (Back);
	pText->baseline.x--;
	font_DrawText (pText);
	pText->baseline.x += 2;
	font_DrawText (pText);
	pText->baseline.x--;
	pText->baseline.y--;
	font_DrawText (pText);
	pText->baseline.y += 2;
	font_DrawText (pText);
	pText->baseline.y--;
	SetContextForeGroundColor (Fore);
	font_DrawText (pText);
}

static COUNT
ParseTextLines (TEXT *Lines, COUNT MaxLines, char* Buffer)
{
	COUNT i;
	const char* pEnd = Buffer + strlen (Buffer);

	for (i = 0; i < MaxLines && Buffer < pEnd; ++i, ++Lines)
	{
		char* pTerm = strchr (Buffer, '\n');
		if (!pTerm)
			pTerm = Buffer + strlen (Buffer);
		*pTerm = '\0'; /* terminate string */
		Lines->pStr = Buffer;
		Lines->CharCount = ~0;
		Buffer = pTerm + 1;
	}
	return i;
}

static void
Present_BatchGraphics (PRESENTATION_INPUT_STATE* pPIS)
{
	if (!pPIS->Batched)
	{
		pPIS->Batched = TRUE;
		LockMutex (GraphicsLock);
		BatchGraphics ();
	}
}

static void
Present_UnbatchGraphics (PRESENTATION_INPUT_STATE* pPIS, BOOLEAN bYield)
{
	if (pPIS->Batched)
	{
		UnbatchGraphics ();
		UnlockMutex (GraphicsLock);
		pPIS->Batched = FALSE;
		if (bYield)
			TaskSwitch ();
	}
}

static void
Present_GenerateSIS (PRESENTATION_INPUT_STATE* pPIS)
{
#define MODULE_YOFS_P  (-79)
#define DRIVE_TOP_Y_P  (DRIVE_TOP_Y + MODULE_YOFS_P)
#define JET_TOP_Y_P    (JET_TOP_Y + MODULE_YOFS_P)
#define MODULE_TOP_Y_P (MODULE_TOP_Y + MODULE_YOFS_P)
	CONTEXT	OldContext;
	FRAME SisFrame;
	FRAME ModuleFrame;
	FRAME SkelFrame;
	STAMP s;
	RECT r;
	HOT_SPOT hs;
	int slot;
	COUNT piece;
	COLOR SisBack;

	LockMutex (GraphicsLock);
	OldContext = SetContext (OffScreenContext);

	SkelFrame = CaptureDrawable (LoadGraphic (SISSKEL_MASK_PMAP_ANIM));
	ModuleFrame = CaptureDrawable (LoadGraphic (SISMODS_MASK_PMAP_ANIM));

	GetFrameRect (SkelFrame, &r);
	SisFrame = CaptureDrawable (CreateDrawable (
			WANT_PIXMAP, r.extent.width, r.extent.height, 1
			));
	SetContextFGFrame (SisFrame);
	SetContextClipRect (NULL_PTR);
	SisBack = BUILD_COLOR (MAKE_RGB15 (0x01, 0x01, 0x01), 0x07);
	SetContextBackGroundColor (SisBack);
	ClearDrawable ();
	SetFrameTransparentColor (SisFrame, SisBack);

	s.frame = SetAbsFrameIndex (SkelFrame, 0);
	s.origin.x = 0;
	s.origin.y = 0;
	DrawStamp (&s);

	for (slot = 0; slot < NUM_DRIVE_SLOTS; ++slot)
	{
		piece = GLOBAL_SIS (DriveSlots[slot]);
		if (piece < EMPTY_SLOT)
		{
			s.origin.x = DRIVE_TOP_X;
			s.origin.y = DRIVE_TOP_Y_P;
			s.origin.x += slot * SHIP_PIECE_OFFSET;
			s.frame = SetAbsFrameIndex (ModuleFrame, piece);
			DrawStamp (&s);
		}
	}
	for (slot = 0; slot < NUM_JET_SLOTS; ++slot)
	{
		piece = GLOBAL_SIS (JetSlots[slot]);
		if (piece < EMPTY_SLOT)
		{
			s.origin.x = JET_TOP_X;
			s.origin.y = JET_TOP_Y_P;
			s.origin.x += slot * SHIP_PIECE_OFFSET;
			s.frame = SetAbsFrameIndex (ModuleFrame, piece);
			DrawStamp (&s);
		}
	}
	for (slot = 0; slot < NUM_MODULE_SLOTS; ++slot)
	{
		piece = GLOBAL_SIS (ModuleSlots[slot]);
		if (piece < EMPTY_SLOT)
		{
			s.origin.x = MODULE_TOP_X;
			s.origin.y = MODULE_TOP_Y_P;
			s.origin.x += slot * SHIP_PIECE_OFFSET;
			s.frame = SetAbsFrameIndex (ModuleFrame, piece);
			DrawStamp (&s);
		}
	}

	DestroyDrawable (ReleaseDrawable (SkelFrame));
	DestroyDrawable (ReleaseDrawable (ModuleFrame));

	hs.x = r.extent.width / 2;
	hs.y = r.extent.height / 2;
	SetFrameHot (SisFrame, hs);

	SetContext (OldContext);
	FlushGraphics ();
	UnlockMutex (GraphicsLock);

	pPIS->SisFrame = SisFrame;
}

BOOLEAN
ShowPresentationFile (const char *name)
{
	return ShowPresentation (CaptureStringTable (
			LoadStringTableFile (contentDir, name)));
}

static BOOLEAN
DoPresentation (PVOID pIS)
{
	PRESENTATION_INPUT_STATE* pPIS = (PRESENTATION_INPUT_STATE*) pIS;

	if (PulsedInputState.menu[KEY_MENU_CANCEL]
			|| (GLOBAL (CurrentActivity) & CHECK_ABORT))
		return FALSE; /* abort requested - we are done */

	if (pPIS->TimeOut)
	{
		if (GetTimeCounter () > pPIS->TimeOut)
		{	/* time elapsed - continue normal ops */
			pPIS->TimeOut = 0;
			return TRUE;
		}
		
		if (pPIS->TimeOutOnSkip &&
			(PulsedInputState.menu[KEY_MENU_SELECT]
			|| PulsedInputState.menu[KEY_MENU_SPECIAL]
			|| PulsedInputState.menu[KEY_MENU_RIGHT]) )
		{	/* skip requested - continue normal ops */
			pPIS->TimeOut = 0;
			return TRUE;
		}

		SleepThread (ONE_SECOND / 84);
		return TRUE;
	}

	while (pPIS->OperIndex < GetStringTableCount (pPIS->SlideShow))
	{
		char Opcode[16];

		STRINGPTR pStr = GetStringAddress (pPIS->SlideShow);
		pPIS->OperIndex++;
		pPIS->SlideShow = SetRelStringTableIndex (pPIS->SlideShow, 1);

		if (!pStr)
			continue;
		if (1 != sscanf (pStr, "%15s", Opcode))
			continue;
		pStr += strlen (Opcode);
		if (*pStr != '\0')
			++pStr;
		strupr (Opcode);

		if (strcmp (Opcode, "DIMS") == 0)
		{	/* set dimensions */
			int w, h;
			if (2 == sscanf (pStr, "%d %d", &w, &h))
			{
				pPIS->clip_r.extent.width = w;
				pPIS->clip_r.extent.height = h;
				/* center on screen */
				pPIS->clip_r.corner.x = (SCREEN_WIDTH - w) / 2;
				pPIS->clip_r.corner.y = (SCREEN_HEIGHT - h) / 2;
				LockMutex (GraphicsLock);
				SetContextClipRect (&pPIS->clip_r);
				UnlockMutex (GraphicsLock);
			}
		}
		else if (strcmp (Opcode, "FONT") == 0)
		{	/* set font */
			utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr);
			if (pPIS->Font)
				DestroyFont (ReleaseFont (pPIS->Font));
			pPIS->Font = CaptureFont ((FONT_REF) LoadFontFile (pPIS->Buffer));

			if (!pPIS->Batched)
				LockMutex (GraphicsLock);
			SetContextFont (pPIS->Font);
			if (!pPIS->Batched)
				UnlockMutex (GraphicsLock);
		}
		else if (strcmp (Opcode, "ANI") == 0)
		{	/* set ani */
			utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr);
			if (pPIS->Frame)
				DestroyDrawable (ReleaseDrawable (pPIS->Frame));
			pPIS->Frame = CaptureDrawable (LoadCelFile (pPIS->Buffer));
		}
		else if (strcmp (Opcode, "MUSIC") == 0)
		{	/* set music */
			utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr);
			if (pPIS->MusicRef)
			{
				StopMusic ();
				DestroyMusic (pPIS->MusicRef);
			}
			pPIS->MusicRef = LoadMusicFile (pPIS->Buffer);
			PlayMusic (pPIS->MusicRef, FALSE, 1);
		}
		else if (strcmp (Opcode, "WAIT") == 0)
		{	/* wait */
			int msecs;
			Present_UnbatchGraphics (pPIS, TRUE);
			if (1 == sscanf (pStr, "%d", &msecs))
			{
				pPIS->TimeOut = GetTimeCounter ()
						+ msecs * ONE_SECOND / 1000;
				pPIS->TimeOutOnSkip = TRUE;
				return TRUE;
			}
		}
		else if (strcmp (Opcode, "SYNC") == 0)
		{	/* absolute time-sync */
			int msecs;
			Present_UnbatchGraphics (pPIS, TRUE);
			if (1 == sscanf (pStr, "%d", &msecs))
			{
				pPIS->LastSyncTime = pPIS->StartTime
						+ msecs * ONE_SECOND / 1000;
				pPIS->TimeOut = pPIS->LastSyncTime;
				pPIS->TimeOutOnSkip = FALSE;
				return TRUE;
			}
		}
		else if (strcmp (Opcode, "RESYNC") == 0)
		{	/* flush and update absolute sync point */
			pPIS->LastSyncTime = pPIS->StartTime = GetTimeCounter ();
		}
		else if (strcmp (Opcode, "DSYNC") == 0)
		{	/* delta time-sync; from the last absolute sync */
			int msecs;
			Present_UnbatchGraphics (pPIS, TRUE);
			if (1 == sscanf (pStr, "%d", &msecs))
			{
				pPIS->TimeOut = pPIS->LastSyncTime
						+ msecs * ONE_SECOND / 1000;
				pPIS->TimeOutOnSkip = FALSE;
				return TRUE;
			}
		}
		else if (strcmp (Opcode, "TC") == 0)
		{	/* text fore color */
			ParseColorString (pStr, &pPIS->TextColor);
		}
		else if (strcmp (Opcode, "TBC") == 0)
		{	/* text back color */
			ParseColorString (pStr, &pPIS->TextBackColor);
		}
		else if (strcmp (Opcode, "TFC") == 0)
		{	/* text fade color */
			ParseColorString (pStr, &pPIS->TextFadeColor);
		}
		else if (strcmp (Opcode, "TVA") == 0)
		{	/* text vertical align */
			pPIS->TextVPos = toupper (*pStr);
		}
		else if (strcmp (Opcode, "TEXT") == 0)
		{	/* simple text draw */
			SIZE leading;
			COUNT i;
			COORD y;
			
			utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr);
			pPIS->LinesCount = ParseTextLines (pPIS->TextLines,
					MAX_TEXT_LINES, pPIS->Buffer);
			
			if (!pPIS->Batched)
				LockMutex (GraphicsLock);
			GetContextFontLeading (&leading);
			if (!pPIS->Batched)
				UnlockMutex (GraphicsLock);
			switch (pPIS->TextVPos)
			{
			case 'T': /* top */
				y = leading;
				break;
			case 'M': /* middle */
				y = (pPIS->clip_r.extent.height
						- pPIS->LinesCount * leading) / 2;
				break;
			default: /* bottom */
				y = pPIS->clip_r.extent.height - pPIS->LinesCount * leading;
			}
			for (i = 0; i < pPIS->LinesCount; ++i, y += leading)
			{
				pPIS->TextLines[i].align = ALIGN_CENTER;
				pPIS->TextLines[i].baseline.x = SCREEN_WIDTH / 2;
				pPIS->TextLines[i].baseline.y = y;
			}

			if (!pPIS->Batched)
				LockMutex (GraphicsLock);
			SetContextClipping (TRUE);
			for (i = 0; i < pPIS->LinesCount; ++i)
				DrawTracedText (pPIS->TextLines + i,
						pPIS->TextColor, pPIS->TextBackColor);
			if (!pPIS->Batched)
				UnlockMutex (GraphicsLock);
		}
		else if (strcmp (Opcode, "TFI") == 0)
		{	/* text fade-in */
			SIZE leading;
			COUNT i;
			COORD y;
			
			utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr);
			pPIS->LinesCount = ParseTextLines (pPIS->TextLines,
					MAX_TEXT_LINES, pPIS->Buffer);
			
			Present_UnbatchGraphics (pPIS, TRUE);

			LockMutex (GraphicsLock);
			GetContextFontLeading (&leading);
			UnlockMutex (GraphicsLock);

			switch (pPIS->TextVPos)
			{
			case 'T': /* top */
				y = leading;
				break;
			case 'M': /* middle */
				y = (pPIS->clip_r.extent.height
						- pPIS->LinesCount * leading) / 2;
				break;
			default: /* bottom */
				y = pPIS->clip_r.extent.height - pPIS->LinesCount * leading;
			}
			pPIS->tfade_r = pPIS->clip_r;
			pPIS->tfade_r.corner.y += y - leading;
			pPIS->tfade_r.extent.height = (pPIS->LinesCount + 1) * leading;
			for (i = 0; i < pPIS->LinesCount; ++i, y += leading)
			{
				pPIS->TextLines[i].align = ALIGN_CENTER;
				pPIS->TextLines[i].baseline.x = SCREEN_WIDTH / 2;
				pPIS->TextLines[i].baseline.y = y;
			}

			LockMutex (GraphicsLock);
			SetContextClipping (TRUE);
			for (i = 0; i < pPIS->LinesCount; ++i)
				DrawTracedText (pPIS->TextLines + i,
						pPIS->TextFadeColor, pPIS->TextFadeColor);

			/* do transition */
			SetTransitionSource (&pPIS->tfade_r);
			BatchGraphics ();
			for (i = 0; i < pPIS->LinesCount; ++i)
				DrawTracedText (pPIS->TextLines + i,
						pPIS->TextColor, pPIS->TextBackColor);
			ScreenTransition (3, &pPIS->tfade_r);
			UnbatchGraphics ();
			
			UnlockMutex (GraphicsLock);
		}
		else if (strcmp (Opcode, "TFO") == 0)
		{	/* text fade-out */
			COUNT i;
			
			Present_UnbatchGraphics (pPIS, TRUE);

			LockMutex (GraphicsLock);
			SetContextClipping (TRUE);
			/* do transition */
			SetTransitionSource (&pPIS->tfade_r);
			BatchGraphics ();
			for (i = 0; i < pPIS->LinesCount; ++i)
				DrawTracedText (pPIS->TextLines + i,
						pPIS->TextFadeColor, pPIS->TextFadeColor);
			ScreenTransition (3, &pPIS->tfade_r);
			UnbatchGraphics ();
			UnlockMutex (GraphicsLock);
		}
		else if (strcmp (Opcode, "SAVEBG") == 0)
		{	/* save background */
			TFB_DrawScreen_Copy (&pPIS->clip_r,
					TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA);
		}
		else if (strcmp (Opcode, "RESTBG") == 0)
		{	/* restore background */
			TFB_DrawScreen_Copy (&pPIS->clip_r,
					TFB_SCREEN_EXTRA, TFB_SCREEN_MAIN);
		}
		else if (strcmp (Opcode, "DRAW") == 0)
		{	/* draw a graphic */
#define PRES_DRAW_INDEX 0
#define PRES_DRAW_SIS   1
			int cargs;
			int draw_what;
			int index, x, y, scale, angle;
			char ImgName[16];
			int OldScale;
			STAMP s;

			if (1 == sscanf (pStr, "%15s", ImgName)
					&& strcmp (strupr (ImgName), "SIS") == 0)
			{
				draw_what = PRES_DRAW_SIS;
				cargs = sscanf (pStr, "%*s %d %d %d %d",
							&x, &y, &scale, &angle) + 1;
			}
			else
			{
				draw_what = PRES_DRAW_INDEX;
				cargs = sscanf (pStr, "%d %d %d %d %d",
							&index, &x, &y, &scale, &angle);
			}

			if (cargs < 1)
			{
				log_add (log_Warning, "Bad DRAW command '%s'", pStr);
				continue;
			}
			if (cargs < 5)
				angle = 0;
			if (cargs < 4)
				scale = GSCALE_IDENTITY;
			if (cargs < 3)
			{
				x = 0;
				y = 0;
			}

			if (draw_what == PRES_DRAW_INDEX)
			{	/* draw stamp by index */
				s.frame = SetAbsFrameIndex (pPIS->Frame, (COUNT)index);
			}
			else if (draw_what == PRES_DRAW_SIS)
			{	/* draw dynamic SIS image with player's modules */
				if (!pPIS->SisFrame)
					Present_GenerateSIS (pPIS);

				s.frame = SetAbsFrameIndex (pPIS->SisFrame, 0);
			}
			if (angle != 0)
			{
				if (angle != pPIS->LastAngle
						|| draw_what != pPIS->LastDrawKind)
				{
					DestroyDrawable (ReleaseDrawable (pPIS->RotatedFrame));
					pPIS->RotatedFrame = CaptureDrawable (
							RotateFrame (s.frame, DEGREES_TO_ANGLE (angle)));
					pPIS->LastAngle = angle;
					pPIS->LastDrawKind = draw_what;
				}
				s.frame = pPIS->RotatedFrame;
			}
			s.origin.x = x;
			s.origin.y = y;
			if (!pPIS->Batched)
				LockMutex (GraphicsLock);
			OldScale = GetGraphicScale ();
			SetGraphicScale (scale);
			SetContextClipping (TRUE);
			DrawStamp (&s);
			SetGraphicScale (OldScale);
			if (!pPIS->Batched)
				UnlockMutex (GraphicsLock);
		}
		else if (strcmp (Opcode, "BATCH") == 0)
		{	/* batch graphics */
			Present_BatchGraphics (pPIS);
		}
		else if (strcmp (Opcode, "UNBATCH") == 0)
		{	/* unbatch graphics */
			Present_UnbatchGraphics (pPIS, FALSE);
		}
		else if (strcmp (Opcode, "FTC") == 0)
		{	/* fade to color */
			Present_UnbatchGraphics (pPIS, TRUE);
			return DoFadeScreen (pPIS, pStr, FadeAllToColor);
		}
		else if (strcmp (Opcode, "FTB") == 0)
		{	/* fade to black */
			Present_UnbatchGraphics (pPIS, TRUE);
			return DoFadeScreen (pPIS, pStr, FadeAllToBlack);
		}
		else if (strcmp (Opcode, "FTW") == 0)
		{	/* fade to white */
			Present_UnbatchGraphics (pPIS, TRUE);
			return DoFadeScreen (pPIS, pStr, FadeAllToWhite);
		}
		else if (strcmp (Opcode, "CLS") == 0)
		{	/* clear screen */
			RECT r;

			Present_UnbatchGraphics (pPIS, TRUE);

			LockMutex (GraphicsLock);
			GetContextClipRect (&r);
			r.corner.x = r.corner.y = 0;
			/* paint black rect over screen	*/
			SetContextForeGroundColor (
					BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00));
			DrawFilledRectangle (&r);	
			UnlockMutex (GraphicsLock);
		}
		else if (strcmp (Opcode, "CALL") == 0)
		{	/* call another script */
			Present_UnbatchGraphics (pPIS, TRUE);

			utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr);
			ShowPresentationFile (pPIS->Buffer);
		}
		else if (strcmp (Opcode, "NOOP") == 0)
		{	/* no operation - must be a comment in script */
			/* do nothing */
		}
	}
	/* we are all done */
	return FALSE;
}

BOOLEAN
ShowPresentation (STRING PresStr)
{
	CONTEXT OldContext;
	FONT OldFont;
	RECT OldRect;
	PRESENTATION_INPUT_STATE pis;

	pis.SlideShow = PresStr;
	if (!pis.SlideShow)
		return FALSE;
	pis.SlideShow = SetAbsStringTableIndex (pis.SlideShow, 0);
	pis.OperIndex = 0;

	LockMutex (GraphicsLock);
	OldContext = SetContext (ScreenContext);
	GetContextClipRect (&OldRect);
	OldFont = SetContextFont (NULL);
	/* paint black rect over screen	*/
	SetContextBackGroundColor (
			BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00));
	ClearDrawable ();
	UnlockMutex (GraphicsLock);

	FlushInput ();
	SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
	pis.MenuRepeatDelay = 0;
	pis.InputFunc = DoPresentation;
	pis.Font = 0;
	pis.Frame = 0;
	pis.RotatedFrame = 0;
	pis.LastDrawKind = -1;
	pis.LastAngle = 0;
	pis.MusicRef = 0;
	pis.SisFrame = 0;
	pis.Batched = FALSE;
	pis.TextVPos = 'B';
	pis.LastSyncTime = pis.StartTime = GetTimeCounter ();
	pis.TimeOut = 0;
	DoInput (&pis, TRUE);

	SleepThreadUntil (FadeMusic (0, ONE_SECOND));
	StopMusic ();
	FadeMusic (NORMAL_VOLUME, 0);

	DestroyMusic (pis.MusicRef);
	DestroyDrawable (ReleaseDrawable (pis.RotatedFrame));
	DestroyDrawable (ReleaseDrawable (pis.Frame));
	DestroyFont (ReleaseFont (pis.Font));
	DestroyStringTable (ReleaseStringTable (pis.SlideShow));

	LockMutex (GraphicsLock);
	SetContextFont (OldFont);
	SetContextClipRect (&OldRect);
	SetContext (OldContext);
	UnlockMutex (GraphicsLock);

	return TRUE;
}


