2007-01-15 12:09:25 -08:00
|
|
|
/*
|
|
|
|
This file is part of Warzone 2100.
|
|
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
|
|
Copyright (C) 2005-2007 Warzone Resurrection Project
|
|
|
|
|
|
|
|
Warzone 2100 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.
|
|
|
|
|
|
|
|
Warzone 2100 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 Warzone 2100; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2008-02-16 05:12:58 -08:00
|
|
|
/**
|
|
|
|
* @file seqdisp.c
|
2007-06-28 10:47:08 -07:00
|
|
|
*
|
2008-02-16 05:12:58 -08:00
|
|
|
* Functions for the display of the Escape Sequences (FMV).
|
2007-06-28 10:47:08 -07:00
|
|
|
*
|
|
|
|
*/
|
2008-10-08 11:24:19 -07:00
|
|
|
|
2008-03-16 05:39:08 -07:00
|
|
|
#include "lib/framework/frame.h"
|
2008-10-08 11:24:19 -07:00
|
|
|
#include "lib/framework/frameint.h"
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2006-11-06 06:40:07 -08:00
|
|
|
#include <string.h>
|
2007-11-24 03:49:51 -08:00
|
|
|
#include <SDL_timer.h>
|
2006-06-16 12:10:23 -07:00
|
|
|
#include <physfs.h>
|
|
|
|
|
2008-03-16 05:39:08 -07:00
|
|
|
#include "lib/framework/file.h"
|
2006-05-27 09:37:17 -07:00
|
|
|
#include "lib/ivis_common/rendmode.h"
|
2008-03-16 05:39:08 -07:00
|
|
|
#include "lib/ivis_opengl/screen.h"
|
2008-09-20 08:54:41 -07:00
|
|
|
#include "lib/sequence/sequence.h"
|
2006-05-27 09:37:17 -07:00
|
|
|
#include "lib/sound/audio.h"
|
|
|
|
#include "lib/sound/cdaudio.h"
|
|
|
|
#include "lib/script/script.h"
|
2008-03-16 05:39:08 -07:00
|
|
|
|
|
|
|
#include "seqdisp.h"
|
|
|
|
|
|
|
|
#include "warzoneconfig.h"
|
|
|
|
#include "hci.h"//for font
|
|
|
|
#include "loop.h"
|
2007-06-28 10:47:08 -07:00
|
|
|
#include "scripttabs.h"
|
|
|
|
#include "design.h"
|
|
|
|
#include "wrappers.h"
|
2007-06-30 17:28:49 -07:00
|
|
|
#include "init.h" // For fileLoadBuffer
|
2008-02-08 03:05:31 -08:00
|
|
|
#include "drive.h"
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/*
|
|
|
|
* local Definitions
|
|
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
|
|
#define MAX_TEXT_OVERLAYS 32
|
|
|
|
#define MAX_SEQ_LIST 6
|
|
|
|
#define SUBTITLE_BOX_MIN 430
|
|
|
|
#define SUBTITLE_BOX_MAX 480
|
|
|
|
|
2008-10-11 20:05:40 -07:00
|
|
|
// NOTE: The original game never had a true fullscreen mode for FMVs on >640x480 screens.
|
|
|
|
// They would just use double sized videos, and move the text to that area.
|
|
|
|
// Since we *do* offer fullscreen FMVs, this isn't really needed anymore, depending
|
|
|
|
// on how we want to handle the text.
|
|
|
|
static int D_W2 = 0; // Text width offset
|
|
|
|
static int D_H2 = 0; // Text height offset
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-09-20 07:25:58 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
2007-06-28 10:47:08 -07:00
|
|
|
char pText[MAX_STR_LENGTH];
|
2007-01-04 10:41:24 -08:00
|
|
|
UDWORD x;
|
|
|
|
UDWORD y;
|
|
|
|
UDWORD startFrame;
|
|
|
|
UDWORD endFrame;
|
2007-06-28 10:47:08 -07:00
|
|
|
BOOL bSubtitle;
|
2006-02-18 10:54:37 -08:00
|
|
|
} SEQTEXT;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-09-20 07:25:58 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
2007-04-13 08:11:03 -07:00
|
|
|
const char *pSeq; //name of the sequence to play
|
|
|
|
const char *pAudio; //name of the wav to play
|
2007-06-28 10:47:08 -07:00
|
|
|
BOOL bSeqLoop; //loop this sequence
|
|
|
|
SDWORD currentText; //cuurent number of text messages for this seq
|
|
|
|
SEQTEXT aText[MAX_TEXT_OVERLAYS]; //text data to display for this sequence
|
2006-02-18 10:54:37 -08:00
|
|
|
} SEQLIST;
|
2007-06-28 10:47:08 -07:00
|
|
|
/***************************************************************************/
|
|
|
|
/*
|
|
|
|
* local Variables
|
|
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
|
|
|
2007-11-20 14:58:25 -08:00
|
|
|
static BOOL bBackDropWasAlreadyUp;
|
2008-03-24 09:51:17 -07:00
|
|
|
static BOOL bAudioPlaying = false;
|
|
|
|
static BOOL bHoldSeqForAudio = false;
|
|
|
|
static BOOL bSeqSubtitles = true;
|
2008-10-08 11:24:19 -07:00
|
|
|
static BOOL bSeqPlaying = false;
|
2008-10-04 12:28:41 -07:00
|
|
|
static const char aHardPath[] = "sequences/";
|
2007-11-20 14:58:25 -08:00
|
|
|
static char aVideoName[MAX_STR_LENGTH];
|
2008-10-08 11:24:19 -07:00
|
|
|
static char* pVideoBuffer = NULL;
|
|
|
|
static char* pVideoPalette = NULL;
|
|
|
|
static SDWORD frameSkip = 1;
|
2007-11-20 14:58:25 -08:00
|
|
|
static SEQLIST aSeqList[MAX_SEQ_LIST];
|
2007-06-28 10:47:08 -07:00
|
|
|
static SDWORD currentSeq = -1;
|
|
|
|
static SDWORD currentPlaySeq = -1;
|
2008-03-24 09:51:17 -07:00
|
|
|
static BOOL g_bResumeInGame = false;
|
2007-12-24 07:57:29 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/***************************************************************************/
|
|
|
|
/*
|
|
|
|
* local ProtoTypes
|
|
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
|
|
|
2008-10-08 11:24:19 -07:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
VIDEO_PRESELECTED_RESOLUTION,
|
|
|
|
VIDEO_USER_CHOSEN_RESOLUTION,
|
|
|
|
} VIDEO_RESOLUTION;
|
|
|
|
|
|
|
|
static bool seq_StartFullScreenVideo(const char* videoName, const char* audioName, VIDEO_RESOLUTION resolution);
|
|
|
|
BOOL seq_SetupVideoBuffers(void);
|
|
|
|
BOOL seq_ReleaseVideoBuffers(void);
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/***************************************************************************/
|
|
|
|
/*
|
|
|
|
* Source
|
|
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
/* Renders a video sequence specified by filename to a buffer*/
|
2008-10-08 11:24:19 -07:00
|
|
|
bool seq_RenderVideoToBuffer(const char* sequenceName, int seqCommand)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-08 11:24:19 -07:00
|
|
|
static enum
|
|
|
|
{
|
|
|
|
VIDEO_NOT_PLAYING,
|
|
|
|
VIDEO_PLAYING,
|
|
|
|
VIDEO_FINISHED,
|
|
|
|
} videoPlaying = VIDEO_NOT_PLAYING;
|
|
|
|
static enum
|
|
|
|
{
|
|
|
|
VIDEO_LOOP,
|
|
|
|
VIDEO_HOLD_LAST_FRAME,
|
|
|
|
} frameHold = VIDEO_LOOP;
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
if (seqCommand == SEQUENCE_KILL)
|
|
|
|
{
|
|
|
|
//stop the movie
|
2008-09-20 08:54:41 -07:00
|
|
|
seq_Shutdown();
|
2008-10-08 11:24:19 -07:00
|
|
|
bSeqPlaying = false;
|
|
|
|
frameHold = VIDEO_LOOP;
|
|
|
|
videoPlaying = VIDEO_NOT_PLAYING;
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2008-10-08 11:24:19 -07:00
|
|
|
if (!bSeqPlaying
|
|
|
|
&& frameHold == VIDEO_LOOP)
|
|
|
|
{
|
|
|
|
//start the ball rolling
|
|
|
|
|
|
|
|
iV_SetFont(font_regular);
|
|
|
|
iV_SetTextColour(WZCOL_TEXT_BRIGHT);
|
|
|
|
|
|
|
|
/* We do *NOT* want to use the user-choosen resolution when we
|
|
|
|
* are doing intelligence videos.
|
|
|
|
*/
|
|
|
|
videoPlaying = seq_StartFullScreenVideo(sequenceName, NULL, VIDEO_PRESELECTED_RESOLUTION) ? VIDEO_PLAYING : VIDEO_FINISHED;
|
|
|
|
bSeqPlaying = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (videoPlaying != VIDEO_FINISHED)
|
|
|
|
{
|
|
|
|
videoPlaying = seq_Update() ? VIDEO_PLAYING : VIDEO_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (videoPlaying == VIDEO_FINISHED)
|
|
|
|
{
|
|
|
|
seq_Shutdown();
|
|
|
|
bSeqPlaying = false;
|
|
|
|
frameHold = VIDEO_HOLD_LAST_FRAME;
|
|
|
|
videoPlaying = VIDEO_NOT_PLAYING;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL seq_ReleaseVideoBuffers(void)
|
|
|
|
{
|
|
|
|
free(pVideoBuffer);
|
|
|
|
free(pVideoPalette);
|
|
|
|
pVideoBuffer = NULL;
|
|
|
|
pVideoPalette = NULL;
|
|
|
|
return true;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-10-08 11:24:19 -07:00
|
|
|
BOOL seq_SetupVideoBuffers(void)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2008-10-08 11:24:19 -07:00
|
|
|
static void seq_SetUserResolution(void)
|
|
|
|
{
|
|
|
|
switch (war_GetFMVmode())
|
|
|
|
{
|
|
|
|
case FMV_1X:
|
|
|
|
{
|
|
|
|
// Native (1x)
|
|
|
|
const int x = (screenWidth - 320) / 2;
|
|
|
|
const int y = (screenHeight - 240) / 2;
|
|
|
|
seq_SetDisplaySize(320, 240, x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMV_2X:
|
|
|
|
{
|
|
|
|
// Double (2x)
|
|
|
|
const int x = (screenWidth - 640) / 2;
|
|
|
|
const int y = (screenHeight - 480) / 2;
|
|
|
|
seq_SetDisplaySize(640, 480, x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMV_FULLSCREEN:
|
|
|
|
seq_SetDisplaySize(screenWidth, screenHeight, 0, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ASSERT(!"invalid FMV mode", "Invalid FMV mode: %u", (unsigned int)war_GetFMVmode());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
//full screenvideo functions
|
2008-10-08 11:24:19 -07:00
|
|
|
static bool seq_StartFullScreenVideo(const char* videoName, const char* audioName, VIDEO_RESOLUTION resolution)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-12-27 15:03:09 -08:00
|
|
|
const char* aAudioName;
|
2008-09-20 08:17:01 -07:00
|
|
|
int chars_printed;
|
2006-08-29 12:57:34 -07:00
|
|
|
|
2008-09-20 13:53:28 -07:00
|
|
|
bHoldSeqForAudio = false;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-09-20 08:17:01 -07:00
|
|
|
chars_printed = ssprintf(aVideoName, "%s%s", aHardPath, videoName);
|
|
|
|
ASSERT(chars_printed < sizeof(aVideoName), "sequence path + name greater than max string");
|
2006-02-18 10:54:37 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
//set audio path
|
|
|
|
if (audioName != NULL)
|
|
|
|
{
|
2007-12-27 15:03:09 -08:00
|
|
|
sasprintf((char**)&aAudioName, "sequenceaudio/%s", audioName);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2008-10-08 11:24:19 -07:00
|
|
|
cdAudio_Pause();
|
|
|
|
iV_SetFont(font_regular);
|
|
|
|
iV_SetTextColour(WZCOL_TEXT_BRIGHT);
|
|
|
|
|
|
|
|
/* We do not want to enter loop_SetVideoPlaybackMode() when we are
|
|
|
|
* doing intelligence videos.
|
|
|
|
*/
|
|
|
|
if (resolution == VIDEO_USER_CHOSEN_RESOLUTION)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-08 11:24:19 -07:00
|
|
|
//start video mode
|
|
|
|
if (loop_GetVideoMode() == 0)
|
|
|
|
{
|
|
|
|
// check to see if we need to pause, and set font each time
|
|
|
|
cdAudio_Pause();
|
|
|
|
loop_SetVideoPlaybackMode();
|
|
|
|
iV_SetFont(font_regular);
|
|
|
|
iV_SetTextColour(WZCOL_TEXT_BRIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the dimensions to show full screen or native or ...
|
|
|
|
seq_SetUserResolution();
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-12-24 07:57:29 -08:00
|
|
|
if (!seq_Play(aVideoName))
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-08 11:24:19 -07:00
|
|
|
seq_Shutdown();
|
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (audioName == NULL)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bAudioPlaying = false;
|
2008-09-20 08:52:01 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-08 11:24:19 -07:00
|
|
|
// NOT controlled by sliders for now?
|
2008-09-20 08:54:41 -07:00
|
|
|
static const float maxVolume = 1.f;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-09-20 08:52:01 -07:00
|
|
|
bAudioPlaying = audio_PlayStream(aAudioName, maxVolume, NULL, NULL) ? true : false;
|
2008-10-08 11:24:19 -07:00
|
|
|
ASSERT(bAudioPlaying == true, "unable to initialise sound %s", aAudioName);
|
2008-09-20 08:52:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-03-30 10:38:35 -07:00
|
|
|
BOOL seq_UpdateFullScreenVideo(int *pbClear)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-08 11:24:19 -07:00
|
|
|
int i;
|
2008-03-24 09:51:17 -07:00
|
|
|
BOOL bMoreThanOneSequenceLine = false;
|
2008-10-08 11:24:19 -07:00
|
|
|
bool stillPlaying;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-10-11 20:05:40 -07:00
|
|
|
unsigned int subMin = SUBTITLE_BOX_MAX + D_H2;
|
|
|
|
unsigned int subMax = SUBTITLE_BOX_MIN + D_H2;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
//get any text lines over bottom of the video
|
2008-10-08 11:24:19 -07:00
|
|
|
unsigned int realFrame = seq_GetFrameNumber();
|
2007-06-28 10:47:08 -07:00
|
|
|
for(i=0;i<MAX_TEXT_OVERLAYS;i++)
|
|
|
|
{
|
2008-06-22 10:39:00 -07:00
|
|
|
if (aSeqList[currentPlaySeq].aText[i].pText[0] != '\0')
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-15 08:35:26 -07:00
|
|
|
if (aSeqList[currentPlaySeq].aText[i].bSubtitle)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
if ((realFrame >= aSeqList[currentPlaySeq].aText[i].startFrame) && (realFrame <= aSeqList[currentPlaySeq].aText[i].endFrame))
|
|
|
|
{
|
|
|
|
if (subMin > aSeqList[currentPlaySeq].aText[i].y)
|
|
|
|
{
|
|
|
|
if (aSeqList[currentPlaySeq].aText[i].y > SUBTITLE_BOX_MIN)
|
|
|
|
{
|
|
|
|
subMin = aSeqList[currentPlaySeq].aText[i].y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (subMax < aSeqList[currentPlaySeq].aText[i].y)
|
|
|
|
{
|
|
|
|
subMax = aSeqList[currentPlaySeq].aText[i].y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aSeqList[currentPlaySeq].bSeqLoop)//if its a looped video always draw the text
|
|
|
|
{
|
|
|
|
if (subMin >= aSeqList[currentPlaySeq].aText[i].y)
|
|
|
|
{
|
|
|
|
if (aSeqList[currentPlaySeq].aText[i].y > SUBTITLE_BOX_MIN)
|
|
|
|
{
|
|
|
|
subMin = aSeqList[currentPlaySeq].aText[i].y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (subMax < aSeqList[currentPlaySeq].aText[i].y)
|
|
|
|
{
|
|
|
|
subMax = aSeqList[currentPlaySeq].aText[i].y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-10-08 11:24:19 -07:00
|
|
|
|
|
|
|
if (realFrame >= aSeqList[currentPlaySeq].aText[i].endFrame
|
|
|
|
&& realFrame < aSeqList[currentPlaySeq].aText[i].endFrame + frameSkip)
|
|
|
|
{
|
|
|
|
if (pbClear != NULL)
|
|
|
|
{
|
|
|
|
*pbClear = CLEAR_BLACK;
|
|
|
|
}
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-11 20:05:40 -07:00
|
|
|
subMin -= D_H2;//adjust video window here because text is already ofset for big screens
|
|
|
|
subMax -= D_H2;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
if (subMin < SUBTITLE_BOX_MIN)
|
|
|
|
{
|
|
|
|
subMin = SUBTITLE_BOX_MIN;
|
|
|
|
}
|
|
|
|
if (subMax > SUBTITLE_BOX_MAX)
|
|
|
|
{
|
|
|
|
subMax = SUBTITLE_BOX_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subMax > subMin)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bMoreThanOneSequenceLine = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-12-24 07:57:29 -08:00
|
|
|
//call sequence player to download last frame
|
2008-10-08 11:24:19 -07:00
|
|
|
stillPlaying = seq_Update();
|
2007-12-24 07:57:29 -08:00
|
|
|
//print any text over the video
|
2008-10-08 11:24:19 -07:00
|
|
|
realFrame = seq_GetFrameNumber();//textFrame + 1;
|
|
|
|
|
2007-12-24 07:57:29 -08:00
|
|
|
for(i=0;i<MAX_TEXT_OVERLAYS;i++)
|
|
|
|
{
|
2008-06-22 10:39:00 -07:00
|
|
|
if (aSeqList[currentPlaySeq].aText[i].pText[0] != '\0')
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-12-24 07:57:29 -08:00
|
|
|
if ((realFrame >= aSeqList[currentPlaySeq].aText[i].startFrame) && (realFrame <= aSeqList[currentPlaySeq].aText[i].endFrame))
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-12-24 07:57:29 -08:00
|
|
|
if (bMoreThanOneSequenceLine)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-11 20:05:40 -07:00
|
|
|
aSeqList[currentPlaySeq].aText[i].x = 20 + D_W2;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-12-24 07:57:29 -08:00
|
|
|
iV_DrawText(&(aSeqList[currentPlaySeq].aText[i].pText[0]),
|
|
|
|
aSeqList[currentPlaySeq].aText[i].x, aSeqList[currentPlaySeq].aText[i].y);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-12-24 07:57:29 -08:00
|
|
|
else if (aSeqList[currentPlaySeq].bSeqLoop)//if its a looped video always draw the text
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-12-24 07:57:29 -08:00
|
|
|
if (bMoreThanOneSequenceLine)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-11 20:05:40 -07:00
|
|
|
aSeqList[currentPlaySeq].aText[i].x = 20 + D_W2;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-12-24 07:57:29 -08:00
|
|
|
iV_DrawText(&(aSeqList[currentPlaySeq].aText[i].pText[0]),
|
|
|
|
aSeqList[currentPlaySeq].aText[i].x, aSeqList[currentPlaySeq].aText[i].y);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2008-10-08 11:24:19 -07:00
|
|
|
if (!stillPlaying
|
|
|
|
|| bHoldSeqForAudio)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
if (bAudioPlaying)
|
|
|
|
{
|
|
|
|
if (aSeqList[currentPlaySeq].bSeqLoop)
|
|
|
|
{
|
2008-09-20 08:54:41 -07:00
|
|
|
seq_Shutdown();
|
2008-10-08 11:24:19 -07:00
|
|
|
|
2008-09-20 08:54:41 -07:00
|
|
|
if (!seq_Play(aVideoName))
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bHoldSeqForAudio = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bHoldSeqForAudio = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;//should hold the video
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;//should terminate the video
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2008-10-08 11:24:19 -07:00
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL seq_StopFullScreenVideo(void)
|
|
|
|
{
|
2008-02-08 03:05:31 -08:00
|
|
|
StopDriverMode();
|
2007-06-28 10:47:08 -07:00
|
|
|
if (!seq_AnySeqLeft())
|
|
|
|
{
|
|
|
|
loop_ClearVideoPlaybackMode();
|
|
|
|
}
|
|
|
|
|
2008-09-20 08:54:41 -07:00
|
|
|
seq_Shutdown();
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
if (!seq_AnySeqLeft())
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
if ( g_bResumeInGame == true )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
resetDesignPauseState();
|
|
|
|
intAddReticule();
|
2008-03-24 09:51:17 -07:00
|
|
|
g_bResumeInGame = false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2008-10-11 20:05:40 -07:00
|
|
|
#define FOLLOW_ON_JUSTIFICATION 160 // not really used for anything
|
2007-06-28 10:47:08 -07:00
|
|
|
#define MIN_JUSTIFICATION 40
|
|
|
|
|
|
|
|
// add a string at x,y or add string below last line if x and y are 0
|
2008-10-15 08:35:26 -07:00
|
|
|
BOOL seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, SDWORD startFrame, SDWORD endFrame, SEQ_TEXT_POSITIONING textJustification)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
SDWORD sourceLength, currentLength;
|
|
|
|
char* currentText;
|
|
|
|
SDWORD justification;
|
2007-12-24 07:57:29 -08:00
|
|
|
static SDWORD lastX;
|
2008-10-11 20:05:40 -07:00
|
|
|
int BUFFER_WIDTH = pie_GetVideoBufferWidth();
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
iV_SetFont(font_regular);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-10-15 10:48:35 -07:00
|
|
|
ASSERT(aSeqList[currentSeq].currentText < MAX_TEXT_OVERLAYS, "too many text lines");
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-02-18 10:54:37 -08:00
|
|
|
sourceLength = strlen(pText);
|
2007-06-28 10:47:08 -07:00
|
|
|
currentLength = sourceLength;
|
|
|
|
currentText = &(aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].pText[0]);
|
|
|
|
|
|
|
|
//if the string is bigger than the buffer get the last end of the last fullword in the buffer
|
|
|
|
if (currentLength >= MAX_STR_LENGTH)
|
|
|
|
{
|
|
|
|
currentLength = MAX_STR_LENGTH - 1;
|
|
|
|
//get end of the last word
|
|
|
|
while((pText[currentLength] != ' ') && (currentLength > 0))
|
|
|
|
{
|
|
|
|
currentLength--;
|
|
|
|
}
|
|
|
|
currentLength--;
|
|
|
|
}
|
2006-02-18 10:54:37 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
memcpy(currentText,pText,currentLength);
|
|
|
|
currentText[currentLength] = 0;//terminate the string what ever
|
2006-02-18 10:54:37 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
//check the string is shortenough to print
|
|
|
|
//if not take a word of the end and try again
|
|
|
|
while(iV_GetTextWidth(currentText) > BUFFER_WIDTH)
|
|
|
|
{
|
|
|
|
currentLength--;
|
|
|
|
while((pText[currentLength] != ' ') && (currentLength > 0))
|
|
|
|
{
|
|
|
|
currentLength--;
|
|
|
|
}
|
|
|
|
currentText[currentLength] = 0;//terminate the string what ever
|
|
|
|
}
|
|
|
|
currentText[currentLength] = 0;//terminate the string what ever
|
|
|
|
|
|
|
|
//check if x and y are 0 and put text on next line
|
|
|
|
if (((xOffset == 0) && (yOffset == 0)) && (currentLength > 0))
|
|
|
|
{
|
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].x = lastX;
|
|
|
|
// aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText-1].x;
|
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].y = aSeqList[currentSeq].
|
|
|
|
aText[aSeqList[currentSeq].currentText-1].y + iV_GetTextLineSize();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-11 20:05:40 -07:00
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].x = xOffset + D_W2;
|
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].y = yOffset + D_H2;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
lastX = aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].x;
|
|
|
|
|
2008-10-15 08:35:26 -07:00
|
|
|
if (textJustification
|
|
|
|
&& currentLength == sourceLength)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
//justify this text
|
|
|
|
justification = BUFFER_WIDTH - iV_GetTextWidth(currentText);
|
2008-10-15 08:35:26 -07:00
|
|
|
if (textJustification == SEQ_TEXT_JUSTIFY
|
|
|
|
&& justification > MIN_JUSTIFICATION)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].x += (justification/2);
|
|
|
|
}
|
2008-10-15 08:35:26 -07:00
|
|
|
else if (textJustification == SEQ_TEXT_FOLLOW_ON
|
|
|
|
&& justification > FOLLOW_ON_JUSTIFICATION)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-18 10:54:37 -08:00
|
|
|
//set start and finish times for the objects
|
2007-06-28 10:47:08 -07:00
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].startFrame = startFrame;
|
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].endFrame = endFrame;
|
2008-10-15 08:35:26 -07:00
|
|
|
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].bSubtitle = textJustification;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
aSeqList[currentSeq].currentText++;
|
|
|
|
if (aSeqList[currentSeq].currentText >= MAX_TEXT_OVERLAYS)
|
|
|
|
{
|
|
|
|
aSeqList[currentSeq].currentText = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//check text is okay on the screen
|
|
|
|
if (currentLength < sourceLength)
|
|
|
|
{
|
|
|
|
//RECURSE x= 0 y = 0 for nextLine
|
2008-10-15 08:35:26 -07:00
|
|
|
if (textJustification == SEQ_TEXT_JUSTIFY)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-15 08:35:26 -07:00
|
|
|
textJustification = SEQ_TEXT_POSITION;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2008-10-15 08:35:26 -07:00
|
|
|
seq_AddTextForVideo(&pText[currentLength + 1], 0, 0, startFrame, endFrame, textJustification);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL seq_ClearTextForVideo(void)
|
|
|
|
{
|
|
|
|
SDWORD i, j;
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
for (j=0; j < MAX_SEQ_LIST; j++)
|
|
|
|
{
|
|
|
|
for(i=0;i<MAX_TEXT_OVERLAYS;i++)
|
|
|
|
{
|
|
|
|
aSeqList[j].aText[i].pText[0] = 0;
|
|
|
|
aSeqList[j].aText[i].x = 0;
|
|
|
|
aSeqList[j].aText[i].y = 0;
|
|
|
|
aSeqList[j].aText[i].startFrame = 0;
|
|
|
|
aSeqList[j].aText[i].endFrame = 0;
|
|
|
|
aSeqList[j].aText[i].bSubtitle = 0;
|
|
|
|
}
|
|
|
|
aSeqList[j].currentText = 0;
|
|
|
|
}
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2008-10-15 08:35:26 -07:00
|
|
|
static BOOL seq_AddTextFromFile(const char *pTextName, SEQ_TEXT_POSITIONING textJustification)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-12-27 15:03:09 -08:00
|
|
|
char aTextName[MAX_STR_LENGTH];
|
2006-08-12 09:52:37 -07:00
|
|
|
char *pTextBuffer, *pCurrentLine, *pText;
|
2007-06-28 10:47:08 -07:00
|
|
|
UDWORD fileSize;
|
|
|
|
SDWORD xOffset, yOffset, startFrame, endFrame;
|
2006-09-24 12:11:34 -07:00
|
|
|
const char *seps = "\n";
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-10-11 20:05:40 -07:00
|
|
|
// NOTE: The original game never had a fullscreen mode for FMVs on >640x480 screens.
|
|
|
|
// They would just use double sized videos, and move the text to that area.
|
|
|
|
// We just use the full screen for text right now, instead of using offsets.
|
|
|
|
// However, depending on reaction, we may use the old style again.
|
|
|
|
D_H2 = 0; //( pie_GetVideoBufferHeight()- 480)/2;
|
|
|
|
D_W2 = 0; //( pie_GetVideoBufferWidth() - 640)/2;
|
2008-09-20 08:17:01 -07:00
|
|
|
ssprintf(aTextName, "sequenceaudio/%s", pTextName);
|
2006-02-18 10:54:37 -08:00
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
if (loadFileToBufferNoError(aTextName, fileLoadBuffer, FILE_LOAD_BUFFER_SIZE, &fileSize) == false) //Did I mention this is lame? -Q
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-06-30 17:28:49 -07:00
|
|
|
pTextBuffer = fileLoadBuffer;
|
2007-06-28 10:47:08 -07:00
|
|
|
pCurrentLine = strtok(pTextBuffer,seps);
|
|
|
|
while(pCurrentLine != NULL)
|
|
|
|
{
|
|
|
|
if (*pCurrentLine != '/')
|
|
|
|
{
|
|
|
|
if (sscanf(pCurrentLine,"%d %d %d %d", &xOffset, &yOffset, &startFrame, &endFrame) == 4)
|
|
|
|
{
|
2008-10-11 20:05:40 -07:00
|
|
|
// Since all the positioning was hardcoded to specific values, we now calculate the
|
|
|
|
// ratio of our screen, compared to what the game expects and multiply that to x, y.
|
|
|
|
// This makes the text always take up the full screen, instead of original style.
|
|
|
|
xOffset = ((double)pie_GetVideoBufferWidth() / 640.0f) * (double)xOffset;
|
|
|
|
yOffset = ((double)pie_GetVideoBufferHeight() / 480.0f) * (double)yOffset;
|
2007-06-28 10:47:08 -07:00
|
|
|
//get the text
|
|
|
|
pText = strrchr(pCurrentLine,'"');
|
2006-08-23 05:58:48 -07:00
|
|
|
ASSERT( pText != NULL,"seq_AddTextFromFile error parsing text file" );
|
2007-06-28 10:47:08 -07:00
|
|
|
if (pText != NULL)
|
|
|
|
{
|
|
|
|
*pText = (UBYTE)0;
|
|
|
|
}
|
|
|
|
pText = strchr(pCurrentLine,'"');
|
2006-08-23 05:58:48 -07:00
|
|
|
ASSERT( pText != NULL,"seq_AddTextFromFile error parsing text file" );
|
2007-06-28 10:47:08 -07:00
|
|
|
if (pText != NULL)
|
|
|
|
{
|
2008-10-15 08:35:26 -07:00
|
|
|
seq_AddTextForVideo(&pText[1], xOffset, yOffset, startFrame, endFrame, textJustification);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//get next line
|
|
|
|
pCurrentLine = strtok(NULL,seps);
|
|
|
|
}
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//clear the sequence list
|
|
|
|
void seq_ClearSeqList(void)
|
|
|
|
{
|
|
|
|
SDWORD i;
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
seq_ClearTextForVideo();
|
|
|
|
for(i=0;i<MAX_SEQ_LIST;i++)
|
|
|
|
{
|
|
|
|
aSeqList[i].pSeq = NULL;
|
|
|
|
}
|
|
|
|
currentSeq = -1;
|
|
|
|
currentPlaySeq = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//add a sequence to the list to be played
|
2007-04-13 08:11:03 -07:00
|
|
|
void seq_AddSeqToList(const char *pSeqName, const char *pAudioName, const char *pTextName, BOOL bLoop)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
SDWORD strLen;
|
|
|
|
currentSeq++;
|
2006-02-18 10:54:37 -08:00
|
|
|
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
if ((currentSeq) >= MAX_SEQ_LIST)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
ASSERT( false, "seq_AddSeqToList: too many sequences" );
|
2007-06-28 10:47:08 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//OK so add it to the list
|
|
|
|
aSeqList[currentSeq].pSeq = pSeqName;
|
|
|
|
aSeqList[currentSeq].pAudio = pAudioName;
|
|
|
|
aSeqList[currentSeq].bSeqLoop = bLoop;
|
2006-02-18 10:54:37 -08:00
|
|
|
if (pTextName != NULL)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-10-15 10:48:35 -07:00
|
|
|
// Ordinary text shouldn't be justified
|
|
|
|
seq_AddTextFromFile(pTextName, SEQ_TEXT_POSITION);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bSeqSubtitles)
|
|
|
|
{
|
2007-12-27 15:03:09 -08:00
|
|
|
char aSubtitleName[MAX_STR_LENGTH];
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
//check for a subtitle file
|
|
|
|
strLen = strlen(pSeqName);
|
2006-08-23 05:58:48 -07:00
|
|
|
ASSERT( strLen < MAX_STR_LENGTH,"seq_AddSeqToList: sequence name error" );
|
2008-05-25 06:46:49 -07:00
|
|
|
sstrcpy(aSubtitleName, pSeqName);
|
2007-06-28 10:47:08 -07:00
|
|
|
aSubtitleName[strLen - 4] = 0;
|
2008-05-25 06:46:49 -07:00
|
|
|
sstrcat(aSubtitleName, ".txt");
|
2008-10-15 10:48:35 -07:00
|
|
|
// Subtitles should be center justified
|
|
|
|
seq_AddTextFromFile(aSubtitleName, SEQ_TEXT_JUSTIFY);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*checks to see if there are any sequences left in the list to play*/
|
|
|
|
BOOL seq_AnySeqLeft(void)
|
|
|
|
{
|
|
|
|
UBYTE nextSeq;
|
|
|
|
|
|
|
|
nextSeq = (UBYTE)(currentPlaySeq+1);
|
|
|
|
|
|
|
|
//check haven't reached end
|
|
|
|
if (nextSeq > MAX_SEQ_LIST)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
else if (aSeqList[nextSeq].pSeq)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-19 17:49:20 -07:00
|
|
|
static void seqDispCDOK( void )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
BOOL bPlayedOK;
|
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
if ( bBackDropWasAlreadyUp == false )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
screen_StopBackDrop();
|
|
|
|
}
|
2008-09-20 08:54:41 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
currentPlaySeq++;
|
|
|
|
if (currentPlaySeq >= MAX_SEQ_LIST)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bPlayedOK = false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-08 11:24:19 -07:00
|
|
|
bPlayedOK = seq_StartFullScreenVideo(aSeqList[currentPlaySeq].pSeq, aSeqList[currentPlaySeq].pAudio, VIDEO_USER_CHOSEN_RESOLUTION);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
if ( bPlayedOK == false )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-09-03 04:22:51 -07:00
|
|
|
//don't do the callback if we're playing the win/lose video
|
|
|
|
if (!getScriptWinLoseVideo())
|
|
|
|
{
|
|
|
|
debug(LOG_SCRIPT, "*** Called video quit trigger!");
|
2008-10-08 11:24:19 -07:00
|
|
|
// Not sure this is correct... CHECK, since the callback should ONLY
|
|
|
|
// be called when a video is playing (always?)
|
|
|
|
if (seq_Playing())
|
|
|
|
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_VIDEO_QUIT);
|
2006-09-03 04:22:51 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
displayGameOver(getScriptWinLoseVideo() == PLAY_WIN);
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*returns the next sequence in the list to play*/
|
|
|
|
void seq_StartNextFullScreenVideo(void)
|
|
|
|
{
|
|
|
|
seqDispCDOK();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seq_SetSubtitles(BOOL bNewState)
|
|
|
|
{
|
|
|
|
bSeqSubtitles = bNewState;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL seq_GetSubtitles(void)
|
|
|
|
{
|
|
|
|
return bSeqSubtitles;
|
|
|
|
}
|