mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
358
Code/BinkMovie/BINKMovie.cpp
Normal file
358
Code/BinkMovie/BINKMovie.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binkmovie.h"
|
||||
#include "dx8wrapper.h"
|
||||
#include "formconv.h"
|
||||
#include "render2d.h"
|
||||
#include "Bink.h"
|
||||
#include "rect.h"
|
||||
#include "subtitlemanager.h"
|
||||
#include "dx8caps.h"
|
||||
|
||||
class BINKMovieClass
|
||||
{
|
||||
private:
|
||||
StringClass Filename;
|
||||
HBINK Bink;
|
||||
bool FrameChanged;
|
||||
unsigned TextureCount;
|
||||
unsigned long TicksPerFrame;
|
||||
|
||||
struct TextureInfoStruct {
|
||||
TextureClass* Texture;
|
||||
int TextureWidth;
|
||||
int TextureHeight;
|
||||
int TextureLocX;
|
||||
int TextureLocY;
|
||||
RectClass UV;
|
||||
RectClass Rect;
|
||||
};
|
||||
|
||||
TextureInfoStruct* TextureInfos;
|
||||
unsigned char* TempBuffer;
|
||||
Render2DClass Renderer;
|
||||
SubTitleManagerClass* SubTitleManager;
|
||||
|
||||
public:
|
||||
BINKMovieClass(const char* filename,const char* subtitlename,FontCharsClass* font);
|
||||
~BINKMovieClass();
|
||||
|
||||
void Update();
|
||||
void Render();
|
||||
bool Is_Complete();
|
||||
};
|
||||
|
||||
|
||||
static BINKMovieClass* CurrentMovie;
|
||||
|
||||
|
||||
void BINKMovie::Play(const char* filename,const char* subtitlename, FontCharsClass* font)
|
||||
{
|
||||
if (CurrentMovie) {
|
||||
delete CurrentMovie;
|
||||
CurrentMovie = NULL;
|
||||
}
|
||||
|
||||
CurrentMovie = new BINKMovieClass(filename,subtitlename,font);
|
||||
}
|
||||
|
||||
|
||||
void BINKMovie::Stop()
|
||||
{
|
||||
if (CurrentMovie) {
|
||||
delete CurrentMovie;
|
||||
CurrentMovie = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BINKMovie::Update()
|
||||
{
|
||||
if (CurrentMovie) {
|
||||
CurrentMovie->Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BINKMovie::Render()
|
||||
{
|
||||
if (CurrentMovie) {
|
||||
CurrentMovie->Render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BINKMovie::Init()
|
||||
{
|
||||
BinkSoundUseDirectSound(0);
|
||||
}
|
||||
|
||||
|
||||
void BINKMovie::Shutdown()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
|
||||
bool BINKMovie::Is_Complete()
|
||||
{
|
||||
if (CurrentMovie) {
|
||||
return CurrentMovie->Is_Complete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BINKMovieClass::BINKMovieClass(const char* filename, const char* subtitlename, FontCharsClass* font)
|
||||
:
|
||||
Filename(filename),
|
||||
Bink(0),
|
||||
FrameChanged(true),
|
||||
TicksPerFrame(0),
|
||||
SubTitleManager(NULL)
|
||||
{
|
||||
Bink = BinkOpen(Filename, 0);
|
||||
|
||||
if (Bink == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
TempBuffer = new unsigned char[Bink->Width * Bink->Height*2];
|
||||
|
||||
const D3DCAPS8& dx8caps = DX8Wrapper::Get_Current_Caps()->Get_DX8_Caps();
|
||||
unsigned poweroftwowidth = 1;
|
||||
|
||||
while (poweroftwowidth < Bink->Width) {
|
||||
poweroftwowidth <<= 1;
|
||||
}
|
||||
|
||||
unsigned poweroftwoheight = 1;
|
||||
|
||||
while (poweroftwoheight < Bink->Height) {
|
||||
poweroftwoheight <<= 1;
|
||||
}
|
||||
|
||||
if (poweroftwowidth > dx8caps.MaxTextureWidth) {
|
||||
poweroftwowidth = dx8caps.MaxTextureWidth;
|
||||
}
|
||||
|
||||
if (poweroftwoheight > dx8caps.MaxTextureHeight) {
|
||||
poweroftwoheight = dx8caps.MaxTextureHeight;
|
||||
}
|
||||
|
||||
TextureCount = 0;
|
||||
unsigned max_width = poweroftwowidth;
|
||||
unsigned max_height = poweroftwoheight;
|
||||
unsigned x, y;
|
||||
|
||||
for (y = 0; y < Bink->Height; y += max_height-2) { // Two pixels are lost due to duplicated edges to prevent bilinear artifacts
|
||||
for (x = 0; x < Bink->Width; x += max_width-2) {
|
||||
++TextureCount;
|
||||
}
|
||||
}
|
||||
|
||||
TextureInfos = new TextureInfoStruct[TextureCount];
|
||||
unsigned cnt = 0;
|
||||
|
||||
for (y = 0; y < Bink->Height; y += max_height-1) {
|
||||
for (x = 0; x < Bink->Width; x += max_width-1) {
|
||||
TextureInfos[cnt].Texture = new TextureClass(
|
||||
max_width, max_height, D3DFormat_To_WW3DFormat(D3DFMT_R5G6B5),
|
||||
TextureClass::MIP_LEVELS_1, TextureClass::POOL_MANAGED, false);
|
||||
|
||||
TextureInfos[cnt].TextureLocX = x;
|
||||
TextureInfos[cnt].TextureLocY = y;
|
||||
TextureInfos[cnt].TextureWidth = max_width;
|
||||
TextureInfos[cnt].UV.Right = float(max_width) / float(max_width);
|
||||
|
||||
if ((TextureInfos[cnt].TextureWidth + x) > Bink->Width) {
|
||||
TextureInfos[cnt].TextureWidth = Bink->Width - x;
|
||||
TextureInfos[cnt].UV.Right = float(TextureInfos[cnt].TextureWidth - 1) / float(max_width);
|
||||
}
|
||||
|
||||
TextureInfos[cnt].TextureHeight = max_height;
|
||||
TextureInfos[cnt].UV.Bottom = float(max_height) / float(max_height);
|
||||
|
||||
if ((TextureInfos[cnt].TextureHeight + y) > Bink->Height) {
|
||||
TextureInfos[cnt].TextureHeight = Bink->Height - y;
|
||||
TextureInfos[cnt].UV.Bottom = float(TextureInfos[cnt].TextureHeight + 1) / float(max_height);
|
||||
}
|
||||
|
||||
TextureInfos[cnt].UV.Left = 1.0f / float(max_width);
|
||||
TextureInfos[cnt].UV.Top = 1.0f / float(max_height);
|
||||
|
||||
TextureInfos[cnt].Rect.Left = float(TextureInfos[cnt].TextureLocX) / float(Bink->Width);
|
||||
TextureInfos[cnt].Rect.Top = float(TextureInfos[cnt].TextureLocY) / float(Bink->Height);
|
||||
TextureInfos[cnt].Rect.Right = float(TextureInfos[cnt].TextureLocX + TextureInfos[cnt].TextureWidth) / float(Bink->Width);
|
||||
TextureInfos[cnt].Rect.Bottom = float(TextureInfos[cnt].TextureLocY + TextureInfos[cnt].TextureHeight) / float(Bink->Height);
|
||||
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
Renderer.Reset();
|
||||
|
||||
// Calculate the time per frame of video
|
||||
unsigned int rate = (Bink->FrameRate / Bink->FrameRateDiv);
|
||||
TicksPerFrame = (60 / rate);
|
||||
|
||||
if (subtitlename && font) {
|
||||
SubTitleManager = SubTitleManagerClass::Create(filename, subtitlename, font);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BINKMovieClass::~BINKMovieClass()
|
||||
{
|
||||
if (Bink == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Bink) {
|
||||
BinkClose(Bink);
|
||||
}
|
||||
|
||||
delete[] TempBuffer;
|
||||
|
||||
if (TextureInfos) {
|
||||
for (unsigned t = 0; t < TextureCount; ++t) {
|
||||
REF_PTR_RELEASE(TextureInfos[t].Texture);
|
||||
}
|
||||
|
||||
delete[] TextureInfos;
|
||||
}
|
||||
|
||||
if (SubTitleManager) {
|
||||
delete SubTitleManager;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BINKMovieClass::Update()
|
||||
{
|
||||
if (!Bink) {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameChanged |= !BinkWait(Bink);
|
||||
}
|
||||
|
||||
|
||||
static unsigned char* Get_Tex_Address(unsigned char* buffer, int x, int y, int w, int h)
|
||||
{
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (x >= w) {
|
||||
x = w - 1;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
} else if (y >= h) {
|
||||
y = h - 1;
|
||||
}
|
||||
|
||||
return buffer + x * 2 + y * 2 * w;
|
||||
}
|
||||
|
||||
|
||||
void BINKMovieClass::Render()
|
||||
{
|
||||
if (!Bink) {
|
||||
return;
|
||||
}
|
||||
|
||||
// decompress a frame
|
||||
if (FrameChanged) {
|
||||
BinkDoFrame(Bink);
|
||||
FrameChanged = false;
|
||||
|
||||
BinkCopyToBuffer(Bink, TempBuffer, Bink->Width * 2, Bink->Height, 0, 0, BINKSURFACE565|BINKCOPYNOSCALING);
|
||||
|
||||
for (unsigned t = 0; t < TextureCount; ++t) {
|
||||
IDirect3DTexture8* d3d_texture = TextureInfos[t].Texture->Peek_DX8_Texture();
|
||||
|
||||
if (d3d_texture) {
|
||||
unsigned char* cur_tex_ptr = Get_Tex_Address(TempBuffer, TextureInfos[t].TextureLocX,
|
||||
TextureInfos[t].TextureLocY, Bink->Width, Bink->Height);
|
||||
|
||||
unsigned w = TextureInfos[t].TextureWidth;
|
||||
unsigned h = TextureInfos[t].TextureHeight;
|
||||
|
||||
if (w > Bink->Width-TextureInfos[t].TextureLocX) {
|
||||
w = Bink->Width-TextureInfos[t].TextureLocX;
|
||||
}
|
||||
|
||||
if (h > Bink->Height-TextureInfos[t].TextureLocY) {
|
||||
h = Bink->Height-TextureInfos[t].TextureLocY;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC d3d_surf_desc;
|
||||
D3DLOCKED_RECT locked_rect;
|
||||
|
||||
DX8_ErrorCode(d3d_texture->GetLevelDesc(0, &d3d_surf_desc));
|
||||
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = w;
|
||||
rect.bottom = h;
|
||||
DX8_ErrorCode(d3d_texture->LockRect(0,&locked_rect,&rect,0));
|
||||
|
||||
for (unsigned y = 0; y < h; ++y) {
|
||||
unsigned char* dest = (unsigned char*)locked_rect.pBits + y * locked_rect.Pitch;
|
||||
memcpy(dest, cur_tex_ptr, w * 2);
|
||||
cur_tex_ptr += Bink->Width * 2;
|
||||
}
|
||||
|
||||
DX8_ErrorCode(d3d_texture->UnlockRect(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (Bink->FrameNum < Bink->Frames) // goto the next if not on the last
|
||||
BinkNextFrame(Bink);
|
||||
}
|
||||
|
||||
for (unsigned t = 0; t < TextureCount; ++t) {
|
||||
Renderer.Reset();
|
||||
Renderer.Set_Texture(TextureInfos[t].Texture);
|
||||
Renderer.Set_Coordinate_Range(RectClass(0.0f, 0.0f, 1.0f, 1.0f));//Bink->Width,Bink->Height));
|
||||
|
||||
RectClass rect(TextureInfos[t].TextureLocX, TextureInfos[t].TextureLocY, TextureInfos[t].TextureWidth, TextureInfos[t].TextureHeight);
|
||||
Renderer.Add_Quad(TextureInfos[t].Rect, TextureInfos[t].UV, 0xffffffff);
|
||||
Renderer.Render();
|
||||
}
|
||||
|
||||
if (SubTitleManager) {
|
||||
unsigned long movieTime = (Bink->FrameNum * TicksPerFrame);
|
||||
SubTitleManager->Process(movieTime);
|
||||
SubTitleManager->Render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BINKMovieClass::Is_Complete()
|
||||
{
|
||||
if (!Bink) return true;
|
||||
return (Bink->FrameNum>=Bink->Frames);
|
||||
}
|
||||
|
||||
58
Code/BinkMovie/BINKMovie.h
Normal file
58
Code/BinkMovie/BINKMovie.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(_MSV_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BINKMOVIE_H
|
||||
#define BINKMOVIE_H
|
||||
|
||||
#include "always.h"
|
||||
#include "wwstring.h"
|
||||
|
||||
class FontCharsClass;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// BINK movie player. You'll need to have binkw32.dll in the run directory!
|
||||
//
|
||||
// To start a movie call Play("movie.bik","subtitle_name");
|
||||
// To end movie playing call Stop();
|
||||
//
|
||||
// In order to change the subtitle properties see SubTitleManagerClass.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BINKMovie
|
||||
{
|
||||
public:
|
||||
static void Play(const char* filename,const char* subtitlename=NULL, FontCharsClass* font = NULL);
|
||||
static void Stop();
|
||||
static void Update();
|
||||
static void Render();
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
static bool Is_Complete();
|
||||
};
|
||||
|
||||
#endif
|
||||
157
Code/BinkMovie/BinkMovie.dsp
Normal file
157
Code/BinkMovie/BinkMovie.dsp
Normal file
@@ -0,0 +1,157 @@
|
||||
# Microsoft Developer Studio Project File - Name="BinkMovie" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=BinkMovie - Win32 Profile
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "BinkMovie.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "BinkMovie.mak" CFG="BinkMovie - Win32 Profile"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "BinkMovie - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "BinkMovie - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "BinkMovie - Win32 Profile" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Commando/Code/BinkMovie", XPFEAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "BinkMovie - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX- /Zi /O2 /Ob2 /I "..\wwmath" /I "..\\" /I "..\ww3d2" /I "..\wwdebug" /I "..\wwlib" /I "..\DirectX\Include" /D "NDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\Libs\Release\BinkMovie.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "BinkMovie - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GR- /GX- /ZI /Od /I "..\wwmath" /I "..\\" /I "..\ww3d2" /I "..\wwdebug" /I "..\wwlib" /I "..\DirectX\Include" /D "_DEBUG" /D "WWDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\Libs\Debug\BinkMovie.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "BinkMovie - Win32 Profile"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Profile"
|
||||
# PROP BASE Intermediate_Dir "Profile"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Profile"
|
||||
# PROP Intermediate_Dir "Profile"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MT /W4 /GX- /Zi /O2 /Ob2 /I "..\wwmath" /I "..\\" /I "..\ww3d2" /I "..\wwdebug" /I "..\wwlib" /I "..\DirectX\Include" /D "NDEBUG" /D "WWDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo /out:"Debug\BinkMovieD.lib"
|
||||
# ADD LIB32 /nologo /out:"..\Libs\Profile\BinkMovie.lib"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "BinkMovie - Win32 Release"
|
||||
# Name "BinkMovie - Win32 Debug"
|
||||
# Name "BinkMovie - Win32 Profile"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BINKMovie.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subtitle.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subtitlemanager.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subtitleparser.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BINK.H
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BINKMovie.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\RAD.H
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subtitle.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subtitlemanager.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subtitleparser.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
BIN
Code/BinkMovie/Debug/BinkMovie.pch
Normal file
BIN
Code/BinkMovie/Debug/BinkMovie.pch
Normal file
Binary file not shown.
BIN
Code/BinkMovie/Profile/BinkMovie.pch
Normal file
BIN
Code/BinkMovie/Profile/BinkMovie.pch
Normal file
Binary file not shown.
BIN
Code/BinkMovie/Release/BinkMovie.pch
Normal file
BIN
Code/BinkMovie/Release/BinkMovie.pch
Normal file
Binary file not shown.
156
Code/BinkMovie/subtitle.cpp
Normal file
156
Code/BinkMovie/subtitle.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /Commando/Code/BinkMovie/subtitle.cpp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Subtitling support.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Author: Denzil_l $
|
||||
* $Modtime: 1/15/02 8:48p $
|
||||
* $Revision: 2 $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "always.h"
|
||||
#include "subtitle.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleClass::SubTitleClass
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleClass::SubTitleClass()
|
||||
:
|
||||
mTimeStamp(0),
|
||||
mDuration(20 * 60),
|
||||
mRGBColor(0x00FFFFFF),
|
||||
mLinePosition(15),
|
||||
mAlignment(Center),
|
||||
mCaption(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleClass::~SubTitleClass
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleClass::~SubTitleClass()
|
||||
{
|
||||
if (mCaption != NULL) {
|
||||
delete[] mCaption;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleClass::SetRGBColor
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Set the color the subtitle caption should be displayed in.
|
||||
*
|
||||
* INPUTS
|
||||
* unsigned char red
|
||||
* unsigned char green
|
||||
* unsigned char blue
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void SubTitleClass::Set_RGB_Color(
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue)
|
||||
{
|
||||
// Combine components as 8:8:8
|
||||
mRGBColor = (
|
||||
((unsigned long)red << 16) |
|
||||
((unsigned long)green << 8) |
|
||||
(unsigned long)blue);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleClass::SetCaption
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Set the caption text
|
||||
*
|
||||
* INPUTS
|
||||
* Caption - Caption string
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void SubTitleClass::Set_Caption(wchar_t* string)
|
||||
{
|
||||
// Release existing caption
|
||||
if (mCaption != NULL) {
|
||||
delete[] mCaption;
|
||||
mCaption = NULL;
|
||||
}
|
||||
|
||||
// Make a copy of caption
|
||||
if (string != NULL) {
|
||||
unsigned int length = wcslen(string);
|
||||
mCaption = new wchar_t[length + 1];
|
||||
WWASSERT(mCaption != NULL);
|
||||
|
||||
if (mCaption != NULL) {
|
||||
wcscpy(mCaption, string);
|
||||
}
|
||||
}
|
||||
}
|
||||
112
Code/BinkMovie/subtitle.h
Normal file
112
Code/BinkMovie/subtitle.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /Commando/Code/BinkMovie/subtitle.h $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Subtitling support.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Author: Denzil_l $
|
||||
* $Modtime: 1/15/02 8:48p $
|
||||
* $Revision: 2 $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef _SUBTITLE_H_
|
||||
#define _SUBTITLE_H_
|
||||
|
||||
#include "always.h"
|
||||
#include "wwdebug.h"
|
||||
#include <wchar.h>
|
||||
|
||||
class SubTitleClass
|
||||
{
|
||||
public:
|
||||
SubTitleClass();
|
||||
~SubTitleClass();
|
||||
|
||||
// Set the time (in milliseconds) at which the subtitle is to be displayed.
|
||||
void Set_Display_Time(unsigned long time) { mTimeStamp = time; }
|
||||
|
||||
// Retrieve the time in ticks (1/60 seconds) this subtitle is to be displayed.
|
||||
unsigned long Get_Display_Time(void) const { return mTimeStamp; }
|
||||
|
||||
// Set the time duration in ticks (1/60 seconds) for the subtitle to remain displayed.
|
||||
void Set_Display_Duration(unsigned long duration) { mDuration = duration; }
|
||||
|
||||
// Retrieve the duration time in ticks (1/60 seconds) for the subtitle.
|
||||
unsigned long Get_Display_Duration(void) const { return mDuration; }
|
||||
|
||||
// Set the color the subtitle caption should be displayed in.
|
||||
void Set_RGB_Color(unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
||||
// Retrieve the color of the subtitle
|
||||
unsigned long Get_RGB_Color(void) const { return mRGBColor; }
|
||||
|
||||
// Set the line position the subtitle should be displayed at.
|
||||
void Set_Line_Position(int linePos)
|
||||
{
|
||||
WWASSERT((linePos >= 1) && (linePos <= 15));
|
||||
mLinePosition = linePos;
|
||||
}
|
||||
|
||||
// Retrieve the line position to display the subtitle at.
|
||||
int Get_Line_Position(void) const { return mLinePosition; }
|
||||
|
||||
// Caption justifications
|
||||
typedef enum
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Center,
|
||||
} Alignment;
|
||||
|
||||
// Set the alignment of the subtitle caption
|
||||
void Set_Alignment(Alignment align)
|
||||
{mAlignment = align;}
|
||||
|
||||
// Retrieve the caption justification
|
||||
Alignment Get_Alignment(void) const { return mAlignment; }
|
||||
|
||||
// Set the caption text
|
||||
void Set_Caption(wchar_t* string);
|
||||
|
||||
// Retrieve the caption text
|
||||
const wchar_t* Get_Caption(void) const { return mCaption; }
|
||||
|
||||
private:
|
||||
unsigned long mTimeStamp;
|
||||
unsigned long mDuration;
|
||||
unsigned long mRGBColor;
|
||||
int mLinePosition;
|
||||
Alignment mAlignment;
|
||||
wchar_t* mCaption;
|
||||
};
|
||||
|
||||
#endif // _SUBTITLE_H_
|
||||
351
Code/BinkMovie/subtitlemanager.cpp
Normal file
351
Code/BinkMovie/subtitlemanager.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /Commando/Code/BinkMovie/subtitlemanager.cpp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Subtitling manager
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Author: Denzil_l $
|
||||
* $Modtime: 1/24/02 10:11a $
|
||||
* $Revision: 3 $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "always.h"
|
||||
#include "subtitlemanager.h"
|
||||
#include "subtitleparser.h"
|
||||
#include "subtitle.h"
|
||||
#include "xstraw.h"
|
||||
#include "rawfile.h"
|
||||
#include "assetmgr.h"
|
||||
#include "ww3d.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::Create
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Instantiate a subtitle manager for the specified movie.
|
||||
*
|
||||
* INPUTS
|
||||
* Filename - Name of movie file to create subtitle manager for.
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleManagerClass* SubTitleManagerClass::Create(const char* filename, const char* subtitlefilename, FontCharsClass* font)
|
||||
{
|
||||
if ((filename == NULL) || (strlen(filename) == 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (subtitlefilename && !font) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create subtitle manager for the vqa
|
||||
SubTitleManagerClass* instance = new SubTitleManagerClass();
|
||||
WWASSERT(instance != NULL);
|
||||
|
||||
if (instance != NULL) {
|
||||
instance->Set_Font(font);
|
||||
|
||||
// Retrieve moviename
|
||||
char fname[_MAX_FNAME];
|
||||
_splitpath(filename, NULL, NULL, fname, NULL);
|
||||
bool loaded = instance->Load_Sub_Titles(fname, subtitlefilename);
|
||||
|
||||
if (loaded == false) {
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::SubTitleManagerClass
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleManagerClass::SubTitleManagerClass()
|
||||
:
|
||||
mSubTitles(NULL),
|
||||
mSubTitleIndex(0),
|
||||
mActiveSubTitle(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::~SubTitleManagerClass
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleManagerClass::~SubTitleManagerClass()
|
||||
{
|
||||
// Release subtitle entries
|
||||
if (mSubTitles != NULL) {
|
||||
for (int index = 0; index < mSubTitles->Count(); index++) {
|
||||
delete (*mSubTitles)[index];
|
||||
}
|
||||
|
||||
delete mSubTitles;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SubTitleManagerClass::Set_Font(FontCharsClass* font)
|
||||
{
|
||||
if (font) {
|
||||
Renderer.Set_Font(font);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::LoadSubTitles
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* Moviename - Pointer to movie name
|
||||
*
|
||||
* RESULTS
|
||||
* Success -
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bool SubTitleManagerClass::Load_Sub_Titles(const char* moviename, const char* subtitlefilename)
|
||||
{
|
||||
if ((moviename == NULL) || (strlen(moviename) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((subtitlefilename == NULL) || (strlen(subtitlefilename) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RawFileClass file(subtitlefilename);
|
||||
|
||||
if (!file.Is_Available()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileStraw input(file);
|
||||
SubTitleParserClass parser(input);
|
||||
|
||||
mSubTitles = parser.Get_Sub_Titles(moviename);
|
||||
|
||||
if (mSubTitles == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Make sure entries are sorted by time.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::Process
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Handle subtitle processing. This must be called each frame advance.
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bool SubTitleManagerClass::Process(unsigned long movieTime)
|
||||
{
|
||||
if (mSubTitles == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool update = false;
|
||||
|
||||
for (;;) {
|
||||
// Terminate if there aren't more subtitles
|
||||
if (mSubTitleIndex >= mSubTitles->Count()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next subtitle
|
||||
SubTitleClass* subtitle = (*mSubTitles)[mSubTitleIndex];
|
||||
WWASSERT(subtitle != NULL);
|
||||
|
||||
// Check the display time against the current movie time. If it is time
|
||||
// to display the subtitle then send a subtitle event to the client.
|
||||
unsigned long displayTime = subtitle->Get_Display_Time();
|
||||
|
||||
// If its not time then we are done.
|
||||
if (displayTime > movieTime) {
|
||||
break;
|
||||
} else {
|
||||
// Make this subtitle the active one
|
||||
mActiveSubTitle = subtitle;
|
||||
|
||||
// Advance to the next subtitle entry
|
||||
mSubTitleIndex++;
|
||||
|
||||
Draw_Sub_Title(subtitle);
|
||||
update = true;
|
||||
|
||||
// WWDEBUG_SAY(("SubTitle: %04d @ %u\n", mSubTitleIndex, movieTime));
|
||||
}
|
||||
}
|
||||
|
||||
// If the active subtitles duration has expired then remove it as being active.
|
||||
if (mActiveSubTitle != NULL) {
|
||||
SubTitleClass* subtitle = mActiveSubTitle;
|
||||
unsigned long expireTime = subtitle->Get_Display_Time() + subtitle->Get_Display_Duration();
|
||||
|
||||
if (movieTime >= expireTime) {
|
||||
mActiveSubTitle = NULL;
|
||||
|
||||
// Erase subtitle
|
||||
Renderer.Reset();
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::Reset
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void SubTitleManagerClass::Reset(void)
|
||||
{
|
||||
mSubTitleIndex = 0;
|
||||
mActiveSubTitle = NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleManagerClass::DrawSubTitle
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* const SubTitleClass* subtitle
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void SubTitleManagerClass::Draw_Sub_Title(const SubTitleClass* subtitle)
|
||||
{
|
||||
WWASSERT(subtitle != NULL);
|
||||
|
||||
Renderer.Reset();
|
||||
|
||||
unsigned short* string = (unsigned short*)subtitle->Get_Caption();
|
||||
|
||||
int w,h,bits;
|
||||
bool windowed;
|
||||
WW3D::Get_Device_Resolution(w,h,bits,windowed);
|
||||
Vector2 extents=Renderer.Get_Text_Extents( string );
|
||||
|
||||
// Assume left justification
|
||||
int xPos = 0;
|
||||
int yPos = subtitle->Get_Line_Position() * (h/16);
|
||||
int xSize=extents[0];
|
||||
|
||||
SubTitleClass::Alignment align = subtitle->Get_Alignment();
|
||||
|
||||
if (align == SubTitleClass::Center) {
|
||||
xPos = ((w - xSize) / 2);
|
||||
}
|
||||
else if (align == SubTitleClass::Right) {
|
||||
xPos = (w - xSize);
|
||||
}
|
||||
|
||||
Renderer.Set_Location(Vector2(xPos,yPos));
|
||||
Renderer.Build_Sentence(string);
|
||||
|
||||
// Set font color
|
||||
unsigned long rgbColor = subtitle->Get_RGB_Color()|0xff000000;
|
||||
|
||||
Renderer.Draw_Sentence(rgbColor);
|
||||
}
|
||||
|
||||
|
||||
void SubTitleManagerClass::Render()
|
||||
{
|
||||
Renderer.Render();
|
||||
}
|
||||
87
Code/BinkMovie/subtitlemanager.h
Normal file
87
Code/BinkMovie/subtitlemanager.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /Commando/Code/BinkMovie/subtitlemanager.h $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Subtitling manager
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Author: Denzil_l $
|
||||
* $Modtime: 1/15/02 9:13p $
|
||||
* $Revision: 2 $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef _SUBTITLEMANAGER_H_
|
||||
#define _SUBTITLEMANAGER_H_
|
||||
|
||||
#include "always.h"
|
||||
#include <wwlib\vector.h>
|
||||
#include "wwstring.h"
|
||||
#include <windows.h>
|
||||
#include "render2dsentence.h"
|
||||
|
||||
class SubTitleClass;
|
||||
class Surface;
|
||||
|
||||
class SubTitleManagerClass
|
||||
{
|
||||
public:
|
||||
// Instantiate a subtitle manager
|
||||
static SubTitleManagerClass* Create(const char* filename, const char* subtitlefilename, FontCharsClass* font);
|
||||
|
||||
// Destroy subtitle manager
|
||||
~SubTitleManagerClass();
|
||||
|
||||
// Check if there are subtitles.
|
||||
bool Has_Sub_Titles(void) const { return (mSubTitles != NULL); }
|
||||
|
||||
// Reset subtitles to start
|
||||
void Reset(void);
|
||||
|
||||
// Process subtitles
|
||||
bool Process(unsigned long movieTime);
|
||||
void Render();
|
||||
|
||||
private:
|
||||
// Prevent direct creation
|
||||
SubTitleManagerClass();
|
||||
|
||||
void Set_Font(FontCharsClass* font);
|
||||
|
||||
bool Load_Sub_Titles(const char* moviename, const char* subtitlefilename);
|
||||
void Draw_Sub_Title(const SubTitleClass* subtitle);
|
||||
|
||||
DynamicVectorClass<class SubTitleClass*>* mSubTitles;
|
||||
int mSubTitleIndex;
|
||||
SubTitleClass* mActiveSubTitle;
|
||||
Render2DSentenceClass Renderer;
|
||||
};
|
||||
|
||||
#endif // _SUBTITLEMANAGER_H_
|
||||
583
Code/BinkMovie/subtitleparser.cpp
Normal file
583
Code/BinkMovie/subtitleparser.cpp
Normal file
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /Commando/Code/BinkMovie/subtitleparser.cpp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Subtitling control file parser
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Author: Denzil_l $
|
||||
* $Modtime: 1/12/02 9:27p $
|
||||
* $Revision: 2 $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "subtitleparser.h"
|
||||
#include "subtitle.h"
|
||||
#include "straw.h"
|
||||
#include "readline.h"
|
||||
#include "trim.h"
|
||||
#include <wchar.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Subtitle control file parsing tokens
|
||||
#define BEGINMOVIE_TOKEN L"BeginMovie"
|
||||
#define ENDMOVIE_TOKEN L"EndMovie"
|
||||
#define TIMEBIAS_TOKEN L"TimeBias"
|
||||
#define TIME_TOKEN L"Time"
|
||||
#define DURATION_TOKEN L"Duration"
|
||||
#define POSITION_TOKEN L"Position"
|
||||
#define COLOR_TOKEN L"Color"
|
||||
#define TEXT_TOKEN L"Text"
|
||||
|
||||
unsigned long DecodeTimeString(wchar_t* string);
|
||||
void Parse_Time(wchar_t* string, SubTitleClass* subTitle);
|
||||
void Parse_Duration(wchar_t* string, SubTitleClass* subTitle);
|
||||
void Parse_Position(wchar_t* string, SubTitleClass* subTitle);
|
||||
void Parse_Color(wchar_t* string, SubTitleClass* subTitle);
|
||||
void Parse_Text(wchar_t* string, SubTitleClass* subTitle);
|
||||
|
||||
SubTitleParserClass::TokenHook SubTitleParserClass::mTokenHooks[] =
|
||||
{
|
||||
{TIME_TOKEN, Parse_Time},
|
||||
{DURATION_TOKEN, Parse_Duration},
|
||||
{POSITION_TOKEN, Parse_Position},
|
||||
{COLOR_TOKEN, Parse_Color},
|
||||
{TEXT_TOKEN, Parse_Text},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::SubTitleParserClass
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* Input - Control file input stream.
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleParserClass::SubTitleParserClass(Straw& input)
|
||||
:
|
||||
mInput(input),
|
||||
mLineNumber(0)
|
||||
{
|
||||
// Check for Unicode byte-order mark.
|
||||
// All Unicode plaintext files are prefixed with the byte-order mark U+FEFF
|
||||
// or its mirror U+FFFE. This mark is used to indicate the byte order of a
|
||||
// text stream.
|
||||
wchar_t byteOrderMark = 0;
|
||||
mInput.Get(&byteOrderMark, sizeof(wchar_t));
|
||||
WWASSERT(byteOrderMark == 0xFEFF);
|
||||
|
||||
if (byteOrderMark != 0xFEFF) {
|
||||
WWDEBUG_SAY(("Error: Subtitle control file is not unicode!\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::~SubTitleParserClass
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
SubTitleParserClass::~SubTitleParserClass()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::GetSubTitles
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
DynamicVectorClass<SubTitleClass*>* SubTitleParserClass::Get_Sub_Titles(const char* moviename)
|
||||
{
|
||||
DynamicVectorClass<SubTitleClass*>* subTitleCollection = NULL;
|
||||
|
||||
// Find the movie marker
|
||||
if (Find_Movie_Entry(moviename) == true) {
|
||||
// Allocate container to hold subtitles
|
||||
subTitleCollection = new DynamicVectorClass<SubTitleClass*>;
|
||||
WWASSERT(subTitleCollection != NULL);
|
||||
|
||||
if (subTitleCollection != NULL) {
|
||||
for (;;) {
|
||||
// Retrieve a line from the control file
|
||||
wchar_t* string = Get_Next_Line();
|
||||
|
||||
if ((string != NULL) && (wcslen(string) > 0)) {
|
||||
// Check for subtitle entry markers
|
||||
if ((string[0] == L'<') && (string[wcslen(string) - 1] == L'>')) {
|
||||
// Trim off markers
|
||||
string++;
|
||||
string[wcslen(string) - 1] = 0;
|
||||
wcstrim(string);
|
||||
|
||||
// Ignore empty caption
|
||||
if (wcslen(string) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a new SubTitleClass
|
||||
SubTitleClass* subTitle = new SubTitleClass();
|
||||
WWASSERT(subTitle != NULL);
|
||||
|
||||
if (subTitle == NULL) {
|
||||
WWDEBUG_SAY(("***** Failed to create SubTitleClass!\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (Parse_Sub_Title(string, subTitle) == true) {
|
||||
subTitleCollection->Add(subTitle);
|
||||
}
|
||||
else {
|
||||
delete subTitle;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Terminate if end movie token encountered.
|
||||
if (wcsnicmp(string, ENDMOVIE_TOKEN, wcslen(ENDMOVIE_TOKEN)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (subTitleCollection->Count() == 0) {
|
||||
delete subTitleCollection;
|
||||
subTitleCollection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subTitleCollection;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::FindMovieEntry
|
||||
*
|
||||
* DESCRIPTION
|
||||
* No description provided,
|
||||
*
|
||||
* INPUTS
|
||||
* Moviename - Pointer to name of movie to find subtitles for.
|
||||
*
|
||||
* RESULTS
|
||||
* Success - True if movie entry found; False if unable to find movie entry.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bool SubTitleParserClass::Find_Movie_Entry(const char* moviename)
|
||||
{
|
||||
// Convert the moviename into Unicode
|
||||
WWASSERT(moviename != NULL);
|
||||
wchar_t wideName[32];
|
||||
mbstowcs(wideName, moviename, 32);
|
||||
|
||||
do {
|
||||
// Retrieve line of text
|
||||
wchar_t* string = Get_Next_Line();
|
||||
|
||||
// Terminate if no string read.
|
||||
if (string == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for begin movie token
|
||||
if (wcsnicmp(string, BEGINMOVIE_TOKEN, wcslen(BEGINMOVIE_TOKEN)) == 0) {
|
||||
// Get moviename following the token
|
||||
wchar_t* ptr = wcschr(string, L' ');
|
||||
|
||||
// Check for matching moviename
|
||||
if (ptr != NULL) {
|
||||
wcstrim(ptr);
|
||||
|
||||
if (wcsicmp(ptr, wideName) == 0) {
|
||||
WWDEBUG_SAY(("Found movie entry %s\n", moviename));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::ParseSubTitle
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* wchar_t* string
|
||||
* SubTitleClass* subTitle
|
||||
*
|
||||
* RESULTS
|
||||
* bool
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bool SubTitleParserClass::Parse_Sub_Title(wchar_t* string, SubTitleClass* subTitle)
|
||||
{
|
||||
// Parameter check
|
||||
WWASSERT(string != NULL);
|
||||
WWASSERT(subTitle != NULL);
|
||||
|
||||
for (;;) {
|
||||
// Find token separator
|
||||
wchar_t* separator = wcschr(string, L'=');
|
||||
|
||||
if (separator == NULL) {
|
||||
WWDEBUG_SAY(("Error on line %d: syntax error\n", Get_Line_Number()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// NULL terminate token part
|
||||
*separator++ = 0;
|
||||
|
||||
// Tokens are to the left of the separator
|
||||
wchar_t* token = string;
|
||||
wcstrim(token);
|
||||
|
||||
// Parameters are to the right of the separator
|
||||
wchar_t* param = separator;
|
||||
wcstrim(param);
|
||||
|
||||
// Quoted parameters are treated as literals (ignore contents)
|
||||
if (param[0] == L'"') {
|
||||
// Skip leading quote
|
||||
param++;
|
||||
|
||||
// Use next quote to mark end of parameter
|
||||
separator = wcschr(param, L'"');
|
||||
|
||||
if (separator == NULL) {
|
||||
WWDEBUG_SAY(("Error on line %d: mismatched quotes\n", Get_Line_Number()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// NULL terminate parameter
|
||||
*separator++ = 0;
|
||||
|
||||
// Skip any comma following a literal string since we used the trailing
|
||||
// quote to terminate the tokens parameters
|
||||
wcstrim(separator);
|
||||
|
||||
if (*separator == L',') {
|
||||
separator++;
|
||||
}
|
||||
|
||||
// Advance string past quoted parameter
|
||||
string = separator;
|
||||
}
|
||||
else {
|
||||
// Look for separator to next token
|
||||
separator = wcspbrk(param, L", ");
|
||||
|
||||
if (separator != NULL) {
|
||||
*separator++ = 0;
|
||||
string = separator;
|
||||
}
|
||||
else {
|
||||
string = L"";
|
||||
}
|
||||
}
|
||||
|
||||
// Error on empty tokens
|
||||
if (wcslen(token) == 0) {
|
||||
WWDEBUG_SAY(("Error on line %d: missing token\n", Get_Line_Number()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse current token
|
||||
Parse_Token(token, param, subTitle);
|
||||
|
||||
// Prepare for next token
|
||||
wcstrim(string);
|
||||
|
||||
if (wcslen(string) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::ParseToken
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* wchar_t* token
|
||||
* wchar_t* param
|
||||
* SubTitleClass* subTitle
|
||||
*
|
||||
* RESULTS
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void SubTitleParserClass::Parse_Token(wchar_t* token, wchar_t* param, SubTitleClass* subTitle)
|
||||
{
|
||||
// Parameter check
|
||||
WWASSERT(token != NULL);
|
||||
WWASSERT(subTitle != NULL);
|
||||
|
||||
if (token != NULL) {
|
||||
int index = 0;
|
||||
|
||||
while (mTokenHooks[index].Token != NULL) {
|
||||
TokenHook& hook = mTokenHooks[index];
|
||||
|
||||
if (wcsicmp(hook.Token, token) == 0) {
|
||||
WWASSERT(subTitle != NULL);
|
||||
hook.Handler(param, subTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SubTitleParserClass::GetNextLine
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Retrieve the next line of text from the control file.
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULTS
|
||||
* String - Pointer to next line of text. NULL if error or EOF.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
wchar_t* SubTitleParserClass::Get_Next_Line(void)
|
||||
{
|
||||
bool eof = false;
|
||||
|
||||
while (eof == false) {
|
||||
// Read in a line of text
|
||||
Read_Line(mInput, mBuffer, LINE_MAX, eof);
|
||||
mLineNumber++;
|
||||
|
||||
// Remove whitespace
|
||||
wchar_t* string = wcstrim(mBuffer);
|
||||
|
||||
// Skip comments and blank lines
|
||||
if ((wcslen(string) > 0) && (string[0] != L';')) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Convert a time string in the format hh:mm:ss:tt into 1/60 second ticks.
|
||||
unsigned long Decode_Time_String(wchar_t* string)
|
||||
{
|
||||
#define TICKS_PER_SECOND 60
|
||||
#define TICKS_PER_MINUTE (60 * TICKS_PER_SECOND)
|
||||
#define TICKS_PER_HOUR (60 * TICKS_PER_MINUTE)
|
||||
|
||||
WWASSERT(string != NULL);
|
||||
|
||||
wchar_t buffer[12];
|
||||
wcsncpy(buffer, string, 12);
|
||||
buffer[11] = 0;
|
||||
|
||||
wchar_t* ptr = &buffer[0];
|
||||
|
||||
// Isolate hours part
|
||||
wchar_t* separator = wcschr(ptr, L':');
|
||||
WWASSERT(separator != NULL);
|
||||
*separator++ = 0;
|
||||
unsigned long hours = wcstoul(ptr, NULL, 10);
|
||||
|
||||
// Isolate minutes part
|
||||
ptr = separator;
|
||||
separator = wcschr(ptr, L':');
|
||||
WWASSERT(separator != NULL);
|
||||
*separator++ = 0;
|
||||
unsigned long minutes = wcstoul(ptr, NULL, 10);
|
||||
|
||||
// Isolate seconds part
|
||||
ptr = separator;
|
||||
separator = wcschr(ptr, L':');
|
||||
WWASSERT(separator != NULL);
|
||||
*separator++ = 0;
|
||||
unsigned long seconds = wcstoul(ptr, NULL, 10);
|
||||
|
||||
// Isolate hundredth part (1/100th of a second)
|
||||
ptr = separator;
|
||||
unsigned long hundredth = wcstoul(ptr, NULL, 10);
|
||||
|
||||
unsigned long time = (hours * TICKS_PER_HOUR);
|
||||
time += (minutes * TICKS_PER_MINUTE);
|
||||
time += (seconds * TICKS_PER_SECOND);
|
||||
time += ((hundredth * TICKS_PER_SECOND) / 100);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
void Parse_Time(wchar_t* param, SubTitleClass* subTitle)
|
||||
{
|
||||
WWASSERT(param != NULL);
|
||||
WWASSERT(subTitle != NULL);
|
||||
unsigned long time = Decode_Time_String(param);
|
||||
subTitle->Set_Display_Time(time);
|
||||
}
|
||||
|
||||
|
||||
void Parse_Duration(wchar_t* param, SubTitleClass* subTitle)
|
||||
{
|
||||
WWASSERT(param != NULL);
|
||||
WWASSERT(subTitle != NULL);
|
||||
unsigned long time = Decode_Time_String(param);
|
||||
|
||||
if (time > 0) {
|
||||
subTitle->Set_Display_Duration(time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Parse_Position(wchar_t* param, SubTitleClass* subTitle)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
const wchar_t* Name;
|
||||
SubTitleClass::Alignment Align;
|
||||
} _alignLookup[] = {
|
||||
{L"Left", SubTitleClass::Left},
|
||||
{L"Right", SubTitleClass::Right},
|
||||
{L"Center", SubTitleClass::Center},
|
||||
{NULL, SubTitleClass::Center}
|
||||
};
|
||||
|
||||
WWASSERT(subTitle != NULL);
|
||||
WWASSERT(param != NULL);
|
||||
|
||||
wchar_t* ptr = param;
|
||||
|
||||
// Line position
|
||||
wchar_t* separator = wcschr(ptr, L':');
|
||||
|
||||
if (separator != NULL) {
|
||||
*separator++ = 0;
|
||||
int linePos = wcstol(ptr, NULL, 0);
|
||||
subTitle->Set_Line_Position(linePos);
|
||||
ptr = separator;
|
||||
}
|
||||
|
||||
// Justification
|
||||
SubTitleClass::Alignment align = SubTitleClass::Center;
|
||||
int index = 0;
|
||||
|
||||
while (_alignLookup[index].Name != NULL) {
|
||||
if (wcsicmp(ptr, _alignLookup[index].Name) == 0) {
|
||||
align = _alignLookup[index].Align;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
subTitle->Set_Alignment(align);
|
||||
}
|
||||
|
||||
|
||||
void Parse_Color(wchar_t* param, SubTitleClass* subTitle)
|
||||
{
|
||||
WWASSERT(param != NULL);
|
||||
WWASSERT(subTitle != NULL);
|
||||
|
||||
wchar_t* ptr = param;
|
||||
|
||||
wchar_t* separator = wcschr(ptr, L':');
|
||||
*separator++ = 0;
|
||||
unsigned char red = (unsigned char)wcstoul(ptr, NULL, 10);
|
||||
|
||||
ptr = separator;
|
||||
separator = wcschr(ptr, L':');
|
||||
*separator++ = 0;
|
||||
unsigned char green = (unsigned char)wcstoul(ptr, NULL, 10);
|
||||
|
||||
ptr = separator;
|
||||
unsigned char blue = (unsigned char)wcstoul(ptr, NULL, 10);
|
||||
|
||||
subTitle->Set_RGB_Color(red, green, blue);
|
||||
}
|
||||
|
||||
|
||||
void Parse_Text(wchar_t* param, SubTitleClass* subTitle)
|
||||
{
|
||||
WWASSERT(param != NULL);
|
||||
WWASSERT(subTitle != NULL);
|
||||
|
||||
subTitle->Set_Caption(param);
|
||||
}
|
||||
84
Code/BinkMovie/subtitleparser.h
Normal file
84
Code/BinkMovie/subtitleparser.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /Commando/Code/BinkMovie/subtitleparser.h $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Subtitling control file parser
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Author: Ian_l $
|
||||
* $Modtime: 8/24/01 2:36p $
|
||||
* $Revision: 1 $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef _SUBTITLEPARSER_H_
|
||||
#define _SUBTITLEPARSER_H_
|
||||
|
||||
#include "always.h"
|
||||
#include <wwlib\vector.h>
|
||||
#include <stddef.h>
|
||||
|
||||
class Straw;
|
||||
class SubTitleClass;
|
||||
|
||||
class SubTitleParserClass
|
||||
{
|
||||
public:
|
||||
SubTitleParserClass(Straw& input);
|
||||
~SubTitleParserClass();
|
||||
|
||||
DynamicVectorClass<SubTitleClass*>* Get_Sub_Titles(const char* moviename);
|
||||
|
||||
private:
|
||||
enum {LINE_MAX = 1024};
|
||||
|
||||
typedef struct tagTokenHook
|
||||
{
|
||||
const wchar_t* Token;
|
||||
void (*Handler)(wchar_t* param, SubTitleClass* subTitle);
|
||||
} TokenHook;
|
||||
|
||||
// Prevent copy construction
|
||||
SubTitleParserClass(const SubTitleParserClass&);
|
||||
const SubTitleParserClass operator=(const SubTitleParserClass&);
|
||||
|
||||
bool Find_Movie_Entry(const char* moviename);
|
||||
bool Parse_Sub_Title(wchar_t* string, SubTitleClass* subTitle);
|
||||
void Parse_Token(wchar_t* token, wchar_t* param, SubTitleClass* subTitle);
|
||||
wchar_t* Get_Next_Line(void);
|
||||
unsigned int Get_Line_Number(void) const {return mLineNumber;}
|
||||
|
||||
static TokenHook mTokenHooks[];
|
||||
Straw& mInput;
|
||||
wchar_t mBuffer[LINE_MAX];
|
||||
unsigned int mLineNumber;
|
||||
};
|
||||
|
||||
#endif // _SUBTITLEPARSER_H_
|
||||
Reference in New Issue
Block a user