summaryrefslogtreecommitdiff
path: root/utils/xbox/xbox_loader
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xbox/xbox_loader
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/xbox/xbox_loader')
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_english.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_french.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_german.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_italian.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_spanish.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/LoadingIcon.tgabin0 -> 16428 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/SourceScreen.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.abcbin0 -> 5938 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.tgabin0 -> 524306 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/footer.tgabin0 -> 131116 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.bmpbin0 -> 49208 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.rdf7
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_english.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_french.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_german.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_italian.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_spanish.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow2.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow3.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow4.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow5.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow6.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow7.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow8.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/LoaderMedia_Source/slideshow9.tgabin0 -> 921644 bytes
-rw-r--r--utils/xbox/xbox_loader/loader.rdf173
-rw-r--r--utils/xbox/xbox_loader/xbox_fileCopy.cpp595
-rw-r--r--utils/xbox/xbox_loader/xbox_loader.cpp2019
-rw-r--r--utils/xbox/xbox_loader/xbox_loader.h171
-rw-r--r--utils/xbox/xbox_loader/xbox_loader.sln24
-rw-r--r--utils/xbox/xbox_loader/xbox_loader.vcproj366
-rw-r--r--utils/xbox/xbox_loader/xmvhelper.cpp788
-rw-r--r--utils/xbox/xbox_loader/xmvhelper.h177
33 files changed, 4320 insertions, 0 deletions
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_english.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_english.tga
new file mode 100644
index 0000000..5c61f95
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_english.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_french.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_french.tga
new file mode 100644
index 0000000..0116d18
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_french.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_german.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_german.tga
new file mode 100644
index 0000000..629524e
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_german.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_italian.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_italian.tga
new file mode 100644
index 0000000..c37b3a2
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_italian.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_spanish.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_spanish.tga
new file mode 100644
index 0000000..a935072
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/LegalScreen_spanish.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/LoadingIcon.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/LoadingIcon.tga
new file mode 100644
index 0000000..ae2134d
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/LoadingIcon.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/SourceScreen.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/SourceScreen.tga
new file mode 100644
index 0000000..4acd064
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/SourceScreen.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.abc b/utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.abc
new file mode 100644
index 0000000..bcbc925
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.abc
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.tga
new file mode 100644
index 0000000..103fb95
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/Tahoma_16.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/footer.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/footer.tga
new file mode 100644
index 0000000..340f4a5
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/footer.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.bmp b/utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.bmp
new file mode 100644
index 0000000..29e905e
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.bmp
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.rdf b/utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.rdf
new file mode 100644
index 0000000..e31fa3a
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/loader_icon.rdf
@@ -0,0 +1,7 @@
+Texture MyTex
+{
+ Source loader_icon.bmp
+ Format D3DFMT_DXT1
+ Width 128
+ Height 128
+}
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_english.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_english.tga
new file mode 100644
index 0000000..b45b3a1
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_english.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_french.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_french.tga
new file mode 100644
index 0000000..2963e36
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_french.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_german.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_german.tga
new file mode 100644
index 0000000..2636bec
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_german.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_italian.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_italian.tga
new file mode 100644
index 0000000..a09efae
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_italian.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_spanish.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_spanish.tga
new file mode 100644
index 0000000..ade8343
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow1_spanish.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow2.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow2.tga
new file mode 100644
index 0000000..52e952b
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow2.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow3.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow3.tga
new file mode 100644
index 0000000..76b3700
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow3.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow4.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow4.tga
new file mode 100644
index 0000000..1bc591d
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow4.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow5.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow5.tga
new file mode 100644
index 0000000..040a8ac
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow5.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow6.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow6.tga
new file mode 100644
index 0000000..1edbb6e
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow6.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow7.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow7.tga
new file mode 100644
index 0000000..4f47769
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow7.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow8.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow8.tga
new file mode 100644
index 0000000..30dabe8
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow8.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow9.tga b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow9.tga
new file mode 100644
index 0000000..a9cfb82
--- /dev/null
+++ b/utils/xbox/xbox_loader/LoaderMedia_Source/slideshow9.tga
Binary files differ
diff --git a/utils/xbox/xbox_loader/loader.rdf b/utils/xbox/xbox_loader/loader.rdf
new file mode 100644
index 0000000..33e7552
--- /dev/null
+++ b/utils/xbox/xbox_loader/loader.rdf
@@ -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
+}
+
+
+
+
+
+
+
diff --git a/utils/xbox/xbox_loader/xbox_fileCopy.cpp b/utils/xbox/xbox_loader/xbox_fileCopy.cpp
new file mode 100644
index 0000000..39d0c65
--- /dev/null
+++ b/utils/xbox/xbox_loader/xbox_fileCopy.cpp
@@ -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;
+}
diff --git a/utils/xbox/xbox_loader/xbox_loader.cpp b/utils/xbox/xbox_loader/xbox_loader.cpp
new file mode 100644
index 0000000..7cbeb77
--- /dev/null
+++ b/utils/xbox/xbox_loader/xbox_loader.cpp
@@ -0,0 +1,2019 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// APPLOADER.CPP
+//
+// Stub executeable
+//=====================================================================================//
+#include "xbox_loader.h"
+
+struct installData_t
+{
+ char **m_ppSrcFiles;
+ char **m_ppDstFiles;
+ DWORD *m_pDstFileSizes;
+ int m_numFiles;
+ DWORD m_totalSize;
+ xCompressHeader **m_ppxcHeaders;
+};
+
+DWORD g_installStartTime;
+DWORD g_installElapsedTime;
+installData_t g_installData;
+CopyStats_t g_copyStats;
+int g_activeDevice;
+__int64 g_loaderStartTime;
+
+
+//-----------------------------------------------------------------------------
+// GetLocalizedLoadingString
+//-----------------------------------------------------------------------------
+const wchar_t *GetLocalizedLoadingString()
+{
+ switch( XGetLanguage() )
+ {
+ case XC_LANGUAGE_FRENCH:
+ return L"CHARGEMENT...";
+ case XC_LANGUAGE_ITALIAN:
+ return L"CARICAMENTO...";
+ case XC_LANGUAGE_GERMAN:
+ return L"L�DT...";
+ case XC_LANGUAGE_SPANISH:
+ return L"CARGANDO...";
+ }
+ return L"LOADING...";
+}
+
+//-----------------------------------------------------------------------------
+// GetNextLangauge
+// Start at -1
+//-----------------------------------------------------------------------------
+int GetNextLanguage( int languageID )
+{
+ if ( languageID < 0 )
+ return XC_LANGUAGE_ENGLISH;
+
+ // cycle to end
+ switch ( languageID )
+ {
+ case XC_LANGUAGE_ENGLISH:
+ return XC_LANGUAGE_FRENCH;
+ case XC_LANGUAGE_FRENCH:
+ return XC_LANGUAGE_ITALIAN;
+ case XC_LANGUAGE_ITALIAN:
+ return XC_LANGUAGE_GERMAN;
+ case XC_LANGUAGE_GERMAN:
+ return XC_LANGUAGE_SPANISH;
+ case XC_LANGUAGE_SPANISH:
+ return -1;
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// GetLanguageString
+//-----------------------------------------------------------------------------
+const char *GetLanguageString( int languageID )
+{
+ switch( languageID )
+ {
+ case XC_LANGUAGE_FRENCH:
+ return "french";
+ case XC_LANGUAGE_ITALIAN:
+ return "italian";
+ case XC_LANGUAGE_GERMAN:
+ return "german";
+ case XC_LANGUAGE_SPANISH:
+ return "spanish";
+ }
+ return "english";
+}
+
+//-----------------------------------------------------------------------------
+// FixupNamespaceFilename
+//-----------------------------------------------------------------------------
+bool FixupNamespaceFilename( const char *pFilename, char *pOutFilename, int languageID )
+{
+ char newFilename[MAX_PATH];
+
+ bool bFixup = false;
+ int dstLen = 0;
+ int srcLen = strlen( pFilename );
+ for ( int i=0; i<srcLen+1; i++ )
+ {
+ // replace every occurrence of % with language
+ if ( pFilename[i] == '%' )
+ {
+ int len = strlen( GetLanguageString( languageID ) );
+ memcpy( newFilename + dstLen, GetLanguageString( languageID ), len );
+ dstLen += len;
+ bFixup = true;
+ }
+ else
+ {
+ newFilename[dstLen] = pFilename[i];
+ dstLen++;
+ }
+ }
+
+ strcpy( pOutFilename, newFilename );
+ return bFixup;
+}
+
+//-----------------------------------------------------------------------------
+// DeleteOtherLocalizedFiles
+//-----------------------------------------------------------------------------
+void DeleteOtherLocalizedFiles( const char *pFilename, int languageIDToKeep )
+{
+ char newFilename[MAX_PATH];
+ char mrkFilename[MAX_PATH];
+ bool bFixup;
+
+ int languageID = -1;
+ while ( 1 )
+ {
+ languageID = GetNextLanguage( languageID );
+ if ( languageID == -1 )
+ {
+ // cycled through
+ break;
+ }
+
+ if ( languageID == languageIDToKeep )
+ {
+ // skip
+ continue;
+ }
+
+ bFixup = FixupNamespaceFilename( pFilename, newFilename, languageID );
+ if ( !bFixup )
+ {
+ // nothing to do
+ continue;
+ }
+
+ SetFileAttributes( newFilename, FILE_ATTRIBUTE_NORMAL );
+ DeleteFile( newFilename );
+
+ // delete marker
+ strcpy( mrkFilename, newFilename );
+ strcat( mrkFilename, ".mrk" );
+ SetFileAttributes( mrkFilename, FILE_ATTRIBUTE_NORMAL );
+ DeleteFile( mrkFilename );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// LerpColor
+//-----------------------------------------------------------------------------
+unsigned int LerpColor( unsigned int c0, unsigned int c1, float t )
+{
+ int i;
+ float a;
+ float b;
+ unsigned char* c;
+ unsigned int newcolor;
+
+ if ( t <= 0.0f )
+ return c0;
+ else if ( t >= 1.0f )
+ return c1;
+
+ // lerp each component
+ c = (unsigned char*)&newcolor;
+ for ( i=0; i<4; i++ )
+ {
+ a = (float)(c0 & 0xFF);
+ b = (float)(c1 & 0xFF);
+ *c++ = (unsigned char)(a + t*(b-a));
+
+ // next color component
+ c0 >>= 8;
+ c1 >>= 8;
+ }
+
+ return newcolor;
+}
+
+//-----------------------------------------------------------------------------
+// ConvertToWideString
+//-----------------------------------------------------------------------------
+void ConvertToWideString( wchar_t *pDst, const char *pSrc )
+{
+ int len = strlen( pSrc )+1;
+ for (int i=0; i<len; i++)
+ {
+ pDst[i] = pSrc[i];
+ }
+}
+
+//-----------------------------------------------------------------------------
+// CopyString
+//-----------------------------------------------------------------------------
+char *CopyString( const char *pString )
+{
+ char *pNewString = (char *)malloc( strlen( pString ) + 1 );
+ strcpy( pNewString, pString );
+
+ return pNewString;
+}
+
+//-----------------------------------------------------------------------------
+// FixFilename
+//-----------------------------------------------------------------------------
+void FixFilename( char *pPath )
+{
+ int len = strlen( pPath );
+ for (int i=0; i<len; ++i)
+ {
+ if ( pPath[i] == '/')
+ pPath[i] = '\\';
+ }
+}
+
+//-----------------------------------------------------------------------------
+// StripQuotes
+//-----------------------------------------------------------------------------
+void StripQuotes( char *pToken )
+{
+ int len = strlen( pToken );
+ if ( pToken[0] == '"' && pToken[len-1] == '"' )
+ {
+ memcpy( pToken, pToken+1, len-2 );
+ pToken[len-2] = '\0';
+ }
+}
+
+//-----------------------------------------------------------------------------
+// DoesFileExist
+//-----------------------------------------------------------------------------
+bool DoesFileExist( const char *pFilename, DWORD *pSize )
+{
+ HANDLE hFile = CreateFile( pFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ if ( pSize )
+ {
+ *pSize = GetFileSize( hFile, NULL );
+ if ( *pSize == (DWORD)-1 )
+ {
+ *pSize = 0;
+ }
+ }
+
+ // exists
+ CloseHandle( hFile );
+ return true;
+ }
+
+ // not present
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// NormalizePath
+//
+//-----------------------------------------------------------------------------
+void NormalizePath( char* path, bool forceToLower )
+{
+ int i;
+ int srclen;
+
+ srclen = strlen( path );
+ for ( i=0; i<srclen; i++ )
+ {
+ if ( path[i] == '/' )
+ path[i] = '\\';
+ else if ( forceToLower && ( path[i] >= 'A' && path[i] <= 'Z' ) )
+ path[i] = path[i] - 'A' + 'a';
+ }
+}
+
+//-----------------------------------------------------------------------------
+// DeleteAllFiles
+//
+//-----------------------------------------------------------------------------
+void DeleteAllFiles( const char* pDirectory, int level, bool bRecurse )
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA findData;
+ char basepath[MAX_PATH];
+ char searchpath[MAX_PATH];
+ char filename[MAX_PATH];
+
+ TL_AddSeperatorToPath( (char*)pDirectory, basepath );
+ strcpy( searchpath, basepath );
+ strcat( searchpath, "*.*" );
+
+ hFind = FindFirstFile( searchpath, &findData );
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( !stricmp( findData.cFileName, "." ) || !stricmp( findData.cFileName, ".." ) )
+ {
+ continue;
+ }
+
+ strcpy( filename, basepath );
+ strcat( filename, findData.cFileName );
+ NormalizePath( filename, false );
+
+ if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+ if ( bRecurse )
+ {
+ DeleteAllFiles( filename, level+1, true );
+ RemoveDirectory( filename );
+ continue;
+ }
+ }
+
+ SetFileAttributes( filename, FILE_ATTRIBUTE_NORMAL );
+ DeleteFile( filename );
+ }
+ while ( FindNextFile( hFind, &findData ) );
+ FindClose( hFind );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// GetXCompressedHeader
+//-----------------------------------------------------------------------------
+bool GetXCompressedHeader( const char *pFilename, xCompressHeader *pHeader )
+{
+ HANDLE hFile = CreateFile( pFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ DWORD dwBytesRead = 0;
+ ReadFile( hFile, pHeader, sizeof( xCompressHeader ), &dwBytesRead, NULL );
+ CloseHandle( hFile );
+ if ( pHeader->nMagic == xCompressHeader::MAGIC && pHeader->nVersion == xCompressHeader::VERSION )
+ {
+ // valid
+ return true;
+ }
+ }
+
+ // invalid
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// IsTargetFileValid
+//
+// Optional non-zero expected source file size must matcg
+//-----------------------------------------------------------------------------
+bool IsTargetFileValid( const char *pFilename, DWORD dwSrcFileSize )
+{
+ char mrkFilename[MAX_PATH];
+ DWORD dwTargetFileSize = 0;
+ DWORD dwSize = 0;
+ DWORD dwAttributes;
+
+ // all valid target files are non-zero
+ if ( !DoesFileExist( pFilename, &dwTargetFileSize ) || !dwTargetFileSize )
+ {
+ return false;
+ }
+
+ dwAttributes = GetFileAttributes( pFilename );
+ if ( dwAttributes != (DWORD)-1 && ( dwAttributes & FILE_ATTRIBUTE_READONLY ) )
+ {
+ // target files marked read only don't get overwritten
+ return true;
+ }
+
+ // all valid target files must have marker file
+ // presence ensures file was successfully copied
+ strcpy( mrkFilename, pFilename );
+ strcat( mrkFilename, ".mrk" );
+ if ( !DoesFileExist( mrkFilename, NULL ) )
+ {
+ // cannot rely on contents, regardless of size match
+ DeleteFile( pFilename );
+ return false;
+ }
+
+ if ( dwSrcFileSize && dwSrcFileSize != dwTargetFileSize )
+ {
+ DeleteFile( pFilename );
+ return false;
+ }
+
+ // assume valid
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Constructor for CXBoxLoader class
+//-----------------------------------------------------------------------------
+CXBoxLoader::CXBoxLoader() : CXBApplication()
+{
+ // need a persistent time base, use the RTC
+ // all other tick counters reset across relaunch
+ FILETIME fileTime;
+ GetSystemTimeAsFileTime( &fileTime );
+ g_loaderStartTime = ((ULARGE_INTEGER*)&fileTime)->QuadPart;
+
+ m_contextCode = 0;
+ m_pLastMovieFrame = NULL;
+ m_pVB = NULL;
+ m_bAllowAttractAbort = false;
+ m_numFiles = 0;
+ m_bLaunch = false;
+ m_dwLoading = 0;
+ m_bDrawLegal = false;
+ m_LegalTime = 0;
+ m_installThread = NULL;
+ m_State = 0;
+ m_bDrawLoading = false;
+ m_bDrawProgress = false;
+ m_bInstallComplete = false;
+ m_FrameCounter = 0;
+ m_MovieCount = 0;
+ m_bMovieErrorIsFatal = false;
+ m_bDrawDebug = false;
+ m_LoadingBarStartTime = 0;
+ m_LoadingBarEndTime = 0;
+ m_LegalStartTime = 0;
+ m_bCaptureLastMovieFrame = 0;
+ m_bDrawSlideShow = false;
+ m_SlideShowStartTime = 0;
+ m_pLogData = NULL;
+ m_pDefaultTrueTypeFont = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// FatalMediaError
+//-----------------------------------------------------------------------------
+void CXBoxLoader::FatalMediaError()
+{
+ m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0L );
+
+ LPDIRECT3DSURFACE8 pBackBuffer;
+ m_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
+
+ LPCWSTR pLine1;
+ LPCWSTR pLine2;
+ switch( XGetLanguage() )
+ {
+ case XC_LANGUAGE_FRENCH:
+ pLine1 = L"Le disque utilis� pr�sente une anomalie.";
+ pLine2 = L"Il est peut-�tre sale ou endommag�.";
+ break;
+ case XC_LANGUAGE_ITALIAN:
+ pLine1 = L"Il disco in uso ha qualche problema.";
+ pLine2 = L"Potrebbe essere sporco o danneggiato.";
+ break;
+ case XC_LANGUAGE_GERMAN:
+ pLine1 = L"Bei der benutzten CD ist ein Problem aufgetreten.";
+ pLine2 = L"M�glicherweise ist sie verschmutzt oder besch�digt.";
+ break;
+ case XC_LANGUAGE_SPANISH:
+ pLine1 = L"Hay un problema con el disco que est� usando.";
+ pLine2 = L"Puede estar sucio o da�ado.";
+ break;
+ default:
+ pLine1 = L"There is a problem with the disc you are using.";
+ pLine2 = L"It may be dirty or damaged.";
+ break;
+ }
+
+ if ( m_pDefaultTrueTypeFont )
+ {
+ m_pDefaultTrueTypeFont->SetTextAlignment( XFONT_CENTER|XFONT_TOP );
+ m_pDefaultTrueTypeFont->TextOut( pBackBuffer, pLine1, (unsigned)-1, 320, 240-15 );
+ m_pDefaultTrueTypeFont->TextOut( pBackBuffer, pLine2, (unsigned)-1, 320, 240+15 );
+ }
+
+ // Present the scene
+ m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
+
+ pBackBuffer->Release();
+
+ // forever
+ while (1);
+}
+
+//-----------------------------------------------------------------------------
+// LoadTexture
+//-----------------------------------------------------------------------------
+D3DTexture *CXBoxLoader::LoadTexture( int resourceID )
+{
+ // Get access to the texture
+ return ( m_xprResource.GetTexture( resourceID ) );
+}
+
+//-----------------------------------------------------------------------------
+// LoadFont
+//-----------------------------------------------------------------------------
+HRESULT CXBoxLoader::LoadFont( CXBFont *pFont, int resourceID )
+{
+ return pFont->Create( m_xprResource.GetTexture( resourceID ),
+ m_xprResource.GetData( resourceID + sizeof(D3DTexture) ) );
+}
+
+//-----------------------------------------------------------------------------
+// DrawRect
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawRect( int x, int y, int w, int h, DWORD color )
+{
+ // Set states
+ D3DDevice::SetTexture( 0, NULL );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE );
+ D3DDevice::SetRenderState( D3DRS_ZENABLE, FALSE );
+ D3DDevice::SetRenderState( D3DRS_FOGENABLE, FALSE );
+ D3DDevice::SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
+ D3DDevice::SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
+ D3DDevice::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
+ D3DDevice::SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
+ D3DDevice::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
+ D3DDevice::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
+ D3DDevice::SetVertexShader( D3DFVF_XYZRHW|D3DFVF_DIFFUSE );
+
+ FLOAT fX1 = x;
+ FLOAT fY1 = y;
+ FLOAT fX2 = x + w - 1;
+ FLOAT fY2 = y + h - 1;
+
+ D3DDevice::Begin( D3DPT_QUADLIST );
+ D3DDevice::SetVertexDataColor( D3DVSDE_DIFFUSE, color );
+ D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX1, fY1, 1.0f, 1.0f );
+ D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX2, fY1, 1.0f, 1.0f );
+ D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX2, fY2, 1.0f, 1.0f );
+ D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX1, fY2, 1.0f, 1.0f );
+ D3DDevice::End();
+}
+
+
+//-----------------------------------------------------------------------------
+// DrawTexture
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawTexture( D3DTexture *pD3DTexture, int x, int y, int w, int h, int color )
+{
+ struct VERTEX { D3DXVECTOR4 p; D3DCOLOR c; FLOAT tu, tv; };
+ if ( !m_pVB )
+ {
+ // Create a vertex buffer for rendering the help screen
+ D3DDevice::CreateVertexBuffer( 4*sizeof(VERTEX), D3DUSAGE_WRITEONLY, 0L, D3DPOOL_DEFAULT, &m_pVB );
+ }
+
+ VERTEX* v;
+ m_pVB->Lock( 0, 0, (BYTE**)&v, 0L );
+
+ // Calculate vertex positions
+ FLOAT fLeft = x + 0.5f;
+ FLOAT fTop = y + 0.5f;
+ FLOAT fRight = x+w - 0.5f;
+ FLOAT fBottom = y+h - 0.5f;
+
+ // position
+ v[0].p = D3DXVECTOR4( fLeft, fTop, 0, 0 );
+ v[1].p = D3DXVECTOR4( fRight, fTop, 0, 0 );
+ v[2].p = D3DXVECTOR4( fRight, fBottom, 0, 0 );
+ v[3].p = D3DXVECTOR4( fLeft, fBottom, 0, 0 );
+
+ // color
+ v[0].c = color;
+ v[1].c = color;
+ v[2].c = color;
+ v[3].c = color;
+
+ D3DSURFACE_DESC desc;
+ pD3DTexture->GetLevelDesc( 0, &desc );
+
+ // linear texcoords
+ v[0].tu = 0;
+ v[0].tv = 0;
+ v[1].tu = desc.Width;
+ v[1].tv = 0;
+ v[2].tu = desc.Width;
+ v[2].tv = desc.Height;
+ v[3].tu = 0;
+ v[3].tv = desc.Height;
+
+ m_pVB->Unlock();
+
+ // Set state to render the image
+ D3DDevice::SetTexture( 0, pD3DTexture );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
+ D3DDevice::SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
+ D3DDevice::SetRenderState( D3DRS_ZENABLE, FALSE );
+ D3DDevice::SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
+ D3DDevice::SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_ALWAYS );
+ D3DDevice::SetRenderState( D3DRS_FOGENABLE, FALSE );
+ D3DDevice::SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
+ D3DDevice::SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
+ D3DDevice::SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
+ D3DDevice::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
+ D3DDevice::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
+ D3DDevice::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
+ D3DDevice::SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
+ D3DDevice::SetVertexShader( D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1 );
+
+ // Render the image
+ D3DDevice::SetStreamSource( 0, m_pVB, sizeof(VERTEX) );
+ D3DDevice::DrawPrimitive( D3DPT_QUADLIST, 0, 1 );
+}
+
+//-----------------------------------------------------------------------------
+// StartVideo
+//
+// May take a few ms.
+//-----------------------------------------------------------------------------
+HRESULT CXBoxLoader::StartVideo( const CHAR* strFilename, bool bFromMemory, bool bFatalOnError )
+{
+ HRESULT hr;
+ if ( bFromMemory )
+ {
+ // play from memory, so as no to interfere with disc access
+ hr = m_player.OpenMovieFromMemory( strFilename, D3DFMT_LIN_A8R8G8B8, m_pd3dDevice, TRUE );
+ }
+ else
+ {
+ // play from disc
+ hr = m_player.OpenFile( strFilename, D3DFMT_LIN_A8R8G8B8, m_pd3dDevice, TRUE );
+ }
+
+ // can fail anytime
+ m_bMovieErrorIsFatal = bFatalOnError;
+
+ m_MovieCount++;
+
+ if ( FAILED( hr ) )
+ {
+ OUTPUT_DEBUG_STRING( "Video playback failed!\n" );
+
+ if ( bFatalOnError )
+ {
+ FatalMediaError();
+ }
+ }
+
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// StopVideo
+//
+// May take a few ms.
+//-----------------------------------------------------------------------------
+void CXBoxLoader::StopVideo()
+{
+ m_player.TerminatePlayback();
+}
+
+//-----------------------------------------------------------------------------
+// LoadInstallScript
+//
+// Parse filenames to be copied
+//-----------------------------------------------------------------------------
+bool CXBoxLoader::LoadInstallScript()
+{
+ void *pFileData = NULL;
+ DWORD fileSize = 0;
+ DWORD dwSrcSize;
+ HRESULT hr;
+ char srcFile[MAX_PATH];
+ char dstFile[MAX_PATH];
+ char localizedFile[MAX_PATH];
+ HANDLE hFind;
+ char sourceFilename[MAX_PATH];
+ char sourcePath[MAX_PATH];
+ char targetFilename[MAX_PATH];
+ char filename[MAX_PATH];
+ WIN32_FIND_DATA findData;
+ bool bCompressed;
+ xCompressHeader xcHeader;
+ char *pVersion;
+ bool bTargetIsLocalized;
+ int languageID;
+
+ memset( &g_installData, 0, sizeof( installData_t ) );
+
+ hr = XBUtil_LoadFile( "D:\\LoaderMedia\\install.txt", &pFileData, &fileSize );
+ if ( hr != S_OK || !fileSize )
+ {
+ return false;
+ }
+
+ languageID = XGetLanguage();
+
+ // full re-install
+ bool bForce = true;
+
+ // scan
+ TL_SetScriptData( (char*)pFileData, fileSize );
+ while ( 1 )
+ {
+ char *pToken = TL_GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+ StripQuotes( pToken );
+ strcpy( srcFile, pToken);
+
+ pToken = TL_GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+ StripQuotes( pToken );
+ strcpy( dstFile, pToken);
+
+ // replace with language token
+ FixupNamespaceFilename( srcFile, srcFile, languageID );
+ bTargetIsLocalized = FixupNamespaceFilename( dstFile, localizedFile, languageID );
+
+ if ( bTargetIsLocalized )
+ {
+ // localized files are allowed to change without requiring a full re-install
+ bool bDeleteMapCache = false;
+ if ( !IsTargetFileValid( localizedFile, 0 ) )
+ {
+ // must delete map cache to ensure localized files have enough room
+ bDeleteMapCache = true;
+ }
+
+ // only allowing one localized file of this type, delete all others
+ DeleteOtherLocalizedFiles( dstFile, languageID );
+ strcpy( dstFile, localizedFile );
+
+ if ( bDeleteMapCache )
+ {
+ char mapPath[MAX_PATH];
+ strcpy( mapPath, localizedFile );
+ TL_StripFilename( mapPath );
+ TL_AddSeperatorToPath( mapPath, mapPath );
+ strcat( mapPath, "maps\\" );
+ DeleteAllFiles( mapPath, 0, false );
+ }
+ }
+
+ pVersion = strstr( dstFile, "version_" );
+ if ( pVersion )
+ {
+ if ( m_numFiles )
+ {
+ // version statement out of sequence
+ return false;
+ }
+
+ m_Version = atoi( pVersion + strlen( "version_" ) );
+
+ if ( IsTargetFileValid( dstFile, 0 ) )
+ {
+ // version file exists, files should be same
+ bForce = false;
+ }
+
+ if ( bForce )
+ {
+ // delete all files at the specified directory
+ strcpy( targetFilename, dstFile );
+ TL_StripFilename( targetFilename );
+ DeleteAllFiles( targetFilename, 0, true );
+ }
+ }
+
+ // source file could be wildcard, get path only
+ strcpy( sourcePath, srcFile );
+ TL_StripFilename( sourcePath );
+
+ hFind = FindFirstFile( srcFile, &findData );
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( !stricmp( findData.cFileName, "." ) || !stricmp( findData.cFileName, ".." ) )
+ {
+ continue;
+ }
+ if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+ continue;
+ }
+
+ TL_AddSeperatorToPath( sourcePath, sourceFilename );
+ strcat( sourceFilename, findData.cFileName );
+ NormalizePath( sourceFilename, false );
+
+ // target filename may be path or absolute file
+ strcpy( targetFilename, dstFile );
+
+ TL_StripPath( dstFile, filename );
+ if ( !filename[0] )
+ {
+ // target filename is path only
+ TL_AddSeperatorToPath( dstFile, targetFilename );
+ strcat( targetFilename, findData.cFileName );
+ NormalizePath( targetFilename, false );
+ }
+
+ if ( !DoesFileExist( sourceFilename, &dwSrcSize ) )
+ {
+ // can't validate source
+ return false;
+ }
+
+ if ( strstr( sourceFilename, ".xz_" ) && strstr( targetFilename, ".xzp" ) )
+ {
+ bCompressed = true;
+ if ( GetXCompressedHeader( sourceFilename, &xcHeader ) )
+ {
+ g_installData.m_totalSize += xcHeader.nUncompressedFileSize;
+
+ if ( !bForce && IsTargetFileValid( targetFilename, xcHeader.nUncompressedFileSize ) )
+ {
+ // target already exists, no need to recopy
+ g_copyStats.m_bytesCopied += xcHeader.nUncompressedFileSize;
+ continue;
+ }
+ }
+ else
+ {
+ // invalid
+ return false;
+ }
+ }
+ else
+ {
+ g_installData.m_totalSize += dwSrcSize;
+
+ bCompressed = false;
+ if ( !bForce && IsTargetFileValid( targetFilename, dwSrcSize ) )
+ {
+ // target already exists, no need to recopy
+ g_copyStats.m_bytesCopied += dwSrcSize;
+ continue;
+ }
+ }
+
+ if ( m_numFiles < MAX_FILES )
+ {
+ m_fileSrc[m_numFiles] = CopyString( sourceFilename );
+ m_fileDest[m_numFiles] = CopyString( targetFilename );
+
+ if ( bCompressed )
+ {
+ xCompressHeader *pxcHeader = new xCompressHeader;
+ memcpy( pxcHeader, &xcHeader, sizeof( xCompressHeader ) );
+ m_fileCompressionHeaders[m_numFiles] = pxcHeader;
+ m_fileDestSizes[m_numFiles] = pxcHeader->nUncompressedFileSize;
+ }
+ else
+ {
+ m_fileCompressionHeaders[m_numFiles] = NULL;
+ m_fileDestSizes[m_numFiles] = dwSrcSize;
+ }
+
+ m_numFiles++;
+ }
+ }
+ while ( FindNextFile( hFind, &findData ) );
+ FindClose( hFind );
+ }
+ else
+ {
+ // source file not found, invalid
+ return false;
+ }
+ }
+
+ // finsihed with install script
+ free( pFileData );
+
+ g_installData.m_ppSrcFiles = m_fileSrc;
+ g_installData.m_ppDstFiles = m_fileDest;
+ g_installData.m_ppxcHeaders = m_fileCompressionHeaders;
+ g_installData.m_pDstFileSizes = m_fileDestSizes;
+ g_installData.m_numFiles = m_numFiles;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Copies all install files to the hard drive
+//-----------------------------------------------------------------------------
+DWORD WINAPI InstallThreadFunc( LPVOID lpParam )
+{
+ char mrkFilename[MAX_PATH];
+ bool bSuccess;
+ HANDLE hFile;
+
+ g_installStartTime = GetTickCount();
+
+ // started loading
+ *(DWORD*)lpParam = 1;
+
+ for ( int i = 0; i < g_installData.m_numFiles; ++i )
+ {
+ DWORD bytesCopied = g_copyStats.m_bytesCopied;
+
+ // install has already validated, if it's in the list, copy it
+ bSuccess = CopyFileOverlapped( g_installData.m_ppSrcFiles[i], g_installData.m_ppDstFiles[i], g_installData.m_ppxcHeaders[i], &g_copyStats );
+
+ strcpy( mrkFilename, g_installData.m_ppDstFiles[i] );
+ strcat( mrkFilename, ".mrk" );
+
+ SetFileAttributes( mrkFilename, FILE_ATTRIBUTE_NORMAL );
+ if ( bSuccess )
+ {
+ // add marker
+ hFile = CreateFile( mrkFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ CloseHandle( hFile );
+ }
+ }
+ else
+ {
+ // remove marker
+ DeleteFile( mrkFilename );
+ DeleteFile( g_installData.m_ppDstFiles[i] );
+
+ // errors can't stop install
+ // snap progress to expected completion
+ g_copyStats.m_bytesCopied = bytesCopied + g_installData.m_pDstFileSizes[i];
+ }
+ }
+
+ g_installElapsedTime = GetTickCount() - g_installStartTime;
+
+ // finished loading
+ *(DWORD*)lpParam = 0;
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Verify disk space
+//-----------------------------------------------------------------------------
+bool CXBoxLoader::VerifyInstall( void )
+{
+ memset( &g_copyStats, 0, sizeof( CopyStats_t ) );
+
+ LoadLogFile();
+
+ if ( !LoadInstallScript() )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Look for possible forensic log file
+//-----------------------------------------------------------------------------
+void CXBoxLoader::LoadLogFile( void )
+{
+#if defined( XBOX_FORENSIC_LOG )
+ HRESULT hr;
+ char *pFileData = NULL;
+ DWORD fileSize = 0;
+
+ hr = XBUtil_LoadFile( "Z:\\hl2fatal.log", (void**)&pFileData, &fileSize );
+ if ( hr != S_OK || !fileSize )
+ {
+ return;
+ }
+
+ // copy and null terminate
+ m_pLogData = (char *)malloc( fileSize+1 );
+
+ int j = 0;
+ for (int i=0; i<(int)fileSize; i++)
+ {
+ if ( pFileData[i] == 0x0D )
+ continue;
+ m_pLogData[j++] = pFileData[i];
+ }
+ m_pLogData[j] = '\0';
+
+ free( pFileData );
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Starts installation to disk
+//-----------------------------------------------------------------------------
+bool CXBoxLoader::StartInstall( void )
+{
+ // Start the install thread
+ m_installThread = CreateThread( NULL, 0, &InstallThreadFunc, &m_dwLoading, 0, 0 );
+ if ( !m_installThread )
+ {
+ // failed
+ return false;
+ }
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Shows the legal text
+//-----------------------------------------------------------------------------
+void CXBoxLoader::StartLegalScreen( int legal )
+{
+ m_bDrawLegal = true;
+ m_LegalTime = GetTickCount();
+ m_LegalStartTime = 0;
+
+ switch ( legal )
+ {
+ case LEGAL_MAIN:
+ m_pLegalTexture = m_pMainLegalTexture;
+ break;
+ case LEGAL_SOURCE:
+ m_pLegalTexture = m_pSourceLegalTexture;
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// DrawLegals
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawLegals()
+{
+ unsigned int color;
+ float t;
+
+ if ( !m_bDrawLegal )
+ return;
+
+ if ( !m_LegalStartTime )
+ {
+ m_LegalStartTime = GetTickCount();
+ }
+
+ // fade legals
+ t = (float)(GetTickCount() - m_LegalStartTime)/LEGAL_DISPLAY_TIME;
+ if ( t < 0.1f )
+ {
+ // fade up
+ color = LerpColor( 0xFF000000, 0xFFFFFFFF, t*10.0f );
+ }
+ else if ( t < 0.9f )
+ {
+ // hold
+ color = 0xFFFFFFFF;
+ }
+ else
+ {
+ // fade out
+ color = LerpColor( 0xFFFFFFFF, 0xFF000000, (t-0.9f)*10.0f );
+ }
+
+ DrawTexture( m_pLegalTexture, 0, 0, 640, 480, color );
+}
+
+//-----------------------------------------------------------------------------
+// DrawSlideshow
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawSlideshow()
+{
+ float t;
+
+ if ( !m_bDrawSlideShow )
+ return;
+
+ if ( !m_SlideShowStartTime )
+ {
+ m_SlideShowStartTime = GetTickCount();
+ m_SlideShowCount = -1;
+ m_bFinalSlide = false;
+ }
+
+ if ( !m_bInstallComplete && ( GetTickCount() - m_SlideShowStartTime > SLIDESHOW_SLIDETIME ) )
+ {
+ // next slide
+ m_SlideShowCount++;
+ m_SlideShowStartTime = GetTickCount();
+ }
+
+ t = ( GetTickCount() - m_SlideShowStartTime )/(float)SLIDESHOW_FLIPTIME;
+ if ( t >= 1.0f )
+ t = 1.0f;
+
+ if ( m_bInstallComplete && !m_bFinalSlide && t >= 1.0f )
+ {
+ // wait for current slide to complete
+ // final slide must transition back to transition screen
+ m_SlideShowStartTime = GetTickCount();
+ m_bFinalSlide = true;
+ t = 0;
+ }
+
+ if ( !m_bFinalSlide )
+ {
+ // fade next slide in
+ unsigned int fadeInColor = LerpColor( 0x00FFFFFF, 0xFFFFFFFF, t );
+ if ( fadeInColor != 0xFFFFFFFF && m_SlideShowCount != -1 )
+ DrawTexture( m_pSlideShowTextures[m_SlideShowCount % MAX_SLIDESHOW_TEXTURES], 0, 0, 640, 480, 0xFFFFFFFF );
+ DrawTexture( m_pSlideShowTextures[(m_SlideShowCount + 1) % MAX_SLIDESHOW_TEXTURES], 0, 0, 640, 480, fadeInColor );
+ }
+ else
+ {
+ // fade last slide out
+ unsigned int fadeInColor = LerpColor( 0xFFFFFFFF, 0x00FFFFFF, t );
+ DrawTexture( m_pSlideShowTextures[(m_SlideShowCount + 1) % MAX_SLIDESHOW_TEXTURES], 0, 0, 640, 480, fadeInColor );
+ }
+
+ if ( m_bInstallComplete && m_bFinalSlide && t >= 1.0f )
+ {
+ // end of slideshow
+ m_bDrawSlideShow = false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// DrawDebug
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawDebug()
+{
+#ifndef _RETAIL
+ if ( !m_bDrawDebug )
+ return;
+
+ DrawRect( 0, 0, 640, 480, 0xC0000000 );
+
+ m_Font.Begin();
+ m_Font.SetScaleFactors( 0.8f, 0.8f );
+
+ int xPos = SCREEN_WIDTH/2;
+ int yPos = SCREEN_HEIGHT/4;
+ float rate;
+
+ wchar_t textBuffer[256];
+ swprintf( textBuffer, L"Version: %d", m_Version );
+ m_Font.DrawText( 40, 40, 0xffffffff, textBuffer, 0 );
+
+ wchar_t srcFilename[MAX_PATH];
+ wchar_t dstFilename[MAX_PATH];
+ ConvertToWideString( srcFilename, g_copyStats.m_srcFilename );
+ ConvertToWideString( dstFilename, g_copyStats.m_dstFilename );
+ swprintf( textBuffer, L"From: %s (%.2f MB)", srcFilename, (float)g_copyStats.m_readSize/(1024.0f*1024.0f) );
+ m_Font.DrawText( xPos, yPos + 20, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+ swprintf( textBuffer, L"To: %s (%.2f MB)", dstFilename, (float)g_copyStats.m_writeSize/(1024.0f*1024.0f) );
+ m_Font.DrawText( xPos, yPos + 40, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ if ( g_copyStats.m_bufferReadTime && m_dwLoading )
+ rate = ( g_copyStats.m_bufferReadSize/(1024.0f*1024.0f) ) / ( g_copyStats.m_bufferReadTime * 0.001f );
+ else
+ rate = 0;
+ swprintf( textBuffer, L"Buffer Read: %.2f MB (%.2f MB/s) (%d)", g_copyStats.m_bufferReadSize/(1024.0f*1024.0f), rate, g_copyStats.m_numReadBuffers );
+ m_Font.DrawText( xPos, yPos + 80, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ rate = g_copyStats.m_inflateTime && m_dwLoading ? (float)g_copyStats.m_inflateSize/(g_copyStats.m_inflateTime * 0.001f) : 0;
+ swprintf( textBuffer, L"Inflate: %.2f MB (%.2f MB/s)", g_copyStats.m_inflateSize/(1024.0f*1024.0f), rate/(1024.0f*1024.0f) );
+ m_Font.DrawText( xPos, yPos + 100, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ if ( g_copyStats.m_bufferWriteTime && m_dwLoading )
+ rate = ( g_copyStats.m_bufferWriteSize/(1024.0f*1024.0f) ) / ( g_copyStats.m_bufferWriteTime * 0.001f );
+ else
+ rate = 0;
+ swprintf( textBuffer, L"Buffer Write: %.2f MB (%.2f MB/s) (%d)", g_copyStats.m_bufferWriteSize/(1024.0f*1024.0f), rate, g_copyStats.m_numWriteBuffers );
+ m_Font.DrawText( xPos, yPos + 120, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ rate = g_copyStats.m_totalReadTime && m_dwLoading ? (float)g_copyStats.m_totalReadSize/(g_copyStats.m_totalReadTime * 0.001f) : 0;
+ swprintf( textBuffer, L"Total Read: %d MB (%.2f MB/s)", g_copyStats.m_totalReadSize/(1024*1024), rate/(1024.0f*1024.0f) );
+ m_Font.DrawText( xPos, yPos + 160, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ rate = g_copyStats.m_totalWriteTime && m_dwLoading ? (float)g_copyStats.m_totalWriteSize/(g_copyStats.m_totalWriteTime * 0.001f) : 0;
+ swprintf( textBuffer, L"Total Write: %d MB (%.2f MB/s)", g_copyStats.m_totalWriteSize/(1024*1024), rate/(1024.0f*1024.0f) );
+ m_Font.DrawText( xPos, yPos + 180, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ float elapsed = (float)(GetTickCount() - g_installStartTime) * 0.001f;
+ if ( m_dwLoading )
+ {
+ if ( elapsed )
+ rate = g_copyStats.m_totalWriteSize/elapsed;
+ else
+ rate = 0;
+ }
+ else
+ {
+ if ( g_installElapsedTime )
+ rate = g_copyStats.m_totalWriteSize/(g_installElapsedTime * 0.001f);
+ else
+ rate = 0;
+ }
+ swprintf( textBuffer, L"Progress: %d/%d MB Elapsed: %d secs (%.2f MB/s)", g_copyStats.m_bytesCopied/(1024*1024), g_installData.m_totalSize/(1024*1024), (int)elapsed, rate/(1024.0f*1024.0f) );
+ m_Font.DrawText( xPos, yPos + 220, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ swprintf( textBuffer, L"Errors: %d", g_copyStats.m_copyErrors );
+ m_Font.DrawText( xPos, yPos + 240, 0xffffffff, textBuffer, XBFONT_CENTER_X );
+
+ m_Font.End();
+#endif
+}
+
+void CXBoxLoader::DrawLog()
+{
+#if defined( XBOX_FORENSIC_LOG )
+ wchar_t textBuffer[1024];
+ int numChars;
+
+ if ( !m_pLogData )
+ return;
+
+ DrawRect( 0, 0, 640, 480, 0xC0000000 );
+
+ m_Font.Begin();
+ m_Font.SetScaleFactors( 0.8f, 0.8f );
+
+ char *pStart = m_pLogData;
+ char *pEnd = pStart;
+ int yPos = 40;
+ for (int i=0; i<20; i++)
+ {
+ pEnd = strstr( pStart, "\n" );
+ if ( !pEnd )
+ numChars = strlen( pStart );
+ else
+ numChars = pEnd-pStart;
+
+ if ( numChars )
+ {
+ for (int j=0; j<numChars; j++)
+ {
+ textBuffer[j] = pStart[j];
+ }
+ textBuffer[j] = 0;
+ m_Font.DrawText( 40, yPos, 0xffffffff, textBuffer, 0 );
+ }
+
+ if ( !pEnd )
+ break;
+
+ // next line
+ pStart = pEnd+1;
+ yPos += 10;
+ }
+
+ m_Font.End();
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// DrawLoadingMarquee
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawLoadingMarquee()
+{
+ if ( !m_bDrawLoading )
+ return;
+
+ int y = 0.80f*480;
+ DrawTexture( m_pLoadingIconTexture, (640-64)/2, y-64, 64, 64, 0xFFFFFFFF );
+
+ // draw loading text
+ m_Font.Begin();
+ m_Font.SetScaleFactors( 0.8f, 0.8f );
+ m_Font.DrawText( 320, y, PROGRESS_TEXT_COLOR, GetLocalizedLoadingString(), XBFONT_CENTER_X );
+ m_Font.End();
+}
+
+//-----------------------------------------------------------------------------
+// DrawProgressBar
+//-----------------------------------------------------------------------------
+void CXBoxLoader::DrawProgressBar()
+{
+ if ( !m_bDrawProgress )
+ return;
+
+ if ( !m_LoadingBarStartTime )
+ {
+ m_LoadingBarStartTime = GetTickCount();
+ }
+
+ // slide the loading bar up
+ float tUp = (float)(GetTickCount() - m_LoadingBarStartTime)/LOADINGBAR_UPTIME;
+ if ( tUp > 1.0f)
+ tUp = 1.0f;
+ float y = 480.0f + tUp*((float)PROGRESS_Y - 480.0f);
+
+ float t0 = 0;
+ float t1 = 0;
+ int numSegments = 0;
+ if ( tUp == 1.0f )
+ {
+ // loading bar is up
+ // don't snap, animate progress to current level of completion
+ t0 = (float)g_copyStats.m_bytesCopied/(float)g_installData.m_totalSize;
+ if ( t0 > 1.0f )
+ t0 = 1.0f;
+ t1 = (float)(GetTickCount() - m_LoadingBarStartTime - LOADINGBAR_WAITTIME)/LOADINGBAR_SLIDETIME;
+ if ( t1 < 0.0f )
+ t1 = 0.0f;
+ else if ( t1 > 1.0f)
+ t1 = 1.0f;
+ numSegments = t0 * t1 * (float)SEGMENT_COUNT;
+ }
+
+#if 0
+ float tDown = 0;
+ if ( t0 == 1.0f && t1 == 1.0f && !m_dwLoading )
+ {
+ // loading anim and copying of data are finished
+ // slide the loading bar down
+ if ( !m_LoadingBarEndTime )
+ {
+ m_LoadingBarEndTime = GetTickCount();
+ }
+ tDown = (float)(GetTickCount() - m_LoadingBarEndTime - LOADINGBAR_WAITTIME)/LOADINGBAR_UPTIME;
+ if ( tDown < 0.0f )
+ tDown = 0.0f;
+ else if ( tDown > 1.0f)
+ tDown = 1.0f;
+ y = PROGRESS_Y + tDown*(480.0f - (float)PROGRESS_Y);
+ }
+
+ if ( tDown == 1.0f )
+ {
+ // loading bar is offscreen
+ m_bInstallComplete = true;
+ }
+#else
+ if ( t0 == 1.0f && t1 == 1.0f && !m_dwLoading )
+ {
+ m_bInstallComplete = true;
+ }
+#endif
+
+ int x = (640-FOOTER_W)/2;
+ DrawTexture( m_pFooterTexture, x, y, FOOTER_W, 480 - PROGRESS_Y, PROGRESS_FOOTER_COLOR );
+ x += FOOTER_W - 35;
+
+ // draw left justified loading text
+ m_Font.Begin();
+ m_Font.SetScaleFactors( 0.8f, 0.8f );
+ int textWidth = m_Font.GetTextWidth( GetLocalizedLoadingString() );
+ x -= SEGMENT_W + textWidth;
+ m_Font.DrawText( x, y+20, PROGRESS_TEXT_COLOR, GetLocalizedLoadingString(), XBFONT_LEFT );
+ m_Font.End();
+
+ // draw progess bar
+ x -= SEGMENT_W + PROGRESS_W;
+ DrawRect( x, y+25, PROGRESS_W, PROGRESS_H, PROGRESS_INSET_COLOR );
+ for ( int i =0; i<numSegments; i++ )
+ {
+ DrawRect( x, y+25+2, SEGMENT_W, PROGRESS_H-4, PROGRESS_SEGMENT_COLOR );
+ x += SEGMENT_W+SEGMENT_GAP;
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Name: PlayVideoFrame()
+// Desc: Plays one frame of video if a movie is currently open and if there is
+// a frame available. This function is safe to call at any time.
+//-----------------------------------------------------------------------------
+BOOL CXBoxLoader::PlayVideoFrame()
+{
+ if ( !m_player.IsPlaying() )
+ return FALSE;
+
+ const FLOAT fMovieWidth = FLOAT( m_player.GetWidth() );
+ const FLOAT fMovieHeight = FLOAT( m_player.GetHeight() );
+
+ // Move to the next frame.
+ LPDIRECT3DTEXTURE8 pTexture = 0;
+ pTexture = m_player.AdvanceFrameForTexturing( m_pd3dDevice );
+
+ // See if the movie is over now.
+ if ( !m_player.IsPlaying() )
+ {
+ if ( m_bCaptureLastMovieFrame )
+ {
+ m_bCaptureLastMovieFrame = false;
+
+ // Copy Texture
+ if ( m_pLastMovieFrame )
+ {
+ m_pLastMovieFrame->Release();
+ m_pLastMovieFrame = NULL;
+ }
+
+ if ( pTexture )
+ {
+ // copy the last frame
+ D3DSURFACE_DESC d3dSurfaceDesc;
+ D3DLOCKED_RECT srcRect;
+ D3DLOCKED_RECT dstRect;
+ pTexture->GetLevelDesc( 0, &d3dSurfaceDesc );
+ m_pd3dDevice->CreateTexture( d3dSurfaceDesc.Width, d3dSurfaceDesc.Height, 0, 0, d3dSurfaceDesc.Format, 0, &m_pLastMovieFrame );
+ pTexture->LockRect( 0, &srcRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE );
+ m_pLastMovieFrame->LockRect( 0, &dstRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE );
+ memcpy( dstRect.pBits, srcRect.pBits, srcRect.Pitch*d3dSurfaceDesc.Height );
+ }
+ }
+
+ // Clean up the movie, then return.
+ m_player.Destroy();
+ return FALSE;
+ }
+
+ // If no texture is ready, return TRUE to indicate that a movie is playing,
+ // but don't render anything yet.
+ if ( !pTexture )
+ return TRUE;
+
+ const FLOAT fSizeY = 480.0f;
+ const FLOAT fOriginX = 320.0f - ( fSizeY * .5f * fMovieWidth / fMovieHeight );
+ const FLOAT fOriginY = 240.0f - fSizeY * .5f;
+
+ // Draw the texture.
+ m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
+ m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
+ m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
+
+ // Draw the texture as a quad.
+ m_pd3dDevice->SetTexture( 0, pTexture );
+ m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
+ m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+
+ // Wrapping isn't allowed on linear textures.
+ m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
+ m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
+
+ FLOAT fLeft = fOriginX + 0.5f;
+ FLOAT fRight = fOriginX + ( fSizeY * fMovieWidth) / fMovieHeight - 0.5f;
+ FLOAT fTop = fOriginY + 0.5f;
+ FLOAT fBottom = fOriginY + fSizeY - 0.5f;
+
+ // On linear textures the texture coordinate range is from 0,0 to width,height, instead
+ // of 0,0 to 1,1.
+ m_pd3dDevice->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1 );
+ m_pd3dDevice->Begin( D3DPT_QUADLIST );
+ m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, 0, fMovieHeight );
+ m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fLeft, fBottom, 0.0f, 1.0f );
+ m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, 0, 0 );
+ m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fLeft, fTop, 0.0f, 1.0f );
+ m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, fMovieWidth, 0 );
+ m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fRight, fTop, 0.0f, 1.0f );
+ m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, fMovieWidth, fMovieHeight );
+ m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fRight, fBottom, 0.0f, 1.0f );
+ m_pd3dDevice->End();
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LaunchHL2
+//-----------------------------------------------------------------------------
+void CXBoxLoader::LaunchHL2( unsigned int contextCode )
+{
+ LAUNCH_DATA launchData;
+ RelaunchHeader_t *pRelaunch;
+ const char *pHL2Name;
+
+ memset( &launchData, 0, sizeof( LAUNCH_DATA ) );
+
+ // build the relaunch structure that HL2 uses
+ pRelaunch = GetRelaunchHeader( launchData.Data );
+
+ pRelaunch->magicNumber = RELAUNCH_MAGIC_NUMBER;
+ pRelaunch->nBytesRelaunchData = 0;
+
+ if ( ( contextCode & CONTEXTCODE_MAGICMASK ) == CONTEXTCODE_HL2MAGIC )
+ {
+ // ok to re-establish persistent data
+ pRelaunch->bRetail = (contextCode & CONTEXTCODE_RETAIL_MODE) > 0;
+ pRelaunch->bInDebugger = (contextCode & CONTEXTCODE_INDEBUGGER) > 0;
+ }
+ else
+ {
+ // ensure we launch under retail conditions
+ contextCode = CONTEXTCODE_NO_XBDM;
+ g_activeDevice = -1;
+ pRelaunch->bRetail = true;
+ pRelaunch->bInDebugger = false;
+ }
+
+ pRelaunch->contextCode = contextCode;
+ pRelaunch->activeDevice = g_activeDevice;
+ pRelaunch->startTime = g_loaderStartTime;
+
+ // launch the xbe that is expected
+ if ( contextCode & CONTEXTCODE_DEBUG_XBE )
+ {
+ // debug xbe
+ pHL2Name = "D:\\hl2d_xbox.xbe";
+ }
+ else if ( contextCode & CONTEXTCODE_RELEASE_XBE )
+ {
+ // release xbe
+ pHL2Name = "D:\\hl2r_xbox.xbe";
+ }
+ else
+ {
+ // default launch to retail xbe
+ pHL2Name = "D:\\hl2_xbox.xbe";
+ }
+
+ XLaunchNewImage( pHL2Name, &launchData );
+
+ // failed
+ FatalMediaError();
+}
+
+//-----------------------------------------------------------------------------
+// Performs initialization
+//-----------------------------------------------------------------------------
+HRESULT CXBoxLoader::Initialize()
+{
+ DWORD launchType;
+ LAUNCH_DATA launchData;
+
+ // no active device until set
+ g_activeDevice = -1;
+
+ // get launch info and command line params needed for early setting of systems
+ LPSTR pCmdLine = "";
+ DWORD retVal = XGetLaunchInfo( &launchType, &launchData );
+ if ( retVal == ERROR_SUCCESS )
+ {
+ if ( launchType == LDT_FROM_DASHBOARD )
+ {
+ // launched from dashboard
+ LD_FROM_DASHBOARD *pLaunchFromDashboard = (LD_FROM_DASHBOARD *)(&launchData);
+ m_contextCode = pLaunchFromDashboard->dwContext;
+ }
+ else if ( launchType == LDT_TITLE )
+ {
+ // launched directly from HL2 to do something
+ LAUNCH_DATA* pLaunchData = (LAUNCH_DATA *)(&launchData);
+ pCmdLine = (char *)pLaunchData->Data;
+
+ RelaunchHeader_t *pHeader = GetRelaunchHeader( pLaunchData->Data );
+ if ( pHeader->magicNumber == RELAUNCH_MAGIC_NUMBER )
+ {
+ m_contextCode = pHeader->contextCode;
+ g_activeDevice = pHeader->activeDevice;
+ }
+ }
+ else if ( launchType == LDT_FROM_DEBUGGER_CMDLINE )
+ {
+ // launched from the debugger
+ LAUNCH_DATA* pLaunchData = (LAUNCH_DATA *)(&launchData);
+ pCmdLine = (char *)pLaunchData->Data;
+ strlwr( pCmdLine );
+
+ // assume retail mode
+ m_contextCode |= CONTEXTCODE_HL2MAGIC;
+ m_contextCode |= CONTEXTCODE_RETAIL_MODE;
+
+ if ( strstr( pCmdLine, "-indebugger" ) )
+ {
+ m_contextCode |= CONTEXTCODE_INDEBUGGER;
+ }
+#ifndef _RETAIL
+ if ( DmIsDebuggerPresent() )
+ {
+ m_contextCode |= CONTEXTCODE_INDEBUGGER;
+ }
+#endif
+ if ( strstr( pCmdLine, "-debug" ) )
+ {
+ // launch to debug xbe
+ m_contextCode |= CONTEXTCODE_DEBUG_XBE;
+ }
+ else if ( strstr( pCmdLine, "-release" ) )
+ {
+ // launch to release xbe
+ m_contextCode |= CONTEXTCODE_RELEASE_XBE;
+ }
+ else
+ {
+ // default launch to retail xbe
+ m_contextCode |= CONTEXTCODE_RETAIL_XBE|CONTEXTCODE_NO_XBDM;
+ if ( strstr( pCmdLine, "-dev" ) )
+ {
+ // force dev link
+ m_contextCode &= ~CONTEXTCODE_NO_XBDM;
+ }
+ }
+
+ if ( strstr( pCmdLine, "-attract" ) )
+ {
+ // running the attract sequence
+ m_contextCode |= CONTEXTCODE_ATTRACT;
+ }
+ }
+ }
+
+ if ( ( m_contextCode & CONTEXTCODE_MAGICMASK ) != CONTEXTCODE_HL2MAGIC )
+ {
+ // unknown, run the install normally
+ // 0 is a special indicator, due to lack of valid magic
+ m_contextCode = 0;
+ }
+ else
+ {
+ if ( m_contextCode & CONTEXTCODE_DASHBOARD )
+ {
+ // coming from dashboard, back to HL2 - immediately!
+ LaunchHL2( m_contextCode );
+ return S_OK;
+ }
+ }
+
+ if ( FAILED( XFONT_OpenDefaultFont( &m_pDefaultTrueTypeFont ) ) )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ // load install resources for context
+ // Load resource file
+ if ( FAILED( m_xprResource.Create( "D:\\LoaderMedia\\loader.xpr" ) ) )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ if ( FAILED( LoadFont( &m_Font, loader_Font_OFFSET ) ) )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ if ( !( m_contextCode & CONTEXTCODE_ATTRACT ) )
+ {
+ m_pFooterTexture = LoadTexture( loader_Footer_OFFSET );
+ if ( !m_pFooterTexture )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ switch( XGetLanguage() )
+ {
+ case XC_LANGUAGE_FRENCH:
+ m_pMainLegalTexture = LoadTexture( loader_MainLegal_french_OFFSET );
+ break;
+ case XC_LANGUAGE_ITALIAN:
+ m_pMainLegalTexture = LoadTexture( loader_MainLegal_italian_OFFSET );
+ break;
+ case XC_LANGUAGE_GERMAN:
+ m_pMainLegalTexture = LoadTexture( loader_MainLegal_german_OFFSET );
+ break;
+ case XC_LANGUAGE_SPANISH:
+ m_pMainLegalTexture = LoadTexture( loader_MainLegal_spanish_OFFSET );
+ break;
+ default:
+ m_pMainLegalTexture = LoadTexture( loader_MainLegal_english_OFFSET );
+ break;
+ }
+ if ( !m_pMainLegalTexture )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ m_pSourceLegalTexture = LoadTexture( loader_SourceLegal_OFFSET );
+ if ( !m_pSourceLegalTexture )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ switch( XGetLanguage() )
+ {
+ case XC_LANGUAGE_FRENCH:
+ m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_french_OFFSET );
+ break;
+ case XC_LANGUAGE_ITALIAN:
+ m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_italian_OFFSET );
+ break;
+ case XC_LANGUAGE_GERMAN:
+ m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_german_OFFSET );
+ break;
+ case XC_LANGUAGE_SPANISH:
+ m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_spanish_OFFSET );
+ break;
+ default:
+ m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_english_OFFSET );
+ break;
+ }
+ m_pSlideShowTextures[1] = LoadTexture( loader_SlideShow2_OFFSET );
+ m_pSlideShowTextures[2] = LoadTexture( loader_SlideShow3_OFFSET );
+ m_pSlideShowTextures[3] = LoadTexture( loader_SlideShow4_OFFSET );
+ m_pSlideShowTextures[4] = LoadTexture( loader_SlideShow5_OFFSET );
+ m_pSlideShowTextures[5] = LoadTexture( loader_SlideShow6_OFFSET );
+ m_pSlideShowTextures[6] = LoadTexture( loader_SlideShow7_OFFSET );
+ m_pSlideShowTextures[7] = LoadTexture( loader_SlideShow8_OFFSET );
+ m_pSlideShowTextures[8] = LoadTexture( loader_SlideShow9_OFFSET );
+ for ( int i=0; i<MAX_SLIDESHOW_TEXTURES; i++ )
+ {
+ if ( !m_pSlideShowTextures )
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ if ( !VerifyInstall() )
+ {
+ OUTPUT_DEBUG_STRING( "Install failed!\n" );
+ return -1;
+ }
+ }
+
+ m_pLoadingIconTexture = LoadTexture( loader_LoadingIcon_OFFSET );
+ if ( !m_pLoadingIconTexture )
+ {
+ return XBAPPERR_MEDIANOTFOUND;
+ }
+
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------
+// Performs per-frame video checks
+//-----------------------------------------------------------------------------
+void CXBoxLoader::TickVideo()
+{
+ if ( m_bMovieErrorIsFatal && m_player.IsFailed() )
+ {
+ FatalMediaError();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Performs per-frame updates
+//-----------------------------------------------------------------------------
+HRESULT CXBoxLoader::FrameMove()
+{
+ bool bFailed = false;
+
+ TickVideo();
+
+ if ( m_State >= 10 && g_copyStats.m_copyErrors )
+ {
+ FatalMediaError();
+ }
+
+ if ( m_State >= 10 && ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_START ) )
+ {
+ m_bDrawDebug ^= 1;
+ }
+
+ if ( m_bAllowAttractAbort && ( m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A] || ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_START ) ) )
+ {
+ StopVideo();
+
+ // allow only once, until reset
+ m_bAllowAttractAbort = false;
+ }
+
+ switch ( m_State )
+ {
+ case 0:
+ if ( m_contextCode & CONTEXTCODE_ATTRACT )
+ {
+ // play attract mode
+ m_State = 1;
+ }
+ else
+ {
+ // normal installation
+ m_State = 9;
+ }
+ break;
+
+ case 1:
+ // Play the attract video
+ if ( FAILED( StartVideo( "D:\\LoaderMedia\\Demo_Attract.xmv", false, false ) ) )
+ {
+ // jump to finish
+ m_State = 4;
+ }
+ else
+ {
+ m_State = 2;
+ }
+ break;
+
+ case 2:
+ if ( m_player.IsPlaying() || m_player.IsFailed() )
+ {
+ // attract is playing, wait for finish
+ m_State = 3;
+ m_bAllowAttractAbort = true;
+ }
+ break;
+
+ case 3:
+ if ( !m_player.IsPlaying() || m_player.IsFailed() )
+ {
+ // attract is over or aborted
+ m_State = 4;
+ }
+ break;
+
+ case 4:
+ // place loading
+ m_bDrawLoading = true;
+ m_FrameCounter = 0;
+ m_State = 5;
+ break;
+
+ case 5:
+ // wait for two frames to pass to ensure loading is rendered
+ if ( m_FrameCounter > 2 )
+ {
+ m_bLaunch = true;
+ m_State = 6;
+ }
+ break;
+
+ case 6:
+ // idle
+ m_State = 6;
+ break;
+
+ case 9:
+ // Play the opening Valve video
+ StartVideo( "D:\\LoaderMedia\\Valve_Leader.xmv", true, true );
+
+ // Start the async installation process
+ if ( !StartInstall() )
+ {
+ OUTPUT_DEBUG_STRING( "Install failed!\n" );
+ bFailed = true;
+ break;
+ }
+ m_State = 10;
+ break;
+
+ case 10:
+ if ( m_player.IsPlaying() )
+ {
+ // intro is playing, wait for finish
+ m_State = 15;
+ }
+ break;
+
+ case 15:
+ if ( !m_player.IsPlaying() )
+ {
+ // intro is over
+ m_State = 20;
+ }
+ break;
+
+ case 20:
+ // start legals
+ StartLegalScreen( LEGAL_SOURCE );
+ m_State = 25;
+ break;
+
+ case 25:
+ if ( m_bDrawLegal && GetTickCount() - m_LegalTime > LEGAL_DISPLAY_TIME )
+ {
+ // advance to next legal
+ StartLegalScreen( LEGAL_MAIN );
+ m_State = 30;
+ }
+ break;
+
+ case 30:
+ if ( m_bDrawLegal && GetTickCount() - m_LegalTime > LEGAL_DISPLAY_TIME )
+ {
+ // end of all legals
+ if ( IsTargetFileValid( "Z:\\LoaderMedia\\Title_Load.xmv", 0 ) )
+ {
+ m_bDrawLegal = false;
+ m_State = 40;
+ }
+ }
+ break;
+
+ case 40:
+ // play the gordon/alyx hl2 game movie
+ m_bCaptureLastMovieFrame = true;
+ StartVideo( "Z:\\LoaderMedia\\Title_Load.xmv", true, true );
+ m_State = 50;
+ break;
+
+ case 50:
+ if ( m_player.IsPlaying() )
+ {
+ // title movie is playing, wait for finish
+ m_State = 60;
+ }
+ break;
+
+ case 60:
+ if ( m_player.GetElapsedTime() >= 8000 && !m_bDrawProgress )
+ {
+ // wait for known audio click, then put up progress bar
+ // start the loading bar animation
+ m_bDrawProgress = true;
+ }
+
+ if ( m_bInstallComplete && m_bDrawProgress )
+ {
+ // install has completed
+ if ( m_player.IsPlaying() )
+ {
+ // force the movie to end
+ m_player.TerminatePlayback();
+ }
+ m_State = 70;
+ }
+ else if ( !m_bInstallComplete && !m_player.IsPlaying() )
+ {
+ // intro movie has finished, but install is still running
+ // start up slideshow cycler
+ m_bDrawSlideShow = true;
+ m_State = 70;
+ }
+ break;
+
+ case 70:
+ // wait for movie or slideshow to stop
+ if ( !m_player.IsPlaying() && !m_bDrawSlideShow )
+ {
+ m_bLaunch = true;
+ m_State = 80;
+ }
+ break;
+
+ case 80:
+ // idle
+ break;
+ }
+
+
+ if ( bFailed )
+ {
+ FatalMediaError();
+ }
+
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------
+// Renders the scene
+//-----------------------------------------------------------------------------
+HRESULT CXBoxLoader::Render()
+{
+ m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0L );
+
+ // Play a frame from a video.
+ BOOL bPlayedFrame = PlayVideoFrame();
+
+ // hold the last frame of the title movie
+ if ( m_State >= 60 && !bPlayedFrame )
+ {
+ DrawTexture( m_pLastMovieFrame, 0, 0, 640, 480, 0xFFFFFFFF );
+ }
+
+ DrawSlideshow();
+ DrawLoadingMarquee();
+ DrawProgressBar();
+ DrawLegals();
+ DrawDebug();
+ DrawLog();
+
+ if ( m_bLaunch )
+ {
+ // The installation has finished
+ // Persist the image before launching hl2
+ m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
+ m_pd3dDevice->PersistDisplay();
+
+ // Make sure the installation thread has completely exited
+ if ( m_installThread )
+ {
+ WaitForSingleObject( m_installThread, INFINITE );
+ CloseHandle( m_installThread );
+ }
+
+ LaunchHL2( m_contextCode );
+ return S_OK;
+ }
+
+ // Present the scene
+ m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
+
+ m_FrameCounter++;
+
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------
+// Entry point to the program.
+//-----------------------------------------------------------------------------
+VOID __cdecl main()
+{
+ CXBoxLoader xbApp;
+ if ( FAILED( xbApp.Create() ) )
+ {
+ xbApp.FatalMediaError();
+ }
+ xbApp.Run();
+}
+
diff --git a/utils/xbox/xbox_loader/xbox_loader.h b/utils/xbox/xbox_loader/xbox_loader.h
new file mode 100644
index 0000000..b37b2d5
--- /dev/null
+++ b/utils/xbox/xbox_loader/xbox_loader.h
@@ -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 );
diff --git a/utils/xbox/xbox_loader/xbox_loader.sln b/utils/xbox/xbox_loader/xbox_loader.sln
new file mode 100644
index 0000000..e702a04
--- /dev/null
+++ b/utils/xbox/xbox_loader/xbox_loader.sln
@@ -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
diff --git a/utils/xbox/xbox_loader/xbox_loader.vcproj b/utils/xbox/xbox_loader/xbox_loader.vcproj
new file mode 100644
index 0000000..f4a3fef
--- /dev/null
+++ b/utils/xbox/xbox_loader/xbox_loader.vcproj
@@ -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>
diff --git a/utils/xbox/xbox_loader/xmvhelper.cpp b/utils/xbox/xbox_loader/xmvhelper.cpp
new file mode 100644
index 0000000..74060de
--- /dev/null
+++ b/utils/xbox/xbox_loader/xmvhelper.cpp
@@ -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;
+}
diff --git a/utils/xbox/xbox_loader/xmvhelper.h b/utils/xbox/xbox_loader/xmvhelper.h
new file mode 100644
index 0000000..59dd390
--- /dev/null
+++ b/utils/xbox/xbox_loader/xmvhelper.h
@@ -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_