2007-01-15 12:09:25 -08:00
/*
This file is part of Warzone 2100.
Copyright ( C ) 1999 - 2004 Eidos Interactive
2009-02-10 10:01:48 -08:00
Copyright ( C ) 2005 - 2009 Warzone Resurrection Project
2007-01-15 12:09:25 -08:00
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>
2006-06-16 12:10:23 -07:00
# include <physfs.h>
2008-03-16 05:39:08 -07:00
# include "lib/framework/file.h"
2009-02-10 09:23:09 -08:00
# include "lib/framework/stdio_ext.h"
2006-05-27 09:37:17 -07:00
# include "lib/ivis_common/rendmode.h"
2008-10-15 10:48:40 -07:00
# include "lib/ivis_common/piemode.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
*/
/***************************************************************************/
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
{
2009-07-15 14:33:24 -07:00
const char * aAudioName = NULL ;
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
}
2010-04-19 13:33:42 -07:00
iV_SetTextColour ( WZCOL_GREY ) ;
iV_DrawText ( & ( aSeqList [ currentPlaySeq ] . aText [ i ] . pText [ 0 ] ) ,
aSeqList [ currentPlaySeq ] . aText [ i ] . x + 1 , aSeqList [ currentPlaySeq ] . aText [ i ] . y + 1 ) ;
iV_SetTextColour ( WZCOL_TEXT_BRIGHT ) ;
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
}
2010-04-19 13:33:42 -07:00
iV_SetTextColour ( WZCOL_GREY ) ;
iV_DrawText ( & ( aSeqList [ currentPlaySeq ] . aText [ i ] . pText [ 0 ] ) ,
aSeqList [ currentPlaySeq ] . aText [ i ] . x + 1 , aSeqList [ currentPlaySeq ] . aText [ i ] . y + 1 ) ;
iV_SetTextColour ( WZCOL_TEXT_BRIGHT ) ;
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
}
// 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 ;
2007-12-24 07:57:29 -08:00
static SDWORD lastX ;
2009-06-17 22:17:56 -07:00
// make sure we take xOffset into account, we don't always start at 0
const unsigned int BUFFER_WIDTH = pie_GetVideoBufferWidth ( ) - xOffset ;
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
2008-10-15 10:48:46 -07:00
while ( iV_GetTextWidth ( currentText ) > BUFFER_WIDTH )
2007-06-28 10:47:08 -07:00
{
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
{
2008-10-15 10:48:46 -07:00
static const int MIN_JUSTIFICATION = 40 ;
static const int FOLLOW_ON_JUSTIFICATION = 160 ;
2007-06-28 10:47:08 -07:00
//justify this text
2008-10-15 10:48:46 -07:00
const int 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
{
2008-10-15 10:48:46 -07:00
aSeqList [ currentSeq ] . aText [ aSeqList [ currentSeq ] . currentText ] . x + = ( justification / 2 ) ;
2007-06-28 10:47:08 -07:00
}
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.
2008-10-15 10:48:43 -07:00
xOffset = ( double ) pie_GetVideoBufferWidth ( ) / 640. * ( double ) xOffset ;
yOffset = ( double ) pie_GetVideoBufferHeight ( ) / 480. * ( double ) yOffset ;
2007-06-28 10:47:08 -07:00
//get the text
pText = strrchr ( pCurrentLine , ' " ' ) ;
2008-10-15 10:48:43 -07:00
ASSERT ( pText ! = NULL , " error parsing text file " ) ;
2007-06-28 10:47:08 -07:00
if ( pText ! = NULL )
{
* pText = ( UBYTE ) 0 ;
}
pText = strchr ( pCurrentLine , ' " ' ) ;
2008-10-15 10:48:43 -07:00
ASSERT ( pText ! = NULL , " error parsing text file " ) ;
2007-06-28 10:47:08 -07:00
if ( pText ! = NULL )
{
2010-04-20 07:13:53 -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
{
currentSeq + + ;
2006-02-18 10:54:37 -08:00
2008-10-15 10:48:43 -07:00
ASSERT ( currentSeq < MAX_SEQ_LIST , " too many sequences " ) ;
if ( currentSeq > = MAX_SEQ_LIST )
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 ] ;
2008-10-15 10:48:43 -07:00
size_t check_len = sstrcpy ( aSubtitleName , pSeqName ) ;
char * extension ;
2009-04-21 18:44:12 -07:00
ASSERT ( check_len < sizeof ( aSubtitleName ) , " given sequence name (%s) longer (%lu) than buffer (%lu) " , pSeqName , ( unsigned long ) check_len , ( unsigned long ) sizeof ( aSubtitleName ) ) ;
2008-10-15 10:48:43 -07:00
// check for a subtitle file
extension = strrchr ( aSubtitleName , ' . ' ) ;
if ( extension )
* extension = ' \0 ' ;
check_len = sstrcat ( aSubtitleName , " .txt " ) ;
ASSERT ( check_len < sizeof ( aSubtitleName ) , " sequence name to long to attach an extension too " ) ;
2007-12-27 15:03:09 -08:00
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 ;
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 ;
}