This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -0,0 +1,7 @@
Texture MyTex
{
Source loader_icon.bmp
Format D3DFMT_DXT1
Width 128
Height 128
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

View File

@@ -0,0 +1,173 @@
// List of resources to bundle.
//
// The output will be a header file (.h) used at compile time,
// and a packed resource file (.xpr) used at runtime.
out_packedresource LoaderMedia\loader.xpr
out_error loader.err
Texture Font
{
Source LoaderMedia_Source\Tahoma_16.tga
Format D3DFMT_A4R4G4B4
Levels 1
}
UserData FontData
{
DataFile LoaderMedia_Source\Tahoma_16.abc
}
Texture Footer
{
Source LoaderMedia_Source\Footer.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture MainLegal_english
{
Source LoaderMedia_Source\LegalScreen_english.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture MainLegal_french
{
Source LoaderMedia_Source\LegalScreen_french.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture MainLegal_italian
{
Source LoaderMedia_Source\LegalScreen_italian.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture MainLegal_german
{
Source LoaderMedia_Source\LegalScreen_german.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture MainLegal_spanish
{
Source LoaderMedia_Source\LegalScreen_spanish.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SourceLegal
{
Source LoaderMedia_Source\SourceScreen.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture LoadingIcon
{
Source LoaderMedia_Source\LoadingIcon.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow1_english
{
Source LoaderMedia_Source\SlideShow1_english.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow1_french
{
Source LoaderMedia_Source\SlideShow1_french.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow1_italian
{
Source LoaderMedia_Source\SlideShow1_italian.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow1_german
{
Source LoaderMedia_Source\SlideShow1_german.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow1_spanish
{
Source LoaderMedia_Source\SlideShow1_spanish.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow2
{
Source LoaderMedia_Source\SlideShow2.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow3
{
Source LoaderMedia_Source\SlideShow3.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow4
{
Source LoaderMedia_Source\SlideShow4.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow5
{
Source LoaderMedia_Source\SlideShow5.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow6
{
Source LoaderMedia_Source\SlideShow6.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow7
{
Source LoaderMedia_Source\SlideShow7.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow8
{
Source LoaderMedia_Source\SlideShow8.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}
Texture SlideShow9
{
Source LoaderMedia_Source\SlideShow9.tga
Format D3DFMT_LIN_A8R8G8B8
Levels 1
}

View File

@@ -0,0 +1,595 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Copies a file using overlapped async IO.
//
// Stub executeable
//=====================================================================================//
#include "xbox_loader.h"
#define BUFFER_SIZE (1*1024*1024)
#define NUM_BUFFERS 4
#define ALIGN(x,y) (((x)+(y)-1) & ~((y)-1))
struct CopyFile_t
{
// source file
HANDLE m_hSrcFile;
DWORD m_srcFileSize;
int m_readBufferSize;
unsigned int m_numReadCycles;
// target file
HANDLE m_hDstFile;
DWORD m_dstFileSize;
// source file gets decompressed
bool m_bInflate;
unsigned char *m_pInflateBuffer;
int m_inflateBufferSize;
bool m_bCopyError;
CopyStats_t *m_pCopyStats;
};
struct Buffer_t
{
unsigned char *pData;
DWORD dwSize;
Buffer_t* pNext;
int id;
};
Buffer_t *g_pReadBuffers = NULL;
Buffer_t *g_pWriteBuffers = NULL;
CRITICAL_SECTION g_criticalSection;
HANDLE g_hReadEvent;
HANDLE g_hWriteEvent;
DWORD *g_pNumReadBuffers;
DWORD *g_pNumWriteBuffers;
//-----------------------------------------------------------------------------
// CreateFilePath
//
// Create full path to specified file.
//-----------------------------------------------------------------------------
bool CreateFilePath( const char *inPath )
{
char* ptr;
char dirPath[MAX_PATH];
BOOL bSuccess;
// prime and skip to first seperator after the drive path
strcpy( dirPath, inPath );
ptr = strchr( dirPath, '\\' );
while ( ptr )
{
ptr = strchr( ptr+1, '\\' );
if ( ptr )
{
*ptr = '\0';
bSuccess = ::CreateDirectory( dirPath, NULL );
*ptr = '\\';
}
}
// ensure read-only is cleared
SetFileAttributes( inPath, FILE_ATTRIBUTE_NORMAL );
return true;
}
//-----------------------------------------------------------------------------
// LockBufferForRead
//
//-----------------------------------------------------------------------------
Buffer_t *LockBufferForRead()
{
if ( !g_pReadBuffers )
{
// out of data, wait for it
WaitForSingleObject( g_hReadEvent, INFINITE );
}
else
{
ResetEvent( g_hReadEvent );
}
EnterCriticalSection( &g_criticalSection );
Buffer_t *pBuffer = g_pReadBuffers;
g_pReadBuffers = pBuffer->pNext;
(*g_pNumReadBuffers)--;
LeaveCriticalSection( &g_criticalSection );
return pBuffer;
}
//-----------------------------------------------------------------------------
// LockBufferForWrite
//
//-----------------------------------------------------------------------------
Buffer_t* LockBufferForWrite()
{
if ( !g_pWriteBuffers )
{
// out of data, wait for more
WaitForSingleObject( g_hWriteEvent, INFINITE );
}
else
{
ResetEvent( g_hWriteEvent );
}
EnterCriticalSection( &g_criticalSection );
Buffer_t *pBuffer = g_pWriteBuffers;
g_pWriteBuffers = pBuffer->pNext;
(*g_pNumWriteBuffers)--;
LeaveCriticalSection( &g_criticalSection );
return pBuffer;
}
//-----------------------------------------------------------------------------
// AddBufferForRead
//
//-----------------------------------------------------------------------------
void AddBufferForRead( Buffer_t *pBuffer )
{
EnterCriticalSection( &g_criticalSection );
// add to end of list
Buffer_t *pCurrent = g_pReadBuffers;
while ( pCurrent && pCurrent->pNext )
{
pCurrent = pCurrent->pNext;
}
if ( pCurrent )
{
pBuffer->pNext = pCurrent->pNext;
pCurrent->pNext = pBuffer;
}
else
{
pBuffer->pNext = NULL;
g_pReadBuffers = pBuffer;
}
(*g_pNumReadBuffers)++;
LeaveCriticalSection( &g_criticalSection );
SetEvent( g_hReadEvent );
}
//-----------------------------------------------------------------------------
// AddBufferForWrite
//
//-----------------------------------------------------------------------------
void AddBufferForWrite( Buffer_t *pBuffer )
{
EnterCriticalSection( &g_criticalSection );
// add to end of list
Buffer_t* pCurrent = g_pWriteBuffers;
while ( pCurrent && pCurrent->pNext )
{
pCurrent = pCurrent->pNext;
}
if ( pCurrent )
{
pBuffer->pNext = pCurrent->pNext;
pCurrent->pNext = pBuffer;
}
else
{
pBuffer->pNext = NULL;
g_pWriteBuffers = pBuffer;
}
(*g_pNumWriteBuffers)++;
LeaveCriticalSection( &g_criticalSection );
SetEvent( g_hWriteEvent );
}
//-----------------------------------------------------------------------------
// ReadFileThread
//
//-----------------------------------------------------------------------------
DWORD WINAPI ReadFileThread( LPVOID lParam )
{
CopyFile_t *pCopyFile;
OVERLAPPED overlappedRead = {0};
DWORD startTime;
DWORD dwBytesRead;
DWORD dwError;
BOOL bResult;
Buffer_t *pBuffer;
pCopyFile = (CopyFile_t*)lParam;
// Copy from the buffer to the Hard Drive
for ( unsigned int readCycle = 0; readCycle < pCopyFile->m_numReadCycles; ++readCycle )
{
pBuffer = LockBufferForRead();
startTime = GetTickCount();
dwBytesRead = 0;
int numAttempts = 0;
retry:
// read file from DVD
bResult = ReadFile( pCopyFile->m_hSrcFile, pBuffer->pData, pCopyFile->m_readBufferSize, NULL, &overlappedRead );
dwError = GetLastError();
if ( !bResult && dwError != ERROR_IO_PENDING )
{
if ( dwError == ERROR_HANDLE_EOF )
{
// nothing more to read
break;
}
numAttempts++;
if ( numAttempts == 3 )
{
// error
pCopyFile->m_bCopyError = true;
break;
}
else
{
goto retry;
}
}
else
{
// Wait for the operation to finish
GetOverlappedResult( pCopyFile->m_hSrcFile, &overlappedRead, &dwBytesRead, TRUE );
overlappedRead.Offset += dwBytesRead;
}
if ( !dwBytesRead )
{
pCopyFile->m_bCopyError = true;
break;
}
pCopyFile->m_pCopyStats->m_bufferReadSize = dwBytesRead;
pCopyFile->m_pCopyStats->m_bufferReadTime = GetTickCount() - startTime;
pCopyFile->m_pCopyStats->m_totalReadSize += pCopyFile->m_pCopyStats->m_bufferReadSize;
pCopyFile->m_pCopyStats->m_totalReadTime += pCopyFile->m_pCopyStats->m_bufferReadTime;
pBuffer->dwSize = dwBytesRead;
AddBufferForWrite( pBuffer );
}
return 0;
}
//-----------------------------------------------------------------------------
// WriteFileThread
//
//-----------------------------------------------------------------------------
DWORD WINAPI WriteFileThread( LPVOID lParam )
{
CopyFile_t *pCopyFile;
OVERLAPPED overlappedWrite = {0};
DWORD startTime;
DWORD dwBytesWrite;
DWORD dwWriteSize;
DWORD dwError;
BOOL bResult;
Buffer_t *pBuffer;
unsigned char *pWriteBuffer;
pCopyFile = (CopyFile_t*)lParam;
while ( overlappedWrite.Offset < pCopyFile->m_dstFileSize )
{
// wait for wake-up event
pBuffer = LockBufferForWrite();
if ( pCopyFile->m_bInflate )
{
startTime = GetTickCount();
DWORD dwSkip = overlappedWrite.Offset ? 0 : sizeof( xCompressHeader );
dwWriteSize = JCALG1_Decompress_Formatted_Buffer( pBuffer->dwSize - dwSkip, pBuffer->pData + dwSkip, pCopyFile->m_inflateBufferSize, pCopyFile->m_pInflateBuffer );
if ( dwWriteSize == (DWORD)-1 )
{
pCopyFile->m_bCopyError = true;
break;
}
pCopyFile->m_pCopyStats->m_inflateSize = dwWriteSize;
pCopyFile->m_pCopyStats->m_inflateTime = GetTickCount() - startTime;
pWriteBuffer = pCopyFile->m_pInflateBuffer;
}
else
{
// straight copy
dwWriteSize = pBuffer->dwSize;
pWriteBuffer = pBuffer->pData;
}
if ( overlappedWrite.Offset + dwWriteSize >= pCopyFile->m_dstFileSize )
{
// last buffer, ensure all data is written
dwWriteSize = ALIGN( dwWriteSize, 512 );
}
startTime = GetTickCount();
dwBytesWrite = 0;
int numAttempts = 0;
retry:
// write file to HDD
bResult = WriteFile( pCopyFile->m_hDstFile, pWriteBuffer, (dwWriteSize/512) * 512, NULL, &overlappedWrite );
dwError = GetLastError();
if ( !bResult && dwError != ERROR_IO_PENDING )
{
numAttempts++;
if ( numAttempts == 3 )
{
// error
pCopyFile->m_bCopyError = true;
break;
}
else
{
goto retry;
}
}
else
{
// Wait for the operation to finish
GetOverlappedResult( pCopyFile->m_hDstFile, &overlappedWrite, &dwBytesWrite, TRUE );
overlappedWrite.Offset += dwBytesWrite;
}
if ( dwBytesWrite )
{
// track expected size
pCopyFile->m_pCopyStats->m_bytesCopied += dwBytesWrite;
pCopyFile->m_pCopyStats->m_writeSize += dwBytesWrite;
}
else
{
pCopyFile->m_bCopyError = true;
break;
}
pCopyFile->m_pCopyStats->m_bufferWriteSize = dwBytesWrite;
pCopyFile->m_pCopyStats->m_bufferWriteTime = GetTickCount() - startTime;
pCopyFile->m_pCopyStats->m_totalWriteSize += pCopyFile->m_pCopyStats->m_bufferWriteSize;
pCopyFile->m_pCopyStats->m_totalWriteTime += pCopyFile->m_pCopyStats->m_bufferWriteTime;
AddBufferForRead( pBuffer );
}
return 0;
}
//-----------------------------------------------------------------------------
// CopyFileInit
//
//-----------------------------------------------------------------------------
void CopyFileInit()
{
static bool init = false;
if ( !init )
{
InitializeCriticalSection( &g_criticalSection );
g_hReadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
g_hWriteEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
init = true;
}
else
{
// expected startup state
ResetEvent( g_hReadEvent );
ResetEvent( g_hWriteEvent );
g_pReadBuffers = NULL;
g_pWriteBuffers = NULL;
}
}
//-----------------------------------------------------------------------------
// CopyFileOverlapped
//
//-----------------------------------------------------------------------------
bool CopyFileOverlapped( const char *pSrcFilename, const char *pDstFilename, xCompressHeader *pxcHeader, CopyStats_t *pCopyStats )
{
CopyFile_t copyFile = {0};
Buffer_t buffers[NUM_BUFFERS] = {0};
HANDLE hReadThread = NULL;
HANDLE hWriteThread = NULL;
bool bSuccess = false;
DWORD startCopyTime;
DWORD dwResult;
int i;
startCopyTime = GetTickCount();
CopyFileInit();
g_pNumReadBuffers = &pCopyStats->m_numReadBuffers;
g_pNumWriteBuffers = &pCopyStats->m_numWriteBuffers;
strcpy( pCopyStats->m_srcFilename, pSrcFilename );
strcpy( pCopyStats->m_dstFilename, pDstFilename );
copyFile.m_hSrcFile = INVALID_HANDLE_VALUE;
copyFile.m_hDstFile = INVALID_HANDLE_VALUE;
copyFile.m_pCopyStats = pCopyStats;
copyFile.m_bCopyError = false;
// validate the source file
copyFile.m_hSrcFile = CreateFile( pSrcFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING, NULL );
if ( copyFile.m_hSrcFile == INVALID_HANDLE_VALUE )
{
// failure
goto cleanUp;
}
copyFile.m_srcFileSize = GetFileSize( copyFile.m_hSrcFile, NULL );
if ( copyFile.m_srcFileSize == (DWORD)-1 )
{
// failure
goto cleanUp;
}
// ensure the target file path exists
CreateFilePath( pDstFilename );
// validate the target file
copyFile.m_hDstFile = CreateFile( pDstFilename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING, NULL );
if ( copyFile.m_hDstFile == INVALID_HANDLE_VALUE )
{
// failure
goto cleanUp;
}
pCopyStats->m_readSize = copyFile.m_srcFileSize;
pCopyStats->m_writeSize = 0;
if ( pxcHeader )
{
// read in chunks of compressed blocks
copyFile.m_readBufferSize = pxcHeader->nReadBlockSize;
copyFile.m_dstFileSize = pxcHeader->nUncompressedFileSize;
}
else
{
// setup for copy
copyFile.m_readBufferSize = BUFFER_SIZE;
copyFile.m_dstFileSize = copyFile.m_srcFileSize;
}
// setup read buffers
for ( i=0; i<NUM_BUFFERS; i++)
{
buffers[i].pData = new unsigned char[copyFile.m_readBufferSize];
buffers[i].dwSize = 0;
buffers[i].pNext = NULL;
AddBufferForRead( &buffers[i] );
}
copyFile.m_numReadCycles = (copyFile.m_srcFileSize + copyFile.m_readBufferSize - 1)/copyFile.m_readBufferSize;
// setup write buffer
if ( pxcHeader )
{
copyFile.m_pInflateBuffer = new unsigned char[pxcHeader->nDecompressionBufferSize];
copyFile.m_inflateBufferSize = pxcHeader->nDecompressionBufferSize;
copyFile.m_bInflate = true;
}
else
{
copyFile.m_bInflate = false;
}
// pre-size the target file in aligned buffers
DWORD dwAligned = ALIGN( copyFile.m_dstFileSize, 512 );
dwResult = SetFilePointer( copyFile.m_hDstFile, dwAligned, NULL, FILE_BEGIN );
if ( dwResult == INVALID_SET_FILE_POINTER )
{
// failure
goto cleanUp;
}
SetEndOfFile( copyFile.m_hDstFile );
// start the read thread
hReadThread = CreateThread( 0, 0, &ReadFileThread, &copyFile, 0, 0 );
if ( !hReadThread )
{
// failure
goto cleanUp;
}
// wait for buffers to populate
// start the write thread
hWriteThread = CreateThread( 0, 0, &WriteFileThread, &copyFile, 0, 0 );
if ( !hWriteThread )
{
// failure
goto cleanUp;
}
// wait for write thread to finish
WaitForSingleObject( hWriteThread, INFINITE );
WaitForSingleObject( hReadThread, INFINITE );
if ( copyFile.m_bCopyError )
{
goto cleanUp;
}
// Fixup the file size
CloseHandle( copyFile.m_hDstFile );
copyFile.m_hDstFile = INVALID_HANDLE_VALUE;
if ( copyFile.m_dstFileSize % 512 )
{
// re-open file as non-buffered to adjust to correct file size
HANDLE hFile = CreateFile( pDstFilename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
SetFilePointer( hFile, copyFile.m_dstFileSize, NULL, FILE_BEGIN );
SetEndOfFile( hFile );
CloseHandle( hFile );
}
// finished
bSuccess = true;
cleanUp:
if ( copyFile.m_hSrcFile != INVALID_HANDLE_VALUE )
{
CloseHandle( copyFile.m_hSrcFile );
}
if ( copyFile.m_hDstFile != INVALID_HANDLE_VALUE )
{
CloseHandle( copyFile.m_hDstFile );
}
if ( hReadThread )
{
CloseHandle( hReadThread );
}
if ( hWriteThread )
{
CloseHandle( hWriteThread );
}
for ( i=0; i<NUM_BUFFERS; i++ )
{
if ( buffers[i].pData )
{
delete [] buffers[i].pData;
}
}
if ( copyFile.m_pInflateBuffer )
{
delete [] copyFile.m_pInflateBuffer;
}
if ( !bSuccess )
{
pCopyStats->m_copyErrors++;
}
pCopyStats->m_copyTime = GetTickCount() - startCopyTime;
return bSuccess;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,171 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// XBOX_LOADER.H
//
// Master Include
//=====================================================================================//
#pragma once
#include <xtl.h>
#include <XBApp.h>
#include <XBFont.h>
#include <XBHelp.h>
#include <xgraphics.h>
#include <xfont.h>
#include <xmv.h>
#include <xbdm.h>
#include <math.h>
#include "XBResource.h"
#include "xmvhelper.h"
#include "toollib.h"
#include "scriplib.h"
#include "loader.h"
#include "jcalg1.h"
#include "xbox/xbox_launch.h"
#define XBOX_FORENSIC_LOG
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define MAX_FILES 500
#define MAX_SLIDESHOW_TEXTURES 9
#define LEGAL_DISPLAY_TIME 6000
#define LOADINGBAR_UPTIME 500.0f // slid up or down
#define LOADINGBAR_SLIDETIME 1500.0f // progress speed
#define LOADINGBAR_WAITTIME 500.0f // delay after up to begin slide
#define SLIDESHOW_SLIDETIME 7000
#define SLIDESHOW_FLIPTIME 1000
#define LEGAL_MAIN 0
#define LEGAL_SOURCE 1
#define FOOTER_W 512
#define SEGMENT_W 10
#define SEGMENT_GAP 1
#define SEGMENT_COUNT 26
#define PROGRESS_Y 405
#define PROGRESS_W (SEGMENT_COUNT*(SEGMENT_W+SEGMENT_GAP))
#define PROGRESS_H 15
#define PROGRESS_X 124
#define PROGRESS_FOOTER_COLOR 0x88FFFFFF
#define PROGRESS_INSET_COLOR 0xFF222222
#define PROGRESS_SEGMENT_COLOR 0xFFCC6C00
#define PROGRESS_TEXT_COLOR 0xFFFFFFFF
//-----------------------------------------------------------------------------
// Main class to run this application. Most functionality is inherited
// from the CXBApplication base class.
//-----------------------------------------------------------------------------
class CXBoxLoader : public CXBApplication
{
public:
CXBoxLoader();
virtual HRESULT Initialize( void );
virtual HRESULT Render( void );
virtual HRESULT FrameMove( void );
void DrawRect( int x, int y, int w, int h, DWORD color );
void DrawLegals();
void DrawDebug();
BOOL PlayVideoFrame();
HRESULT StartVideo( const CHAR* strFilename, bool bFromMemory, bool bFatalOnError );
void StopVideo();
bool StartInstall( void );
bool LoadInstallScript( void );
D3DTexture *LoadTexture( int resourceID );
HRESULT LoadFont( CXBFont *pFont, int resourceID );
void DrawTexture( D3DTexture *pD3DTexture, int x, int y, int w, int h, int color );
void StartLegalScreen( int legal );
void DrawProgressBar();
void DrawLoadingMarquee();
void DrawSlideshow();
bool VerifyInstall();
void StartDashboard( bool bGotoMemory );
void LoadLogFile();
void DrawLog();
void FatalMediaError();
void LaunchHL2( unsigned int contextCode );
void TickVideo();
private:
IDirect3DTexture8 *m_pLastMovieFrame;
D3DTexture *m_pFooterTexture;
D3DTexture *m_pLoadingIconTexture;
D3DTexture *m_pMainLegalTexture;
D3DTexture *m_pSourceLegalTexture;
D3DTexture *m_pLegalTexture;
D3DTexture *m_pSlideShowTextures[MAX_SLIDESHOW_TEXTURES];
CXMVPlayer m_player;
D3DVertexBuffer *m_pVB;
CXBPackedResource m_xprResource;
CXBFont m_Font;
int m_contextCode;
char *m_fileSrc[MAX_FILES];
char *m_fileDest[MAX_FILES];
xCompressHeader *m_fileCompressionHeaders[MAX_FILES];
DWORD m_fileDestSizes[MAX_FILES];
int m_numFiles;
bool m_bAllowAttractAbort;
bool m_bDrawLoading;
bool m_bDrawProgress;
bool m_bDrawDebug;
bool m_bLaunch;
DWORD m_dwLoading;
bool m_bDrawLegal;
HANDLE m_installThread;
DWORD m_LegalTime;
int m_State;
DWORD m_LoadingBarStartTime;
DWORD m_LoadingBarEndTime;
DWORD m_LegalStartTime;
bool m_bInstallComplete;
int m_Version;
int m_FrameCounter;
int m_MovieCount;
bool m_bMovieErrorIsFatal;
bool m_bCaptureLastMovieFrame;
DWORD m_SlideShowStartTime;
bool m_bDrawSlideShow;
int m_SlideShowCount;
bool m_bFinalSlide;
char *m_pLogData;
XFONT* m_pDefaultTrueTypeFont;
};
struct CopyStats_t
{
char m_srcFilename[MAX_PATH];
char m_dstFilename[MAX_PATH];
DWORD m_readSize;
DWORD m_writeSize;
DWORD m_bytesCopied;
DWORD m_totalReadTime;
DWORD m_totalWriteTime;
DWORD m_totalReadSize;
DWORD m_totalWriteSize;
DWORD m_bufferReadSize;
DWORD m_bufferWriteSize;
DWORD m_bufferReadTime;
DWORD m_bufferWriteTime;
DWORD m_inflateSize;
DWORD m_inflateTime;
DWORD m_copyTime;
DWORD m_copyErrors;
DWORD m_numReadBuffers;
DWORD m_numWriteBuffers;
};
extern bool CopyFileOverlapped( const char *pSrc, const char *pDest, xCompressHeader *pxcHeader, CopyStats_t *pCopyStats );
extern bool CreateFilePath( const char *inPath );

View File

@@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xbox_loader", "xbox_loader.vcproj", "{652C7D60-BC02-4E09-96DD-9300FFFF3403}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug_XBox = Debug_XBox
Release_XBox = Release_XBox
Retail_XBox = Retail_XBox
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{652C7D60-BC02-4E09-96DD-9300FFFF3403}.Debug_XBox.ActiveCfg = Debug_XBox|Xbox
{652C7D60-BC02-4E09-96DD-9300FFFF3403}.Debug_XBox.Build.0 = Debug_XBox|Xbox
{652C7D60-BC02-4E09-96DD-9300FFFF3403}.Release_XBox.ActiveCfg = Release_XBox|Xbox
{652C7D60-BC02-4E09-96DD-9300FFFF3403}.Release_XBox.Build.0 = Release_XBox|Xbox
{652C7D60-BC02-4E09-96DD-9300FFFF3403}.Retail_XBox.ActiveCfg = Retail_XBox|Xbox
{652C7D60-BC02-4E09-96DD-9300FFFF3403}.Retail_XBox.Build.0 = Retail_XBox|Xbox
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,366 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="xbox_loader"
ProjectGUID="{652C7D60-BC02-4E09-96DD-9300FFFF3403}"
RootNamespace="xbox_loader"
SccProjectName=""
SccLocalPath="">
<Platforms>
<Platform
Name="Xbox"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug_XBox|Xbox"
OutputDirectory=".\Debug_XBox"
IntermediateDirectory=".\Debug_XBox"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
OptimizeForProcessor="2"
AdditionalIncludeDirectories="..\..\..\public;..\..\..\common;..\Common\include;..\toollib"
PreprocessorDefinitions="_USE_XGMATH,_XBOX,XBOX_SAMPLE,_DEBUG,"
ExceptionHandling="FALSE"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="0"
PrecompiledHeaderThrough="xtl.h"
PrecompiledHeaderFile="$(IntDir)/apploader.pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"
CompileAs="0"
DisableSpecificWarnings="4244"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386 /FIXED:NO"
AdditionalDependencies="xperf.lib xbdm.lib xapilibd.lib d3d8d.lib d3dx8d.lib xmv.lib xgraphicsd.lib dsoundd.lib xboxkrnl.lib"
OutputFile="$(OutDir)/xbox_loader.exe"
LinkIncremental="2"
SuppressStartupBanner="TRUE"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/xbox_loader.pdb"
GenerateMapFile="TRUE"/>
<Tool
Name="VCPostBuildEventTool"
Description="Copying LoaderMedia to \\Fileserver"
CommandLine="copy LoaderMedia\*.* \\FileServer\user\XBox\DVD\LoaderMedia
"/>
<Tool
Name="VCPreBuildEventTool"
CommandLine="bundler LoaderMedia_Source\loader_icon.rdf -o LoaderMedia_Source\loader_icon.xbx"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="XboxDeploymentTool"
RemotePath="xe:\hl2\default.xbe"
AdditionalFiles=""/>
<Tool
Name="XboxImageTool"
StackSize="0x10000"
IncludeDebugInfo="TRUE"
LimitAvailableMemoryTo64MB="TRUE"
SuppressStartupBanner="TRUE"
NoLibWarn="TRUE"
TitleID="0x45410091"
TitleName="Half - Life 2 (Debug Build)"
TitleImage="LoaderMedia_Source\loader_icon.xbx"
XBEVersion="4096"/>
</Configuration>
<Configuration
Name="Release_XBox|Xbox"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCLCompilerTool"
OmitFramePointers="TRUE"
OptimizeForProcessor="2"
AdditionalIncludeDirectories="..\..\..\public;..\..\..\common;..\Common\include;..\toollib"
PreprocessorDefinitions="_USE_XGMATH;_XBOX;NDEBUG"
StringPooling="TRUE"
ExceptionHandling="FALSE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="0"
PrecompiledHeaderThrough=""
PrecompiledHeaderFile=""
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DisableSpecificWarnings="4244"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386 /FIXED:NO"
AdditionalDependencies="xapilib.lib d3d8.lib d3dx8.lib xgraphics.lib dsound.lib xmv.lib xboxkrnl.lib"
OutputFile="$(OutDir)/xbox_loader.exe"
SuppressStartupBanner="TRUE"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/xbox_loader.pdb"
GenerateMapFile="TRUE"
MapExports="TRUE"
MapLines="TRUE"
OptimizeReferences="2"
EnableCOMDATFolding="2"
SetChecksum="TRUE"/>
<Tool
Name="VCPostBuildEventTool"
Description="Copying LoaderMedia to \\Fileserver"
CommandLine="copy LoaderMedia\*.* \\FileServer\user\XBox\DVD\LoaderMedia
copy $(TargetDir)$(TargetName).xbe \\FileServer\user\XBox\DVD\default.xbe
"/>
<Tool
Name="VCPreBuildEventTool"
CommandLine="bundler LoaderMedia_Source\loader_icon.rdf -o LoaderMedia_Source\loader_icon.xbx"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="XboxDeploymentTool"
RemotePath="xe:\hl2\default.xbe"
AdditionalFiles=""/>
<Tool
Name="XboxImageTool"
StackSize="0x10000"
LimitAvailableMemoryTo64MB="TRUE"
SuppressStartupBanner="TRUE"
TitleID="0x45410091"
TitleName="Half - Life 2 (Release Build)"
TitleImage="LoaderMedia_Source\loader_icon.xbx"
XBEVersion="4096"/>
</Configuration>
<Configuration
Name="Retail_XBox|Xbox"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCLCompilerTool"
OmitFramePointers="TRUE"
OptimizeForProcessor="2"
AdditionalIncludeDirectories="..\..\..\public;..\..\..\common;..\Common\include;..\toollib"
PreprocessorDefinitions="_USE_XGMATH;_XBOX;NDEBUG;_RETAIL"
StringPooling="TRUE"
ExceptionHandling="FALSE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="0"
PrecompiledHeaderThrough="xtl.h"
PrecompiledHeaderFile="$(IntDir)/apploader.pch"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DisableSpecificWarnings="4244"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386 /FIXED:NO"
AdditionalDependencies="xapilib.lib d3d8.lib d3dx8.lib xgraphics.lib dsound.lib xmv.lib xboxkrnl.lib"
OutputFile="$(OutDir)/xbox_loader.exe"
SuppressStartupBanner="TRUE"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/xbox_loader.pdb"
GenerateMapFile="TRUE"
MapExports="TRUE"
MapLines="TRUE"
OptimizeReferences="2"
EnableCOMDATFolding="2"
SetChecksum="TRUE"/>
<Tool
Name="VCPostBuildEventTool"
Description="Copying LoaderMedia to \\Fileserver"
CommandLine="copy LoaderMedia\*.* \\FileServer\user\XBox\DVD\LoaderMedia
copy $(TargetDir)$(TargetName).xbe \\FileServer\user\XBox\DVD\default.xbe
"/>
<Tool
Name="VCPreBuildEventTool"
CommandLine="bundler LoaderMedia_Source\loader_icon.rdf -o LoaderMedia_Source\loader_icon.xbx"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="XboxDeploymentTool"
RemotePath="xe:\hl2\default.xbe"
AdditionalFiles=""/>
<Tool
Name="XboxImageTool"
StackSize="0x10000"
LimitAvailableMemoryTo64MB="TRUE"
SuppressStartupBanner="TRUE"
TitleID="0x45410091"
TitleName="Half - Life 2"
TitleImage="LoaderMedia_Source\loader_icon.xbx"
XBEVersion="4096"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath=".\xbox_fileCopy.cpp">
</File>
<File
RelativePath=".\xbox_loader.cpp">
</File>
<File
RelativePath=".\xmvhelper.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc">
<File
RelativePath=".\font.h">
</File>
<File
RelativePath="..\..\..\public\jcalg1.h">
</File>
<File
RelativePath=".\loader.h">
</File>
<File
RelativePath="..\..\..\common\xbox\xbox_launch.h">
</File>
<File
RelativePath=".\xbox_loader.h">
</File>
<File
RelativePath=".\xmvhelper.h">
</File>
</Filter>
<Filter
Name="Common Files"
Filter="">
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath="..\toollib\scriplib.cpp">
</File>
<File
RelativePath="..\toollib\scriplib.h">
</File>
<File
RelativePath="..\toollib\toollib.cpp">
</File>
<File
RelativePath="..\toollib\toollib.h">
</File>
<File
RelativePath="..\Common\src\XBApp.cpp">
</File>
<File
RelativePath="..\Common\src\XBFont.cpp">
</File>
<File
RelativePath="..\Common\src\XBInput.cpp">
</File>
<File
RelativePath="..\Common\src\XBMesh.cpp">
</File>
<File
RelativePath="..\Common\src\XBResource.cpp">
</File>
<File
RelativePath="..\Common\src\XBUtil.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc">
<File
RelativePath="..\Common\include\XBApp.h">
</File>
<File
RelativePath="..\Common\include\XBFont.h">
</File>
<File
RelativePath="..\Common\include\XBHelp.h">
</File>
<File
RelativePath="..\Common\include\XBInput.h">
</File>
<File
RelativePath="..\Common\include\XBMesh.h">
</File>
<File
RelativePath="..\Common\include\XBProfiling.h">
</File>
<File
RelativePath="..\Common\include\XBResource.h">
</File>
<File
RelativePath="..\Common\include\XBUtil.h">
</File>
</Filter>
</Filter>
<Filter
Name="Resources"
Filter="*.rdf">
<File
RelativePath=".\loader.rdf">
<FileConfiguration
Name="Debug_XBox|Xbox">
<Tool
Name="VCCustomBuildTool"
Description="bundler &quot;$(InputPath)&quot;"
CommandLine="bundler &quot;$(InputPath)&quot;"
Outputs="$(ProjectDir)Media\$(InputName).xpr;$(ProjectDir)$(InputName).h"/>
</FileConfiguration>
<FileConfiguration
Name="Release_XBox|Xbox">
<Tool
Name="VCCustomBuildTool"
Description="bundler &quot;$(InputPath)&quot;"
CommandLine="bundler &quot;$(InputPath)&quot;"
Outputs="$(ProjectDir)Media\$(InputName).xpr;$(ProjectDir)$(InputName).h"/>
</FileConfiguration>
<FileConfiguration
Name="Retail_XBox|Xbox">
<Tool
Name="VCCustomBuildTool"
Description="bundler &quot;$(InputPath)&quot;"
CommandLine="bundler &quot;$(InputPath)&quot;"
Outputs="$(ProjectDir)Media\$(InputName).xpr;$(ProjectDir)$(InputName).h"/>
</FileConfiguration>
</File>
<File
RelativePath=".\LoaderMedia_Source\loader_icon.rdf">
</File>
</Filter>
<Filter
Name="Libraries"
Filter="">
<File
RelativePath="..\..\..\lib\public\jcalg1_static.lib">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,788 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//-----------------------------------------------------------------------------
// File: WMVPlayer.cpp
//
// Desc: This helper class provides simple WMV decoding and playback
// functionality. It will be expanded as new playback methods are
// exposed
//
// Hist: 2.7.03 - Created, based on work by Jeff Sullivan
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include "xbox_loader.h"
#include <xtl.h>
#include "XMVHelper.h"
#include "XBUtil.h"
#include <stdio.h>
// Funtion Prototypes for packet loading functions for loading from a file.
HRESULT CALLBACK GetNextPacket( DWORD dwContext,
void **ppPacket,
DWORD* pOffsetToNextPacket );
HRESULT CALLBACK ReleasePreviousPacket( DWORD dwContext,
LONGLONG llNextReadByteOffset,
DWORD dwNextPacketSize );
// Funtion Prototypes for packet loading functions for loading from a block of memory.
HRESULT CALLBACK GetNextMemoryPacket( DWORD dwContext,
void **ppPacket,
DWORD* pOffsetToNextPacket );
HRESULT CALLBACK ReleasePreviousMemoryPacket( DWORD dwContext,
LONGLONG llNextReadByteOffset,
DWORD dwNextPacketSize );
//-----------------------------------------------------------------------------
// Name: CXMVPlayer()
// Desc: Constructor for CXMVPlayer
//-----------------------------------------------------------------------------
CXMVPlayer::CXMVPlayer()
{
m_pXMVDecoder = NULL;
ZeroMemory( &m_VideoDesc, sizeof( m_VideoDesc ) );
ZeroMemory( &m_AudioDesc, sizeof( m_AudioDesc ) );
for ( UINT i=0; i<XMVPLAYER_NUMTEXTURES; i++ )
{
m_pTextures[i] = NULL;
}
m_dwCurrentFrame = -1; // Will be zero after we decode the first frame.
m_bPlaying = FALSE;
m_bOverlaysEnabled = FALSE;
m_loadContext.hFile = INVALID_HANDLE_VALUE;
m_loadContext.pInputBuffer = 0;
m_physicalBuffer = 0;
m_bError = FALSE;
}
//-----------------------------------------------------------------------------
// Name: ~CXMVPlayer()
// Desc: Destructor for CXMVPlayer
//-----------------------------------------------------------------------------
CXMVPlayer::~CXMVPlayer()
{
Destroy();
}
//-----------------------------------------------------------------------------
// Name: Destroy()
// Desc: Free all resources and clear are resource pointers and handles.
//-----------------------------------------------------------------------------
HRESULT CXMVPlayer::Destroy()
{
// Disable overlays if we were using them.
if ( m_bOverlaysEnabled )
{
m_pDevice->EnableOverlay( FALSE );
m_bOverlaysEnabled = FALSE;
}
// Free the XMV decoder.
if ( NULL != m_pXMVDecoder )
{
m_pXMVDecoder->CloseDecoder();
m_pXMVDecoder = NULL;
}
ZeroMemory( &m_VideoDesc, sizeof( m_VideoDesc ) );
ZeroMemory( &m_AudioDesc, sizeof( m_AudioDesc ) );
// Release our textures.
for ( UINT i=0; i<XMVPLAYER_NUMTEXTURES; i++ )
{
if ( m_pTextures[i] )
m_pTextures[i]->Release();
m_pTextures[i] = 0;
}
m_dwCurrentFrame = -1;
m_dwStartTime = 0;
m_bPlaying = FALSE;
// Release any file handles we were using.
if( INVALID_HANDLE_VALUE != m_loadContext.hFile )
{
CloseHandle( m_loadContext.hFile );
m_loadContext.hFile = INVALID_HANDLE_VALUE;
}
// Free up memory used for playing a movie from memory.
if ( m_loadContext.pInputBuffer )
{
free( m_loadContext.pInputBuffer );
m_loadContext.pInputBuffer = 0;
}
// Be sure to release the physical memory last!
if( m_physicalBuffer )
{
XPhysicalFree( m_physicalBuffer );
m_physicalBuffer = 0;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FinishOpeningFile()
// Desc: Helper function for the three Open functions. Enables the audio streams,
// initializes the video descriptor, and allocates textures if needed.
//-----------------------------------------------------------------------------
HRESULT CXMVPlayer::FinishOpeningFile( D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures )
{
assert( format == D3DFMT_YUY2 || format == D3DFMT_LIN_A8R8G8B8 );
assert( XMVPLAYER_NUMTEXTURES >= 2);
HRESULT hr = S_OK;
m_pXMVDecoder->GetVideoDescriptor( &m_VideoDesc );
// Enable the audio streams
for ( unsigned i=0; i < m_VideoDesc.AudioStreamCount; i++ )
{
m_pXMVDecoder->GetAudioDescriptor( i, &m_AudioDesc );
hr = m_pXMVDecoder->EnableAudioStream( i, 0, NULL, NULL);
if ( FAILED( hr ) )
{
XBUtil_DebugPrint( "Unable to enable audio stream 0 (error %x)\n", hr );
Destroy();
return hr;
}
}
for ( int i = 0; i < XMVPLAYER_NUMTEXTURES; i++ )
{
m_pTextures[i] = 0;
if ( bAllocateTextures )
{
hr = pDevice->CreateTexture( m_VideoDesc.Width, m_VideoDesc.Height, 1, 0, format, 0, &m_pTextures[i] );
if ( FAILED( hr ) )
{
XBUtil_DebugPrint( "Unable to create texture %d (error %x)\n", i, hr );
Destroy();
return hr;
}
}
}
// Initialize what texture we are decoding to, if decoding for texture mapping.
m_nDecodeTextureIndex = 0;
// Initialize the various texture pointers for use when decoding for overlays.
pShowingTexture = m_pTextures[0];
pDecodingTexture = m_pTextures[1];
pSubmittedTexture = 0;
m_bPlaying = TRUE;
m_dwStartTime = GetTickCount();
return hr;
}
//-----------------------------------------------------------------------------
// Name: OpenFile()
// Desc: Create an XMV decoder object that reads from a file.
//-----------------------------------------------------------------------------
HRESULT CXMVPlayer::OpenFile( const CHAR* lpFilename, D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures )
{
HRESULT hr = S_OK;
m_bError = FALSE;
if ( NULL == lpFilename || NULL == pDevice )
{
XBUtil_DebugPrint( "Bad parameter to OpenFile()\n" );
m_bError = TRUE;
return E_FAIL;
}
hr = XMVDecoder_CreateDecoderForFile( XMVFLAG_SYNC_ON_NEXT_VBLANK, ( CHAR* )lpFilename, &m_pXMVDecoder );
if ( FAILED( hr ) )
{
XBUtil_DebugPrint( "Unable to create XMV Decoder for %s (error: %x)\n", lpFilename, hr );
m_bError = TRUE;
return hr;
}
hr = FinishOpeningFile( format, pDevice, bAllocateTextures );
if ( FAILED( hr ) )
{
m_bError = TRUE;
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: OpenFileForPackets()
// Desc: Create an XMV decoder object that uses the packet reading interface.
// Currently this just reads from a file, but it can be altered to read from
// custom formats, start partway through a file, etc.
//-----------------------------------------------------------------------------
HRESULT CXMVPlayer::OpenFileForPackets( const CHAR* lpFilename, D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures )
{
HRESULT hr = S_OK;
// We need to read in the first 4K of data for the XMV player to initialize
// itself from. This is most conveniently read as an array of DWORDS.
DWORD first4Kbytes[4096 / sizeof( DWORD )];
// Clear entire context struct to zero
ZeroMemory( &m_loadContext, sizeof( m_loadContext ) );
// Open the input file.
m_loadContext.hFile = CreateFile( lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL );
if( m_loadContext.hFile == INVALID_HANDLE_VALUE )
{
Destroy();
return E_INVALIDARG;
}
// Read the first page from the file. We opened it for
// overlapped IO so we do a pair of reads.
m_loadContext.Overlapped.Offset = 0;
m_loadContext.Overlapped.OffsetHigh = 0;
// Start the read.
if( 0 == ReadFile( m_loadContext.hFile, first4Kbytes, sizeof( first4Kbytes ), NULL, &m_loadContext.Overlapped ) )
{
if( GetLastError() != ERROR_IO_PENDING )
{
Destroy();
return E_FAIL;
}
}
// Wait for the read to finish.
DWORD dwBytesRead;
if( !GetOverlappedResult( m_loadContext.hFile, &m_loadContext.Overlapped, &dwBytesRead, TRUE ) )
{
Destroy();
return E_FAIL;
}
// Check size to make sure input is a valid XMV file.
if( dwBytesRead != 4096 )
{
Destroy();
return E_FAIL;
}
// Create an XMV decoder
hr = XMVDecoder_CreateDecoderForPackets( XMVFLAG_SYNC_ON_NEXT_VBLANK, first4Kbytes, ( DWORD )&m_loadContext,
GetNextPacket, ReleasePreviousPacket, &m_pXMVDecoder );
if( FAILED( hr ) )
{
Destroy();
return E_FAIL;
}
// The size of the first packet and the minimum size of the two packet buffers are stored in the
// second and third DWORDS of the file. From xmv.h:
// * DWORD NextPacketSize // The size of the next packet
// * DWORD ThisPacketSize // The size of this packet
// * DWORD MaxPacketSize // The size of the largest packet in the file
DWORD dwThisPacketSize = first4Kbytes[1];
DWORD dwRequiredPacketSize = first4Kbytes[2];
// Check for illegal parameters.
if( dwThisPacketSize > dwRequiredPacketSize )
{
Destroy();
return E_FAIL;
}
// XPhysicalAlloc is used so that 5.1 or compressed audio streams can be played.
m_physicalBuffer = ( BYTE* )XPhysicalAlloc( dwRequiredPacketSize * 2, MAXULONG_PTR, 0, PAGE_READWRITE );
// Save our information.
m_loadContext.dwPacketSize = dwRequiredPacketSize;
m_loadContext.pLoadingPacket = m_physicalBuffer;
m_loadContext.pDecodingPacket = m_physicalBuffer + dwRequiredPacketSize;
// Read the first packet. We wind up re-reading the first 4096
// bytes but it makes the logic for figuring out how much we read
// a little bit easier...
m_loadContext.Overlapped.Offset = 0;
m_loadContext.Overlapped.OffsetHigh = 0;
if( 0 == ReadFile( m_loadContext.hFile, m_physicalBuffer, dwThisPacketSize, NULL,
&m_loadContext.Overlapped ) )
{
if( GetLastError() != ERROR_IO_PENDING )
{
Destroy();
return E_FAIL;
}
}
// Note - at this point the preceding read has *not* necessarily completed.
// Don't try reading anything from that buffer until GetNextPacket has been
// successfully called.
hr = FinishOpeningFile( format, pDevice, bAllocateTextures );
return hr;
}
//-----------------------------------------------------------------------------
// Name: OpenMovieFromMemory()
// Desc: Create an XMV decoder object that uses the packet reading interface to
// read from a block of memory. To simplify the memory management this function
// also allocates this block of memory and initializes it from a file.
//-----------------------------------------------------------------------------
HRESULT CXMVPlayer::OpenMovieFromMemory( const CHAR* lpFilename, D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures )
{
HRESULT hr = S_OK;
m_bError = FALSE;
// Read the entire file into memory.
void* data;
hr = XBUtil_LoadFile( lpFilename, &data, &m_loadContext.inputSize );
if ( FAILED( hr ) )
{
m_bError = TRUE;
return hr;
}
m_loadContext.pInputBuffer = ( BYTE* )data;
// Check size to make sure input is a valid XMV file.
if( m_loadContext.inputSize < 4096 )
{
Destroy();
m_bError = TRUE;
return E_FAIL;
}
// Get a DWORD pointer to the first 4K - needed by CreateDecoderForPackets
DWORD* first4Kbytes = ( DWORD* )data;
// Create an XMV decoder
hr = XMVDecoder_CreateDecoderForPackets( XMVFLAG_SYNC_ON_NEXT_VBLANK, first4Kbytes, ( DWORD )&m_loadContext, GetNextMemoryPacket,
ReleasePreviousMemoryPacket, &m_pXMVDecoder );
if ( FAILED( hr ) )
{
Destroy();
m_bError = TRUE;
return E_FAIL;
}
// The size of the first packet and the minimum size of the two packet buffers are stored in the
// second and third DWORDS of the file. From xmv.h:
// * DWORD NextPacketSize // The size of the next packet
// * DWORD ThisPacketSize // The size of this packet
// * DWORD MaxPacketSize // The size of the largest packet in the file
DWORD dwThisPacketSize = first4Kbytes[1];
DWORD dwRequiredPacketSize = first4Kbytes[2];
// Check for illegal parameters.
if( dwThisPacketSize > dwRequiredPacketSize )
{
Destroy();
m_bError = TRUE;
return E_FAIL;
}
// XPhysicalAlloc is used so that 5.1 or compressed audio streams can be played.
m_physicalBuffer = ( BYTE* )XPhysicalAlloc( dwRequiredPacketSize * 2, MAXULONG_PTR, 0, PAGE_READWRITE );
// Save our information for the callback functions.
// The size of our two memory blocks.
m_loadContext.dwPacketSize = dwRequiredPacketSize;
// The addresses of our two memory blocks.
m_loadContext.pLoadingPacket = m_physicalBuffer;
m_loadContext.pDecodingPacket = m_physicalBuffer + dwRequiredPacketSize;
// Information about the block of memory the movie is stored in.
m_loadContext.pInputBuffer = ( BYTE* )data;
m_loadContext.inputSize = m_loadContext.inputSize;
m_loadContext.readOffset = 0;
m_loadContext.currentPacketSize = dwThisPacketSize;
hr = FinishOpeningFile( format, pDevice, bAllocateTextures );
if ( FAILED( hr ) )
{
m_bError = TRUE;
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: AdvanceFrameForTexturing()
// Desc: Unpack the appropriate frames of data for use as textures.
//-----------------------------------------------------------------------------
LPDIRECT3DTEXTURE8 CXMVPlayer::AdvanceFrameForTexturing( LPDIRECT3DDEVICE8 pDevice )
{
// You must pass bAllocateTextures==TRUE to Open if you're going to use GetTexture/AdvanceFrame.
assert( m_pTextures[0] );
LPDIRECT3DSURFACE8 pSurface;
pDecodingTexture->GetSurfaceLevel( 0, &pSurface );
// Decode some information to the current draw texture.
XMVRESULT xr = XMV_NOFRAME;
m_pXMVDecoder->GetNextFrame( pSurface, &xr, NULL );
switch ( xr )
{
case XMV_NOFRAME:
// Do nothing - we didn't get a frame.
break;
case XMV_NEWFRAME:
++m_dwCurrentFrame;
// GetNextFrame produced a new frame. So, the texture we were decoding
// to becomes available for drawing as a texture.
pShowingTexture = pDecodingTexture;
// Setup for decoding to the next texture.
m_nDecodeTextureIndex = ( m_nDecodeTextureIndex + 1 ) % XMVPLAYER_NUMTEXTURES;
pDecodingTexture = m_pTextures[ m_nDecodeTextureIndex ];
break;
case XMV_ENDOFFILE:
m_bPlaying = FALSE;
break;
case XMV_FAIL:
// Data corruption or file read error. We'll treat that the same as
// end of file.
m_bPlaying = FALSE;
m_bError = TRUE;
break;
}
SAFE_RELEASE( pSurface );
// If we haven't decoded the first frame then return zero.
if ( m_dwCurrentFrame < 0 )
return 0;
return pShowingTexture;
}
//-----------------------------------------------------------------------------
// Name: AdvanceFrameForOverlays()
// Desc: Unpack the appropriate frames of data for use as an overlay.
//-----------------------------------------------------------------------------
LPDIRECT3DTEXTURE8 CXMVPlayer::AdvanceFrameForOverlays( LPDIRECT3DDEVICE8 pDevice )
{
// You must pass bAllocateTextures==TRUE to Open if you're going to use GetTexture/AdvanceFrame.
assert( m_pTextures[0] );
// You have to call CXMVPlayer::EnableOverlays() if you are going to use overlays.
assert( m_bOverlaysEnabled );
// If a texture has been submitted to be used as an overlay then we have to
// wait for GetUpdateOverlayState() to return TRUE before we can assume that
// the previous texture has *stopped* being displayed. Once GetUpdateOverlayState()
// returns TRUE then we know that pSubmittedTexture is being displayed, which
// means that, pShowingTexture is available as a decoding target.
if ( pSubmittedTexture )
{
// If GetOverlayUpdateStatus() returns FALSE then we can still proceed and
// call GetNextFrame(), but we will pass NULL for the surface parameter.
// Some work will still be done, but none of the surfaces will be altered.
if ( pDevice->GetOverlayUpdateStatus() )
{
// The call to UpdateOverlay() with pSubmittedTexture must have taken
// effect now, so pShowingTexture is available as a decoding target.
assert( !pDecodingTexture );
pDecodingTexture = pShowingTexture;
pShowingTexture = pSubmittedTexture;
pSubmittedTexture = NULL;
}
}
LPDIRECT3DSURFACE8 pSurface = NULL;
if ( pDecodingTexture )
pDecodingTexture->GetSurfaceLevel( 0, &pSurface );
// Decode some information to the current draw texture, which may be NULL.
// pDecodingTexture will be NULL if one texture has been submitted as a new
// overlay but the other one is still being displayed as an overlay.
// If pSurface is NULL GetNextFrame() will still do some work.
XMVRESULT xr = XMV_NOFRAME;
m_pXMVDecoder->GetNextFrame( pSurface, &xr, NULL );
switch ( xr )
{
case XMV_NOFRAME:
// Do nothing - we didn't get a frame.
break;
case XMV_NEWFRAME:
++m_dwCurrentFrame;
// GetNextFrame produced a new frame. So, the texture we were decoding
// to becomes available for displaying as an overlay.
// The other texture is not ready to be a decoding target. It is still
// being displayed as an overlay. So, we assign the newly decoded
// texture to pSubmittedTexture for the program to submit as an overlay,
// but we don't yet move the previously submitted texture from pShowing
// to pDecoding. That happens on a subsequent call to this function, after
// GetOverlayUpdateStatus() returns TRUE to tell us that there are no
// overlay swaps pending.
assert( pDecodingTexture );
assert( !pSubmittedTexture );
pSubmittedTexture = pDecodingTexture;
pDecodingTexture = NULL;
break;
case XMV_ENDOFFILE:
m_bPlaying = FALSE;
break;
case XMV_FAIL:
// Data corruption or file read error. We'll treat that the same as
// end of file.
m_bPlaying = FALSE;
m_bError = TRUE;
break;
}
SAFE_RELEASE( pSurface );
// If we just unpacked a new frame then we return that texture
// and the program must call UpdateOverlay() with the surface
// from that texture.
// If we didn't unpack a frame then the program should do nothing -
// the previous overlay will continue to be displayed.
if ( XMV_NEWFRAME == xr )
return pSubmittedTexture;
// No new frame to display.
return 0;
}
//-----------------------------------------------------------------------------
// Name: TerminatePlayback()
// Desc: Calls XMVDecoder::TerminatePlayback()
//-----------------------------------------------------------------------------
void CXMVPlayer::TerminatePlayback()
{
m_pXMVDecoder->TerminatePlayback();
}
//-----------------------------------------------------------------------------
// Name: Play()
// Desc: Calls XMVDecoder::Play() to play the entire movie.
//-----------------------------------------------------------------------------
HRESULT CXMVPlayer::Play( DWORD Flags, RECT* pRect )
{
// You have to call Open before calling Play.
assert( m_pXMVDecoder );
// Don't pass bAllocateTextures==TRUE to Open if you're going to use Play.
assert( !m_pTextures[0] );
return m_pXMVDecoder->Play( Flags, pRect );
}
//-----------------------------------------------------------------------------
// Name: EnableOverlays()
// Desc: Enable the overlay planes for playing the movie in them, and record
// that the overlays should be disabled when Destroy() is called.
//-----------------------------------------------------------------------------
void CXMVPlayer::EnableOverlays( LPDIRECT3DDEVICE8 pDevice )
{
m_pDevice = pDevice;
pDevice->EnableOverlay( TRUE );
m_bOverlaysEnabled = TRUE;
}
//-----------------------------------------------------------------------------
// Name: GetNextPacket()
// Desc: Callback function to get next packet from a file
//-----------------------------------------------------------------------------
static HRESULT CALLBACK GetNextPacket( DWORD dwContext, VOID** ppPacket,
DWORD* pOffsetToNextPacket )
{
LOAD_CONTEXT* pContext = ( LOAD_CONTEXT* )dwContext;
if( NULL == pContext )
return E_FAIL;
// If the next packet is fully loaded then return it,
// otherwise return NULL.
DWORD dwBytesRead;
if( GetOverlappedResult( pContext->hFile, &pContext->Overlapped,
&dwBytesRead, FALSE ) )
{
// Make the old decoding packet pending.
pContext->pPendingReleasePacket = pContext->pDecodingPacket;
pContext->pDecodingPacket = pContext->pLoadingPacket;
pContext->pLoadingPacket = NULL;
// Offset to the next packet.
*pOffsetToNextPacket = dwBytesRead;
// Set *ppPacket to the data we just loaded.
*ppPacket = pContext->pDecodingPacket;
}
else
{
DWORD dwError = GetLastError();
// If we're waiting on the IO to finish, just do nothing.
if( dwError != ERROR_IO_INCOMPLETE )
return HRESULT_FROM_WIN32( dwError );
*ppPacket = NULL;
*pOffsetToNextPacket = 0;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ReleasePreviousPacket()
// Desc: Callback function to release previous packet from a file
//-----------------------------------------------------------------------------
static HRESULT CALLBACK ReleasePreviousPacket( DWORD dwContext, LONGLONG llNextReadByteOffset,
DWORD dwNextPacketSize )
{
LOAD_CONTEXT* pContext = ( LOAD_CONTEXT* )dwContext;
if( NULL == pContext )
return E_FAIL;
if( dwNextPacketSize != 0 )
{
// Start the next load.
pContext->Overlapped.Offset = ( DWORD )( llNextReadByteOffset & 0xFFFFFFFF );
pContext->Overlapped.OffsetHigh = ( DWORD )( llNextReadByteOffset >> 32 );
// Check for bad input file - buffer overrun
if( dwNextPacketSize > pContext->dwPacketSize )
return E_FAIL;
pContext->pLoadingPacket = pContext->pPendingReleasePacket;
pContext->pPendingReleasePacket = NULL;
if( 0 == ReadFile( pContext->hFile, pContext->pLoadingPacket,
dwNextPacketSize, NULL, &pContext->Overlapped ) )
{
if( GetLastError() != ERROR_IO_PENDING )
return HRESULT_FROM_WIN32( GetLastError() );
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: GetNextMemoryPacket()
// Desc: Callback function to get next packet from a file,
// and setup for the next packet.
//-----------------------------------------------------------------------------
static HRESULT CALLBACK GetNextMemoryPacket( DWORD dwContext, VOID** ppPacket,
DWORD* pOffsetToNextPacket )
{
LOAD_CONTEXT* pContext = ( LOAD_CONTEXT* )dwContext;
if( NULL == pContext )
return E_FAIL;
DWORD dwBytesRead = pContext->inputSize - pContext->readOffset;
if ( pContext->currentPacketSize < dwBytesRead )
dwBytesRead = pContext->currentPacketSize;
memcpy( pContext->pLoadingPacket, pContext->pInputBuffer + pContext->readOffset , dwBytesRead );
pContext->readOffset +=dwBytesRead;
// Swap pointers so that next time we load it goes into the other packet block.
BYTE* temp = pContext->pLoadingPacket;
pContext->pLoadingPacket = pContext->pDecodingPacket;
pContext->pDecodingPacket = temp;
// Offset to the next packet.
*pOffsetToNextPacket = dwBytesRead;
// Set *ppPacket to the data we just loaded.
*ppPacket = pContext->pDecodingPacket;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ReleasePreviousMemoryPacket()
// Desc: Callback function to release previous packet from a block of memory,
// and setup for the next packet.
//-----------------------------------------------------------------------------
static HRESULT CALLBACK ReleasePreviousMemoryPacket( DWORD dwContext, LONGLONG llNextReadByteOffset,
DWORD dwNextPacketSize )
{
LOAD_CONTEXT* pContext = ( LOAD_CONTEXT* )dwContext;
if( NULL == pContext )
return E_FAIL;
// Check for bad input file - buffer overrun
if( dwNextPacketSize > pContext->dwPacketSize )
return E_FAIL;
// Record the size of the next packet we are supposed to read, for GetNextMemoryPacket.
pContext->currentPacketSize = dwNextPacketSize;
return S_OK;
}

View File

@@ -0,0 +1,177 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//-----------------------------------------------------------------------------
// File: XMVHelper.h
//
// Desc: Definition of XMV playback helper class for playing XMVs in a number
// of different ways.
//
// Hist: 2.7.03 - Created, based on work by Jeff Sullivan
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#ifndef _XMVHELPER_H_
#define _XMVHELPER_H_
#include <xtl.h>
#include <xmv.h>
// Number of textures to allocate for decoding. A larger number may help to
// smooth out any frame rate variations if you are decoding to a texture.
// When decoding to overlays two textures are always used.
const DWORD XMVPLAYER_NUMTEXTURES = 2;
//-----------------------------------------------------------------------------
// Name: LOAD_CONTEXT
// Desc: This structure is used to hold information used by the packet callbacks.
//-----------------------------------------------------------------------------
struct LOAD_CONTEXT
{
// Memory available for loading packets - maximum packet size.
DWORD dwPacketSize;
// Packet that XMV was decoding out of, and might still be, that
// we want to load into as soon as we can.
BYTE* pPendingReleasePacket;
// Packet that XMV is decoding out of.
BYTE* pDecodingPacket;
// Packet we are currently loading into.
BYTE* pLoadingPacket;
// Information for when reading packets out of a file.
// Handle to the file we are reading from.
HANDLE hFile;
// Overlapped structure to control asynchronous reading.
OVERLAPPED Overlapped;
// Information for when copying packets out of a memory buffer.
// The size and location of the buffer we are reading from if we are
// playing a movie from memory.
BYTE* pInputBuffer;
DWORD inputSize;
// The offset in the memory buffer that we are currently reading from.
DWORD readOffset;
// The size of the packet that we have 'queued up' for reading. This
// is a packet that we have warned about via ReleasePreviousMemoryPacket
// but have not yet been asked to load.
DWORD currentPacketSize;
};
class CXMVPlayer
{
public:
CXMVPlayer();
~CXMVPlayer();
// Open a .wmv file and prepare it for playing.
// The format parameter specifies what type of texture it should be unpacked into ( if allocateTextures
// is TRUE ). Only YUY2, LIN_X8R8G8B8 and LIN_A8R8G8B8 are supported as formats.
// If you plan to play the movie with Play() or otherwise use overlays then format must be D3DFMT_YUY2
// pDevice is needed in order to create textures.
// allocateTextures should be TRUE if you plan to play the movie manually with AdvanceFrame.
// It should be FALSE if you plan to play the movie with Play().
// IsPlaying() will return TRUE if the movie opened successfully.
HRESULT OpenFile( const CHAR* lpFilename, D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures );
// Open a file using the packet interface. This method of opening a .wmv file can be easily
// customized to read the data from game specific file formats. The GetNextPacket and
// ReleasePreviousPacket functions from XMVHelper.cpp are used to read the packets. See above for
// information about the other parameters.
HRESULT OpenFileForPackets( const CHAR* lpFilename, D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures );
// Open a block of memory for playing using the packet interface. This method of opening a .wmv file can be easily
// customized to read the data from game specific file formats, or to retain the block of data in memory.
// The GetNextMemoryPacket and ReleasePreviousMemoryPacket functions from XMVHelper.cpp are used to read
// the packets. See above for information about the other parameters.
HRESULT OpenMovieFromMemory( const CHAR* lpFilename, D3DFORMAT format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures );
// Destroy frees up all the movie resources. IsPlaying() will return FALSE afterwards. Destroy()
// can be called during movie playback, but is not thread safe.
HRESULT Destroy();
// The AdvanceFrame functions move to the next frame if it is time for that. Call this
// function frequently - typically 30-60 times per second.
// AdvanceFrameForTexturing returns the most recent frame decoded, for texturing.
// It will return zero if the first frame has not been decoded, but otherwise
// will always return a texture.
LPDIRECT3DTEXTURE8 AdvanceFrameForTexturing( LPDIRECT3DDEVICE8 pDevice );
// AdvanceFrameForOverlays returns newly decoded frames, for use as an overlays.
// You MUST call UpdateOverlay() with the texture's surface.
// It will return zero if there is not a *new* frame available.
LPDIRECT3DTEXTURE8 AdvanceFrameForOverlays( LPDIRECT3DDEVICE8 pDevice );
// Get information about the movie playing.
DWORD GetWidth() const { return m_VideoDesc.Width; }
DWORD GetHeight() const { return m_VideoDesc.Height; }
DWORD GetCurrentFrame() const { return m_dwCurrentFrame; }
DWORD GetElapsedTime() const { return m_bPlaying ? GetTickCount() - m_dwStartTime : 0; }
// IsPlaying returns TRUE if a movie has been opened but has not ended or been destroyed.
BOOL IsPlaying() const { return m_bPlaying; }
BOOL IsFailed() const { return m_bError; }
// Call TerminatePlayback on the decoder. It may take a few hundred ms before the movie stops.
// This function is thread safe, as long as you ensure that you don't call Destroy() in another
// thread simultaneously.
void TerminatePlayback();
HRESULT Play( DWORD Flags, RECT* pRect );
// Call this to enable overlays if you will be playing the movie in an overlay using
// AdvanceFrame. The overlays will be disabled when Destroy() is called.
void EnableOverlays( LPDIRECT3DDEVICE8 pDevice );
private:
XMVDecoder* m_pXMVDecoder; // Pointer to the XMV decoder object.
XMVVIDEO_DESC m_VideoDesc; // Description of the .xmv files video data.
XMVAUDIO_DESC m_AudioDesc; // Description of the .xmv files audio data.
LPDIRECT3DTEXTURE8 m_pTextures[XMVPLAYER_NUMTEXTURES]; // Textures to cycle through.
DWORD m_nDecodeTextureIndex; // Index of the current texture to decode to.
// These texture pointers are copies of the values in m_pTextures. They are used to track
// the decode/display/pending status.
// When displaying using textures pShowingTexture points to the texture to display,
// pDecodingTexture points to the texture to decode into, and pSubmittedTexture is always
// zero.
// When displaying using overlays pShowingTexture points to the texture that the hardware
// is currently displaying, pDecodingTexture points to the texture to decode into, and
// pSubmittedTexture is a surface that has been submitted to the overlay system, but not
// necessarily displayed yet. At any given time one of these is always zero. When
// pDecodingTexture is zero that means that pShowingTexture might be being displayed, or
// the hardware might have switched to pSubmittedTexture, we don't know yet.
LPDIRECT3DTEXTURE8 pShowingTexture;
LPDIRECT3DTEXTURE8 pDecodingTexture;
LPDIRECT3DTEXTURE8 pSubmittedTexture;
int m_dwCurrentFrame; // Current frame number - minus one if not yet started.
DWORD m_dwStartTime;
BOOL m_bPlaying; // Is a movie currently playing?
BOOL m_bOverlaysEnabled; // Are overlays enabled? For disabling them on destroy.
LPDIRECT3DDEVICE8 m_pDevice; // For use by Destroy to disable overlays.
BOOL m_bError;
LOAD_CONTEXT m_loadContext; // Data for communicating with packet callback functions.
BYTE* m_physicalBuffer; // Pointer to block of physical memory used for loading packets.
// Helper function for opening files.
HRESULT FinishOpeningFile( D3DFORMAT Format, LPDIRECT3DDEVICE8 pDevice, BOOL bAllocateTextures );
// Copy constructor and assignment operator are private and unimplemented
// to prevent unintentional, unsupported, and disastrous copying.
CXMVPlayer( const CXMVPlayer& source );
CXMVPlayer& operator=( const CXMVPlayer& source );
};
#endif //#ifndef _XMVPLAYER_H_