summaryrefslogtreecommitdiff
path: root/src/uqm/intro.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/intro.c')
-rw-r--r--src/uqm/intro.c875
1 files changed, 875 insertions, 0 deletions
diff --git a/src/uqm/intro.c b/src/uqm/intro.c
new file mode 100644
index 0000000..092c428
--- /dev/null
+++ b/src/uqm/intro.c
@@ -0,0 +1,875 @@
+//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 "globdata.h"
+#include "sis.h"
+#include "setup.h"
+#include "sounds.h"
+#include "colors.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/log.h"
+
+#include <ctype.h>
+
+static BOOLEAN ShowSlidePresentation (STRING PresStr);
+
+typedef struct
+{
+ /* standard state required by DoInput */
+ BOOLEAN (*InputFunc) (void *pInputState);
+
+ /* Presentation state */
+ TimeCount StartTime;
+ TimeCount LastSyncTime;
+ TimeCount TimeOut;
+ int TimeOutOnSkip;
+ STRING SlideShow;
+#define MAX_FONTS 5
+ FONT Fonts[MAX_FONTS];
+ 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;
+ int TextEffect;
+ RECT clip_r;
+ RECT tfade_r;
+#define MAX_TEXT_LINES 15
+ TEXT TextLines[MAX_TEXT_LINES];
+ COUNT LinesCount;
+ char Buffer[512];
+ int MovieFrame;
+ int MovieEndFrame;
+ int InterframeDelay;
+
+} PRESENTATION_INPUT_STATE;
+
+typedef struct {
+ /* standard state required by DoInput */
+ BOOLEAN (*InputFunc) (void *pInputState);
+
+ /* Spinanim state */
+ STAMP anim;
+ TimeCount last_time;
+ int debounce;
+} SPINANIM_INPUT_STATE;
+
+typedef struct
+{
+ // standard state required by DoInput
+ BOOLEAN (*InputFunc) (void *pInputState);
+
+ LEGACY_VIDEO_REF CurVideo;
+
+} VIDEO_INPUT_STATE;
+
+static BOOLEAN DoPresentation (void *pIS);
+
+static BOOLEAN
+ParseColorString (const char *Src, Color* pColor)
+{
+ unsigned clr;
+ if (1 != sscanf (Src, "%x", &clr))
+ return FALSE;
+
+ *pColor = BUILD_COLOR_RGBA (
+ (clr >> 16) & 0xff, (clr >> 8) & 0xff, clr & 0xff, 0);
+ return TRUE;
+}
+
+static BOOLEAN
+DoFadeScreen (PRESENTATION_INPUT_STATE* pPIS, const char *Src, BYTE FadeType)
+{
+ int msecs;
+ if (1 == sscanf (Src, "%d", &msecs))
+ {
+ pPIS->TimeOut = FadeScreen (FadeType, msecs * ONE_SECOND / 1000)
+ + ONE_SECOND / 10;
+ pPIS->TimeOutOnSkip = FALSE;
+ }
+ return TRUE;
+}
+
+static void
+DrawTextEffect (TEXT *pText, Color Fore, Color Back, int Effect)
+{
+ if (Effect == 'T')
+ {
+ font_DrawTracedText (pText, Fore, Back);
+ }
+ else
+ {
+ 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;
+ BatchGraphics ();
+ }
+}
+
+static void
+Present_UnbatchGraphics (PRESENTATION_INPUT_STATE* pPIS, BOOLEAN bYield)
+{
+ if (pPIS->Batched)
+ {
+ UnbatchGraphics ();
+ 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;
+
+ 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);
+ 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 ();
+
+ pPIS->SisFrame = SisFrame;
+}
+
+static void
+Present_DrawMovieFrame (PRESENTATION_INPUT_STATE* pPIS)
+{
+ STAMP s;
+
+ s.origin.x = 0;
+ s.origin.y = 0;
+ s.frame = SetAbsFrameIndex (pPIS->Frame, pPIS->MovieFrame);
+ DrawStamp (&s);
+}
+
+static BOOLEAN
+ShowPresentationFile (const char *name)
+{
+ STRING pres = CaptureStringTable (LoadStringTableFile (contentDir, name));
+ BOOLEAN result = ShowSlidePresentation (pres);
+ DestroyStringTable (ReleaseStringTable (pres));
+ return result;
+}
+
+static BOOLEAN
+DoPresentation (void *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)
+ {
+ TimeCount Delay = ONE_SECOND / 84;
+
+ if (GetTimeCounter () >= pPIS->TimeOut)
+ {
+ if (pPIS->MovieFrame >= 0)
+ { /* Movie mode */
+ Present_DrawMovieFrame (pPIS);
+ ++pPIS->MovieFrame;
+ if (pPIS->MovieFrame > pPIS->MovieEndFrame)
+ pPIS->MovieFrame = -1; /* movie is done */
+ Delay = pPIS->InterframeDelay;
+ }
+ else
+ { /* 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;
+ pPIS->MovieFrame = -1; /* abort any movie in progress */
+ return TRUE;
+ }
+
+ SleepThread (Delay);
+ return TRUE;
+ }
+
+ while (pPIS->OperIndex < GetStringTableCount (pPIS->SlideShow))
+ {
+ char Opcode[16];
+ char *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;
+ SetContextClipRect (&pPIS->clip_r);
+ }
+ }
+ else if (strcmp (Opcode, "FONT") == 0)
+ { /* set and/or load a font */
+ int index;
+ FONT *pFont;
+
+ assert (sizeof (pPIS->Buffer) >= 256);
+
+ pPIS->Buffer[0] = '\0';
+ if (1 > sscanf (pStr, "%d %255[^\n]", &index, pPIS->Buffer) ||
+ index < 0 || index >= MAX_FONTS)
+ {
+ log_add (log_Warning, "Bad FONT command '%s'", pStr);
+ continue;
+ }
+ pFont = &pPIS->Fonts[index];
+
+ if (pPIS->Buffer[0])
+ { /* asked to load a font */
+ if (*pFont)
+ DestroyFont (*pFont);
+ *pFont = LoadFontFile (pPIS->Buffer);
+ }
+
+ SetContextFont (*pFont);
+ }
+ 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 (LoadGraphicFile (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, "TE") == 0)
+ { /* text vertical align */
+ pPIS->TextEffect = toupper (*pStr);
+ }
+ else if (strcmp (Opcode, "TEXT") == 0)
+ { /* simple text draw */
+ int x, y;
+
+ assert (sizeof (pPIS->Buffer) >= 256);
+
+ if (3 == sscanf (pStr, "%d %d %255[^\n]", &x, &y, pPIS->Buffer))
+ {
+ TEXT t;
+
+ t.align = ALIGN_CENTER;
+ t.pStr = pPIS->Buffer;
+ t.CharCount = (COUNT)~0;
+ t.baseline.x = x;
+ t.baseline.y = y;
+ DrawTextEffect (&t, pPIS->TextColor, pPIS->TextBackColor,
+ pPIS->TextEffect);
+ }
+ }
+ 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);
+
+ GetContextFontLeading (&leading);
+
+ 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;
+ }
+
+ for (i = 0; i < pPIS->LinesCount; ++i)
+ DrawTextEffect (pPIS->TextLines + i, pPIS->TextFadeColor,
+ pPIS->TextFadeColor, pPIS->TextEffect);
+
+ /* do transition */
+ SetTransitionSource (&pPIS->tfade_r);
+ BatchGraphics ();
+ for (i = 0; i < pPIS->LinesCount; ++i)
+ DrawTextEffect (pPIS->TextLines + i, pPIS->TextColor,
+ pPIS->TextBackColor, pPIS->TextEffect);
+ ScreenTransition (3, &pPIS->tfade_r);
+ UnbatchGraphics ();
+
+ }
+ else if (strcmp (Opcode, "TFO") == 0)
+ { /* text fade-out */
+ COUNT i;
+
+ Present_UnbatchGraphics (pPIS, TRUE);
+
+ /* do transition */
+ SetTransitionSource (&pPIS->tfade_r);
+ BatchGraphics ();
+ for (i = 0; i < pPIS->LinesCount; ++i)
+ DrawTextEffect (pPIS->TextLines + i, pPIS->TextFadeColor,
+ pPIS->TextFadeColor, pPIS->TextEffect);
+ ScreenTransition (3, &pPIS->tfade_r);
+ UnbatchGraphics ();
+ }
+ 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 = 0;
+ int x, y;
+ int scale;
+ int angle;
+ int scale_mode;
+ char ImgName[16];
+ int old_scale, old_mode;
+ STAMP s;
+
+ if (1 == sscanf (pStr, "%15s", ImgName)
+ && strcmp (strupr (ImgName), "SIS") == 0)
+ {
+ draw_what = PRES_DRAW_SIS;
+ scale_mode = TFB_SCALE_NEAREST;
+ cargs = sscanf (pStr, "%*s %d %d %d %d",
+ &x, &y, &scale, &angle) + 1;
+ }
+ else
+ {
+ draw_what = PRES_DRAW_INDEX;
+ scale_mode = TFB_SCALE_BILINEAR;
+ 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;
+ }
+
+ s.frame = NULL;
+ 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, -angle));
+ pPIS->LastAngle = angle;
+ pPIS->LastDrawKind = draw_what;
+ }
+ s.frame = pPIS->RotatedFrame;
+ }
+ s.origin.x = x;
+ s.origin.y = y;
+ old_mode = SetGraphicScaleMode (scale_mode);
+ old_scale = SetGraphicScale (scale);
+ DrawStamp (&s);
+ SetGraphicScale (old_scale);
+ SetGraphicScaleMode (old_mode);
+ }
+ 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 */
+ Present_UnbatchGraphics (pPIS, TRUE);
+
+ ClearDrawable ();
+ }
+ 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, "LINE") == 0)
+ {
+ int x1, x2, y1, y2;
+ if (4 == sscanf (pStr, "%d %d %d %d", &x1, &y1, &x2, &y2))
+ {
+ LINE l;
+
+ l.first.x = x1;
+ l.first.y = y1;
+ l.second.x = x2;
+ l.second.y = y2;
+
+ SetContextForeGroundColor (pPIS->TextColor);
+ DrawLine (&l);
+ }
+ else
+ {
+ log_add (log_Warning, "Bad LINE command '%s'", pStr);
+ }
+ }
+ else if (strcmp (Opcode, "MOVIE") == 0)
+ {
+ int fps, from, to;
+
+ if (3 == sscanf (pStr, "%d %d %d", &fps, &from, &to) &&
+ fps > 0 && from >= 0 && to >= 0 && to >= from)
+ {
+ Present_UnbatchGraphics (pPIS, TRUE);
+
+ pPIS->MovieFrame = from;
+ pPIS->MovieEndFrame = to;
+ pPIS->InterframeDelay = ONE_SECOND / fps;
+
+ pPIS->TimeOut = GetTimeCounter ();
+ pPIS->TimeOutOnSkip = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ log_add (log_Warning, "Bad MOVIE command '%s'", pStr);
+ }
+ }
+ else if (strcmp (Opcode, "NOOP") == 0)
+ { /* no operation - must be a comment in script */
+ /* do nothing */
+ }
+ }
+ /* we are all done */
+ return FALSE;
+}
+
+static BOOLEAN
+ShowSlidePresentation (STRING PresStr)
+{
+ CONTEXT OldContext;
+ FONT OldFont;
+ RECT OldRect;
+ PRESENTATION_INPUT_STATE pis;
+ int i;
+
+ memset (&pis, 0, sizeof(pis));
+ pis.SlideShow = PresStr;
+ if (!pis.SlideShow)
+ return FALSE;
+ pis.SlideShow = SetAbsStringTableIndex (pis.SlideShow, 0);
+ pis.OperIndex = 0;
+
+ OldContext = SetContext (ScreenContext);
+ GetContextClipRect (&OldRect);
+ OldFont = SetContextFont (NULL);
+ SetContextBackGroundColor (BLACK_COLOR);
+
+ SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
+ pis.InputFunc = DoPresentation;
+ pis.LastDrawKind = -1;
+ pis.TextVPos = 'B';
+ pis.MovieFrame = -1;
+ pis.StartTime = GetTimeCounter ();
+ pis.LastSyncTime = pis.StartTime;
+ DoInput (&pis, TRUE);
+
+ SleepThreadUntil (FadeMusic (0, ONE_SECOND));
+ StopMusic ();
+ FadeMusic (NORMAL_VOLUME, 0);
+
+ DestroyMusic (pis.MusicRef);
+ DestroyDrawable (ReleaseDrawable (pis.RotatedFrame));
+ DestroyDrawable (ReleaseDrawable (pis.Frame));
+ for (i = 0; i < MAX_FONTS; ++i)
+ DestroyFont (pis.Fonts[i]);
+
+ SetContextFont (OldFont);
+ SetContextClipRect (&OldRect);
+ SetContext (OldContext);
+
+ return TRUE;
+}
+
+static BOOLEAN
+DoVideoInput (void *pIS)
+{
+ VIDEO_INPUT_STATE* pVIS = (VIDEO_INPUT_STATE*) pIS;
+
+ if (!PlayingLegacyVideo (pVIS->CurVideo))
+ { // Video probably finished
+ return FALSE;
+ }
+
+ if (PulsedInputState.menu[KEY_MENU_SELECT]
+ || PulsedInputState.menu[KEY_MENU_CANCEL]
+ || PulsedInputState.menu[KEY_MENU_SPECIAL]
+ || (GLOBAL (CurrentActivity) & CHECK_ABORT))
+ { // abort movie
+ return FALSE;
+ }
+ else if (PulsedInputState.menu[KEY_MENU_LEFT]
+ || PulsedInputState.menu[KEY_MENU_RIGHT])
+ {
+ SDWORD newpos = VidGetPosition ();
+ if (PulsedInputState.menu[KEY_MENU_LEFT])
+ newpos -= 2000;
+ else if (PulsedInputState.menu[KEY_MENU_RIGHT])
+ newpos += 1000;
+ if (newpos < 0)
+ newpos = 0;
+
+ VidSeek (newpos);
+ }
+ else
+ {
+ if (!VidProcessFrame ())
+ return FALSE;
+
+ SleepThread (ONE_SECOND / 40);
+ }
+
+ return TRUE;
+}
+
+static void
+FadeClearScreen (void)
+{
+ SleepThreadUntil (FadeScreen (FadeAllToBlack, ONE_SECOND / 2));
+
+ // clear the screen with black
+ SetContext (ScreenContext);
+ SetContextBackGroundColor (BLACK_COLOR);
+ ClearDrawable ();
+
+ FadeScreen (FadeAllToColor, 0);
+}
+
+static BOOLEAN
+ShowLegacyVideo (LEGACY_VIDEO vid)
+{
+ VIDEO_INPUT_STATE vis;
+ LEGACY_VIDEO_REF ref;
+
+ FadeClearScreen ();
+
+ ref = PlayLegacyVideo (vid);
+ if (!ref)
+ return FALSE;
+
+ vis.InputFunc = DoVideoInput;
+ vis.CurVideo = ref;
+ SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
+ DoInput (&vis, TRUE);
+
+ StopLegacyVideo (ref);
+ FadeClearScreen ();
+
+ return TRUE;
+}
+
+BOOLEAN
+ShowPresentation (RESOURCE res)
+{
+ const char *resType = res_GetResourceType (res);
+ if (!resType)
+ {
+ return FALSE;
+ }
+ if (!strcmp (resType, "STRTAB"))
+ {
+ STRING pres = CaptureStringTable (LoadStringTable (res));
+ BOOLEAN result = ShowSlidePresentation (pres);
+ DestroyStringTable (ReleaseStringTable (pres));
+ return result;
+ }
+ else if (!strcmp (resType, "3DOVID"))
+ {
+ LEGACY_VIDEO vid = LoadLegacyVideoInstance (res);
+ BOOLEAN result = ShowLegacyVideo (vid);
+ DestroyLegacyVideo (vid);
+ return result;
+ }
+
+ log_add (log_Warning, "Tried to present '%s', of non-presentable type '%s'", res, resType);
+ return FALSE;
+}