Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2019 lines
54 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // APPLOADER.CPP
  4. //
  5. // Stub executeable
  6. //=====================================================================================//
  7. #include "xbox_loader.h"
  8. struct installData_t
  9. {
  10. char **m_ppSrcFiles;
  11. char **m_ppDstFiles;
  12. DWORD *m_pDstFileSizes;
  13. int m_numFiles;
  14. DWORD m_totalSize;
  15. xCompressHeader **m_ppxcHeaders;
  16. };
  17. DWORD g_installStartTime;
  18. DWORD g_installElapsedTime;
  19. installData_t g_installData;
  20. CopyStats_t g_copyStats;
  21. int g_activeDevice;
  22. __int64 g_loaderStartTime;
  23. //-----------------------------------------------------------------------------
  24. // GetLocalizedLoadingString
  25. //-----------------------------------------------------------------------------
  26. const wchar_t *GetLocalizedLoadingString()
  27. {
  28. switch( XGetLanguage() )
  29. {
  30. case XC_LANGUAGE_FRENCH:
  31. return L"CHARGEMENT...";
  32. case XC_LANGUAGE_ITALIAN:
  33. return L"CARICAMENTO...";
  34. case XC_LANGUAGE_GERMAN:
  35. return L"L�DT...";
  36. case XC_LANGUAGE_SPANISH:
  37. return L"CARGANDO...";
  38. }
  39. return L"LOADING...";
  40. }
  41. //-----------------------------------------------------------------------------
  42. // GetNextLangauge
  43. // Start at -1
  44. //-----------------------------------------------------------------------------
  45. int GetNextLanguage( int languageID )
  46. {
  47. if ( languageID < 0 )
  48. return XC_LANGUAGE_ENGLISH;
  49. // cycle to end
  50. switch ( languageID )
  51. {
  52. case XC_LANGUAGE_ENGLISH:
  53. return XC_LANGUAGE_FRENCH;
  54. case XC_LANGUAGE_FRENCH:
  55. return XC_LANGUAGE_ITALIAN;
  56. case XC_LANGUAGE_ITALIAN:
  57. return XC_LANGUAGE_GERMAN;
  58. case XC_LANGUAGE_GERMAN:
  59. return XC_LANGUAGE_SPANISH;
  60. case XC_LANGUAGE_SPANISH:
  61. return -1;
  62. }
  63. return -1;
  64. }
  65. //-----------------------------------------------------------------------------
  66. // GetLanguageString
  67. //-----------------------------------------------------------------------------
  68. const char *GetLanguageString( int languageID )
  69. {
  70. switch( languageID )
  71. {
  72. case XC_LANGUAGE_FRENCH:
  73. return "french";
  74. case XC_LANGUAGE_ITALIAN:
  75. return "italian";
  76. case XC_LANGUAGE_GERMAN:
  77. return "german";
  78. case XC_LANGUAGE_SPANISH:
  79. return "spanish";
  80. }
  81. return "english";
  82. }
  83. //-----------------------------------------------------------------------------
  84. // FixupNamespaceFilename
  85. //-----------------------------------------------------------------------------
  86. bool FixupNamespaceFilename( const char *pFilename, char *pOutFilename, int languageID )
  87. {
  88. char newFilename[MAX_PATH];
  89. bool bFixup = false;
  90. int dstLen = 0;
  91. int srcLen = strlen( pFilename );
  92. for ( int i=0; i<srcLen+1; i++ )
  93. {
  94. // replace every occurrence of % with language
  95. if ( pFilename[i] == '%' )
  96. {
  97. int len = strlen( GetLanguageString( languageID ) );
  98. memcpy( newFilename + dstLen, GetLanguageString( languageID ), len );
  99. dstLen += len;
  100. bFixup = true;
  101. }
  102. else
  103. {
  104. newFilename[dstLen] = pFilename[i];
  105. dstLen++;
  106. }
  107. }
  108. strcpy( pOutFilename, newFilename );
  109. return bFixup;
  110. }
  111. //-----------------------------------------------------------------------------
  112. // DeleteOtherLocalizedFiles
  113. //-----------------------------------------------------------------------------
  114. void DeleteOtherLocalizedFiles( const char *pFilename, int languageIDToKeep )
  115. {
  116. char newFilename[MAX_PATH];
  117. char mrkFilename[MAX_PATH];
  118. bool bFixup;
  119. int languageID = -1;
  120. while ( 1 )
  121. {
  122. languageID = GetNextLanguage( languageID );
  123. if ( languageID == -1 )
  124. {
  125. // cycled through
  126. break;
  127. }
  128. if ( languageID == languageIDToKeep )
  129. {
  130. // skip
  131. continue;
  132. }
  133. bFixup = FixupNamespaceFilename( pFilename, newFilename, languageID );
  134. if ( !bFixup )
  135. {
  136. // nothing to do
  137. continue;
  138. }
  139. SetFileAttributes( newFilename, FILE_ATTRIBUTE_NORMAL );
  140. DeleteFile( newFilename );
  141. // delete marker
  142. strcpy( mrkFilename, newFilename );
  143. strcat( mrkFilename, ".mrk" );
  144. SetFileAttributes( mrkFilename, FILE_ATTRIBUTE_NORMAL );
  145. DeleteFile( mrkFilename );
  146. }
  147. }
  148. //-----------------------------------------------------------------------------
  149. // LerpColor
  150. //-----------------------------------------------------------------------------
  151. unsigned int LerpColor( unsigned int c0, unsigned int c1, float t )
  152. {
  153. int i;
  154. float a;
  155. float b;
  156. unsigned char* c;
  157. unsigned int newcolor;
  158. if ( t <= 0.0f )
  159. return c0;
  160. else if ( t >= 1.0f )
  161. return c1;
  162. // lerp each component
  163. c = (unsigned char*)&newcolor;
  164. for ( i=0; i<4; i++ )
  165. {
  166. a = (float)(c0 & 0xFF);
  167. b = (float)(c1 & 0xFF);
  168. *c++ = (unsigned char)(a + t*(b-a));
  169. // next color component
  170. c0 >>= 8;
  171. c1 >>= 8;
  172. }
  173. return newcolor;
  174. }
  175. //-----------------------------------------------------------------------------
  176. // ConvertToWideString
  177. //-----------------------------------------------------------------------------
  178. void ConvertToWideString( wchar_t *pDst, const char *pSrc )
  179. {
  180. int len = strlen( pSrc )+1;
  181. for (int i=0; i<len; i++)
  182. {
  183. pDst[i] = pSrc[i];
  184. }
  185. }
  186. //-----------------------------------------------------------------------------
  187. // CopyString
  188. //-----------------------------------------------------------------------------
  189. char *CopyString( const char *pString )
  190. {
  191. char *pNewString = (char *)malloc( strlen( pString ) + 1 );
  192. strcpy( pNewString, pString );
  193. return pNewString;
  194. }
  195. //-----------------------------------------------------------------------------
  196. // FixFilename
  197. //-----------------------------------------------------------------------------
  198. void FixFilename( char *pPath )
  199. {
  200. int len = strlen( pPath );
  201. for (int i=0; i<len; ++i)
  202. {
  203. if ( pPath[i] == '/')
  204. pPath[i] = '\\';
  205. }
  206. }
  207. //-----------------------------------------------------------------------------
  208. // StripQuotes
  209. //-----------------------------------------------------------------------------
  210. void StripQuotes( char *pToken )
  211. {
  212. int len = strlen( pToken );
  213. if ( pToken[0] == '"' && pToken[len-1] == '"' )
  214. {
  215. memcpy( pToken, pToken+1, len-2 );
  216. pToken[len-2] = '\0';
  217. }
  218. }
  219. //-----------------------------------------------------------------------------
  220. // DoesFileExist
  221. //-----------------------------------------------------------------------------
  222. bool DoesFileExist( const char *pFilename, DWORD *pSize )
  223. {
  224. HANDLE hFile = CreateFile( pFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  225. if ( hFile != INVALID_HANDLE_VALUE )
  226. {
  227. if ( pSize )
  228. {
  229. *pSize = GetFileSize( hFile, NULL );
  230. if ( *pSize == (DWORD)-1 )
  231. {
  232. *pSize = 0;
  233. }
  234. }
  235. // exists
  236. CloseHandle( hFile );
  237. return true;
  238. }
  239. // not present
  240. return false;
  241. }
  242. //-----------------------------------------------------------------------------
  243. // NormalizePath
  244. //
  245. //-----------------------------------------------------------------------------
  246. void NormalizePath( char* path, bool forceToLower )
  247. {
  248. int i;
  249. int srclen;
  250. srclen = strlen( path );
  251. for ( i=0; i<srclen; i++ )
  252. {
  253. if ( path[i] == '/' )
  254. path[i] = '\\';
  255. else if ( forceToLower && ( path[i] >= 'A' && path[i] <= 'Z' ) )
  256. path[i] = path[i] - 'A' + 'a';
  257. }
  258. }
  259. //-----------------------------------------------------------------------------
  260. // DeleteAllFiles
  261. //
  262. //-----------------------------------------------------------------------------
  263. void DeleteAllFiles( const char* pDirectory, int level, bool bRecurse )
  264. {
  265. HANDLE hFind;
  266. WIN32_FIND_DATA findData;
  267. char basepath[MAX_PATH];
  268. char searchpath[MAX_PATH];
  269. char filename[MAX_PATH];
  270. TL_AddSeperatorToPath( (char*)pDirectory, basepath );
  271. strcpy( searchpath, basepath );
  272. strcat( searchpath, "*.*" );
  273. hFind = FindFirstFile( searchpath, &findData );
  274. if ( hFind != INVALID_HANDLE_VALUE )
  275. {
  276. do
  277. {
  278. if ( !stricmp( findData.cFileName, "." ) || !stricmp( findData.cFileName, ".." ) )
  279. {
  280. continue;
  281. }
  282. strcpy( filename, basepath );
  283. strcat( filename, findData.cFileName );
  284. NormalizePath( filename, false );
  285. if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  286. {
  287. if ( bRecurse )
  288. {
  289. DeleteAllFiles( filename, level+1, true );
  290. RemoveDirectory( filename );
  291. continue;
  292. }
  293. }
  294. SetFileAttributes( filename, FILE_ATTRIBUTE_NORMAL );
  295. DeleteFile( filename );
  296. }
  297. while ( FindNextFile( hFind, &findData ) );
  298. FindClose( hFind );
  299. }
  300. }
  301. //-----------------------------------------------------------------------------
  302. // GetXCompressedHeader
  303. //-----------------------------------------------------------------------------
  304. bool GetXCompressedHeader( const char *pFilename, xCompressHeader *pHeader )
  305. {
  306. HANDLE hFile = CreateFile( pFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  307. if ( hFile != INVALID_HANDLE_VALUE )
  308. {
  309. DWORD dwBytesRead = 0;
  310. ReadFile( hFile, pHeader, sizeof( xCompressHeader ), &dwBytesRead, NULL );
  311. CloseHandle( hFile );
  312. if ( pHeader->nMagic == xCompressHeader::MAGIC && pHeader->nVersion == xCompressHeader::VERSION )
  313. {
  314. // valid
  315. return true;
  316. }
  317. }
  318. // invalid
  319. return false;
  320. }
  321. //-----------------------------------------------------------------------------
  322. // IsTargetFileValid
  323. //
  324. // Optional non-zero expected source file size must matcg
  325. //-----------------------------------------------------------------------------
  326. bool IsTargetFileValid( const char *pFilename, DWORD dwSrcFileSize )
  327. {
  328. char mrkFilename[MAX_PATH];
  329. DWORD dwTargetFileSize = 0;
  330. DWORD dwSize = 0;
  331. DWORD dwAttributes;
  332. // all valid target files are non-zero
  333. if ( !DoesFileExist( pFilename, &dwTargetFileSize ) || !dwTargetFileSize )
  334. {
  335. return false;
  336. }
  337. dwAttributes = GetFileAttributes( pFilename );
  338. if ( dwAttributes != (DWORD)-1 && ( dwAttributes & FILE_ATTRIBUTE_READONLY ) )
  339. {
  340. // target files marked read only don't get overwritten
  341. return true;
  342. }
  343. // all valid target files must have marker file
  344. // presence ensures file was successfully copied
  345. strcpy( mrkFilename, pFilename );
  346. strcat( mrkFilename, ".mrk" );
  347. if ( !DoesFileExist( mrkFilename, NULL ) )
  348. {
  349. // cannot rely on contents, regardless of size match
  350. DeleteFile( pFilename );
  351. return false;
  352. }
  353. if ( dwSrcFileSize && dwSrcFileSize != dwTargetFileSize )
  354. {
  355. DeleteFile( pFilename );
  356. return false;
  357. }
  358. // assume valid
  359. return true;
  360. }
  361. //-----------------------------------------------------------------------------
  362. // Constructor for CXBoxLoader class
  363. //-----------------------------------------------------------------------------
  364. CXBoxLoader::CXBoxLoader() : CXBApplication()
  365. {
  366. // need a persistent time base, use the RTC
  367. // all other tick counters reset across relaunch
  368. FILETIME fileTime;
  369. GetSystemTimeAsFileTime( &fileTime );
  370. g_loaderStartTime = ((ULARGE_INTEGER*)&fileTime)->QuadPart;
  371. m_contextCode = 0;
  372. m_pLastMovieFrame = NULL;
  373. m_pVB = NULL;
  374. m_bAllowAttractAbort = false;
  375. m_numFiles = 0;
  376. m_bLaunch = false;
  377. m_dwLoading = 0;
  378. m_bDrawLegal = false;
  379. m_LegalTime = 0;
  380. m_installThread = NULL;
  381. m_State = 0;
  382. m_bDrawLoading = false;
  383. m_bDrawProgress = false;
  384. m_bInstallComplete = false;
  385. m_FrameCounter = 0;
  386. m_MovieCount = 0;
  387. m_bMovieErrorIsFatal = false;
  388. m_bDrawDebug = false;
  389. m_LoadingBarStartTime = 0;
  390. m_LoadingBarEndTime = 0;
  391. m_LegalStartTime = 0;
  392. m_bCaptureLastMovieFrame = 0;
  393. m_bDrawSlideShow = false;
  394. m_SlideShowStartTime = 0;
  395. m_pLogData = NULL;
  396. m_pDefaultTrueTypeFont = NULL;
  397. }
  398. //-----------------------------------------------------------------------------
  399. // FatalMediaError
  400. //-----------------------------------------------------------------------------
  401. void CXBoxLoader::FatalMediaError()
  402. {
  403. m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0L );
  404. LPDIRECT3DSURFACE8 pBackBuffer;
  405. m_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
  406. LPCWSTR pLine1;
  407. LPCWSTR pLine2;
  408. switch( XGetLanguage() )
  409. {
  410. case XC_LANGUAGE_FRENCH:
  411. pLine1 = L"Le disque utilis� pr�sente une anomalie.";
  412. pLine2 = L"Il est peut-�tre sale ou endommag�.";
  413. break;
  414. case XC_LANGUAGE_ITALIAN:
  415. pLine1 = L"Il disco in uso ha qualche problema.";
  416. pLine2 = L"Potrebbe essere sporco o danneggiato.";
  417. break;
  418. case XC_LANGUAGE_GERMAN:
  419. pLine1 = L"Bei der benutzten CD ist ein Problem aufgetreten.";
  420. pLine2 = L"M�glicherweise ist sie verschmutzt oder besch�digt.";
  421. break;
  422. case XC_LANGUAGE_SPANISH:
  423. pLine1 = L"Hay un problema con el disco que est� usando.";
  424. pLine2 = L"Puede estar sucio o da�ado.";
  425. break;
  426. default:
  427. pLine1 = L"There is a problem with the disc you are using.";
  428. pLine2 = L"It may be dirty or damaged.";
  429. break;
  430. }
  431. if ( m_pDefaultTrueTypeFont )
  432. {
  433. m_pDefaultTrueTypeFont->SetTextAlignment( XFONT_CENTER|XFONT_TOP );
  434. m_pDefaultTrueTypeFont->TextOut( pBackBuffer, pLine1, (unsigned)-1, 320, 240-15 );
  435. m_pDefaultTrueTypeFont->TextOut( pBackBuffer, pLine2, (unsigned)-1, 320, 240+15 );
  436. }
  437. // Present the scene
  438. m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  439. pBackBuffer->Release();
  440. // forever
  441. while (1);
  442. }
  443. //-----------------------------------------------------------------------------
  444. // LoadTexture
  445. //-----------------------------------------------------------------------------
  446. D3DTexture *CXBoxLoader::LoadTexture( int resourceID )
  447. {
  448. // Get access to the texture
  449. return ( m_xprResource.GetTexture( resourceID ) );
  450. }
  451. //-----------------------------------------------------------------------------
  452. // LoadFont
  453. //-----------------------------------------------------------------------------
  454. HRESULT CXBoxLoader::LoadFont( CXBFont *pFont, int resourceID )
  455. {
  456. return pFont->Create( m_xprResource.GetTexture( resourceID ),
  457. m_xprResource.GetData( resourceID + sizeof(D3DTexture) ) );
  458. }
  459. //-----------------------------------------------------------------------------
  460. // DrawRect
  461. //-----------------------------------------------------------------------------
  462. void CXBoxLoader::DrawRect( int x, int y, int w, int h, DWORD color )
  463. {
  464. // Set states
  465. D3DDevice::SetTexture( 0, NULL );
  466. D3DDevice::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE );
  467. D3DDevice::SetRenderState( D3DRS_ZENABLE, FALSE );
  468. D3DDevice::SetRenderState( D3DRS_FOGENABLE, FALSE );
  469. D3DDevice::SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
  470. D3DDevice::SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  471. D3DDevice::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  472. D3DDevice::SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
  473. D3DDevice::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  474. D3DDevice::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  475. D3DDevice::SetVertexShader( D3DFVF_XYZRHW|D3DFVF_DIFFUSE );
  476. FLOAT fX1 = x;
  477. FLOAT fY1 = y;
  478. FLOAT fX2 = x + w - 1;
  479. FLOAT fY2 = y + h - 1;
  480. D3DDevice::Begin( D3DPT_QUADLIST );
  481. D3DDevice::SetVertexDataColor( D3DVSDE_DIFFUSE, color );
  482. D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX1, fY1, 1.0f, 1.0f );
  483. D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX2, fY1, 1.0f, 1.0f );
  484. D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX2, fY2, 1.0f, 1.0f );
  485. D3DDevice::SetVertexData4f( D3DVSDE_VERTEX, fX1, fY2, 1.0f, 1.0f );
  486. D3DDevice::End();
  487. }
  488. //-----------------------------------------------------------------------------
  489. // DrawTexture
  490. //-----------------------------------------------------------------------------
  491. void CXBoxLoader::DrawTexture( D3DTexture *pD3DTexture, int x, int y, int w, int h, int color )
  492. {
  493. struct VERTEX { D3DXVECTOR4 p; D3DCOLOR c; FLOAT tu, tv; };
  494. if ( !m_pVB )
  495. {
  496. // Create a vertex buffer for rendering the help screen
  497. D3DDevice::CreateVertexBuffer( 4*sizeof(VERTEX), D3DUSAGE_WRITEONLY, 0L, D3DPOOL_DEFAULT, &m_pVB );
  498. }
  499. VERTEX* v;
  500. m_pVB->Lock( 0, 0, (BYTE**)&v, 0L );
  501. // Calculate vertex positions
  502. FLOAT fLeft = x + 0.5f;
  503. FLOAT fTop = y + 0.5f;
  504. FLOAT fRight = x+w - 0.5f;
  505. FLOAT fBottom = y+h - 0.5f;
  506. // position
  507. v[0].p = D3DXVECTOR4( fLeft, fTop, 0, 0 );
  508. v[1].p = D3DXVECTOR4( fRight, fTop, 0, 0 );
  509. v[2].p = D3DXVECTOR4( fRight, fBottom, 0, 0 );
  510. v[3].p = D3DXVECTOR4( fLeft, fBottom, 0, 0 );
  511. // color
  512. v[0].c = color;
  513. v[1].c = color;
  514. v[2].c = color;
  515. v[3].c = color;
  516. D3DSURFACE_DESC desc;
  517. pD3DTexture->GetLevelDesc( 0, &desc );
  518. // linear texcoords
  519. v[0].tu = 0;
  520. v[0].tv = 0;
  521. v[1].tu = desc.Width;
  522. v[1].tv = 0;
  523. v[2].tu = desc.Width;
  524. v[2].tv = desc.Height;
  525. v[3].tu = 0;
  526. v[3].tv = desc.Height;
  527. m_pVB->Unlock();
  528. // Set state to render the image
  529. D3DDevice::SetTexture( 0, pD3DTexture );
  530. D3DDevice::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  531. D3DDevice::SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  532. D3DDevice::SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  533. D3DDevice::SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  534. D3DDevice::SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  535. D3DDevice::SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
  536. D3DDevice::SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
  537. D3DDevice::SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
  538. D3DDevice::SetTextureStageState( 0, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
  539. D3DDevice::SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  540. D3DDevice::SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  541. D3DDevice::SetRenderState( D3DRS_ZENABLE, FALSE );
  542. D3DDevice::SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
  543. D3DDevice::SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_ALWAYS );
  544. D3DDevice::SetRenderState( D3DRS_FOGENABLE, FALSE );
  545. D3DDevice::SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
  546. D3DDevice::SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  547. D3DDevice::SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
  548. D3DDevice::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  549. D3DDevice::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  550. D3DDevice::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  551. D3DDevice::SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
  552. D3DDevice::SetVertexShader( D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1 );
  553. // Render the image
  554. D3DDevice::SetStreamSource( 0, m_pVB, sizeof(VERTEX) );
  555. D3DDevice::DrawPrimitive( D3DPT_QUADLIST, 0, 1 );
  556. }
  557. //-----------------------------------------------------------------------------
  558. // StartVideo
  559. //
  560. // May take a few ms.
  561. //-----------------------------------------------------------------------------
  562. HRESULT CXBoxLoader::StartVideo( const CHAR* strFilename, bool bFromMemory, bool bFatalOnError )
  563. {
  564. HRESULT hr;
  565. if ( bFromMemory )
  566. {
  567. // play from memory, so as no to interfere with disc access
  568. hr = m_player.OpenMovieFromMemory( strFilename, D3DFMT_LIN_A8R8G8B8, m_pd3dDevice, TRUE );
  569. }
  570. else
  571. {
  572. // play from disc
  573. hr = m_player.OpenFile( strFilename, D3DFMT_LIN_A8R8G8B8, m_pd3dDevice, TRUE );
  574. }
  575. // can fail anytime
  576. m_bMovieErrorIsFatal = bFatalOnError;
  577. m_MovieCount++;
  578. if ( FAILED( hr ) )
  579. {
  580. OUTPUT_DEBUG_STRING( "Video playback failed!\n" );
  581. if ( bFatalOnError )
  582. {
  583. FatalMediaError();
  584. }
  585. }
  586. return hr;
  587. }
  588. //-----------------------------------------------------------------------------
  589. // StopVideo
  590. //
  591. // May take a few ms.
  592. //-----------------------------------------------------------------------------
  593. void CXBoxLoader::StopVideo()
  594. {
  595. m_player.TerminatePlayback();
  596. }
  597. //-----------------------------------------------------------------------------
  598. // LoadInstallScript
  599. //
  600. // Parse filenames to be copied
  601. //-----------------------------------------------------------------------------
  602. bool CXBoxLoader::LoadInstallScript()
  603. {
  604. void *pFileData = NULL;
  605. DWORD fileSize = 0;
  606. DWORD dwSrcSize;
  607. HRESULT hr;
  608. char srcFile[MAX_PATH];
  609. char dstFile[MAX_PATH];
  610. char localizedFile[MAX_PATH];
  611. HANDLE hFind;
  612. char sourceFilename[MAX_PATH];
  613. char sourcePath[MAX_PATH];
  614. char targetFilename[MAX_PATH];
  615. char filename[MAX_PATH];
  616. WIN32_FIND_DATA findData;
  617. bool bCompressed;
  618. xCompressHeader xcHeader;
  619. char *pVersion;
  620. bool bTargetIsLocalized;
  621. int languageID;
  622. memset( &g_installData, 0, sizeof( installData_t ) );
  623. hr = XBUtil_LoadFile( "D:\\LoaderMedia\\install.txt", &pFileData, &fileSize );
  624. if ( hr != S_OK || !fileSize )
  625. {
  626. return false;
  627. }
  628. languageID = XGetLanguage();
  629. // full re-install
  630. bool bForce = true;
  631. // scan
  632. TL_SetScriptData( (char*)pFileData, fileSize );
  633. while ( 1 )
  634. {
  635. char *pToken = TL_GetToken( true );
  636. if ( !pToken || !pToken[0] )
  637. break;
  638. StripQuotes( pToken );
  639. strcpy( srcFile, pToken);
  640. pToken = TL_GetToken( true );
  641. if ( !pToken || !pToken[0] )
  642. break;
  643. StripQuotes( pToken );
  644. strcpy( dstFile, pToken);
  645. // replace with language token
  646. FixupNamespaceFilename( srcFile, srcFile, languageID );
  647. bTargetIsLocalized = FixupNamespaceFilename( dstFile, localizedFile, languageID );
  648. if ( bTargetIsLocalized )
  649. {
  650. // localized files are allowed to change without requiring a full re-install
  651. bool bDeleteMapCache = false;
  652. if ( !IsTargetFileValid( localizedFile, 0 ) )
  653. {
  654. // must delete map cache to ensure localized files have enough room
  655. bDeleteMapCache = true;
  656. }
  657. // only allowing one localized file of this type, delete all others
  658. DeleteOtherLocalizedFiles( dstFile, languageID );
  659. strcpy( dstFile, localizedFile );
  660. if ( bDeleteMapCache )
  661. {
  662. char mapPath[MAX_PATH];
  663. strcpy( mapPath, localizedFile );
  664. TL_StripFilename( mapPath );
  665. TL_AddSeperatorToPath( mapPath, mapPath );
  666. strcat( mapPath, "maps\\" );
  667. DeleteAllFiles( mapPath, 0, false );
  668. }
  669. }
  670. pVersion = strstr( dstFile, "version_" );
  671. if ( pVersion )
  672. {
  673. if ( m_numFiles )
  674. {
  675. // version statement out of sequence
  676. return false;
  677. }
  678. m_Version = atoi( pVersion + strlen( "version_" ) );
  679. if ( IsTargetFileValid( dstFile, 0 ) )
  680. {
  681. // version file exists, files should be same
  682. bForce = false;
  683. }
  684. if ( bForce )
  685. {
  686. // delete all files at the specified directory
  687. strcpy( targetFilename, dstFile );
  688. TL_StripFilename( targetFilename );
  689. DeleteAllFiles( targetFilename, 0, true );
  690. }
  691. }
  692. // source file could be wildcard, get path only
  693. strcpy( sourcePath, srcFile );
  694. TL_StripFilename( sourcePath );
  695. hFind = FindFirstFile( srcFile, &findData );
  696. if ( hFind != INVALID_HANDLE_VALUE )
  697. {
  698. do
  699. {
  700. if ( !stricmp( findData.cFileName, "." ) || !stricmp( findData.cFileName, ".." ) )
  701. {
  702. continue;
  703. }
  704. if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  705. {
  706. continue;
  707. }
  708. TL_AddSeperatorToPath( sourcePath, sourceFilename );
  709. strcat( sourceFilename, findData.cFileName );
  710. NormalizePath( sourceFilename, false );
  711. // target filename may be path or absolute file
  712. strcpy( targetFilename, dstFile );
  713. TL_StripPath( dstFile, filename );
  714. if ( !filename[0] )
  715. {
  716. // target filename is path only
  717. TL_AddSeperatorToPath( dstFile, targetFilename );
  718. strcat( targetFilename, findData.cFileName );
  719. NormalizePath( targetFilename, false );
  720. }
  721. if ( !DoesFileExist( sourceFilename, &dwSrcSize ) )
  722. {
  723. // can't validate source
  724. return false;
  725. }
  726. if ( strstr( sourceFilename, ".xz_" ) && strstr( targetFilename, ".xzp" ) )
  727. {
  728. bCompressed = true;
  729. if ( GetXCompressedHeader( sourceFilename, &xcHeader ) )
  730. {
  731. g_installData.m_totalSize += xcHeader.nUncompressedFileSize;
  732. if ( !bForce && IsTargetFileValid( targetFilename, xcHeader.nUncompressedFileSize ) )
  733. {
  734. // target already exists, no need to recopy
  735. g_copyStats.m_bytesCopied += xcHeader.nUncompressedFileSize;
  736. continue;
  737. }
  738. }
  739. else
  740. {
  741. // invalid
  742. return false;
  743. }
  744. }
  745. else
  746. {
  747. g_installData.m_totalSize += dwSrcSize;
  748. bCompressed = false;
  749. if ( !bForce && IsTargetFileValid( targetFilename, dwSrcSize ) )
  750. {
  751. // target already exists, no need to recopy
  752. g_copyStats.m_bytesCopied += dwSrcSize;
  753. continue;
  754. }
  755. }
  756. if ( m_numFiles < MAX_FILES )
  757. {
  758. m_fileSrc[m_numFiles] = CopyString( sourceFilename );
  759. m_fileDest[m_numFiles] = CopyString( targetFilename );
  760. if ( bCompressed )
  761. {
  762. xCompressHeader *pxcHeader = new xCompressHeader;
  763. memcpy( pxcHeader, &xcHeader, sizeof( xCompressHeader ) );
  764. m_fileCompressionHeaders[m_numFiles] = pxcHeader;
  765. m_fileDestSizes[m_numFiles] = pxcHeader->nUncompressedFileSize;
  766. }
  767. else
  768. {
  769. m_fileCompressionHeaders[m_numFiles] = NULL;
  770. m_fileDestSizes[m_numFiles] = dwSrcSize;
  771. }
  772. m_numFiles++;
  773. }
  774. }
  775. while ( FindNextFile( hFind, &findData ) );
  776. FindClose( hFind );
  777. }
  778. else
  779. {
  780. // source file not found, invalid
  781. return false;
  782. }
  783. }
  784. // finsihed with install script
  785. free( pFileData );
  786. g_installData.m_ppSrcFiles = m_fileSrc;
  787. g_installData.m_ppDstFiles = m_fileDest;
  788. g_installData.m_ppxcHeaders = m_fileCompressionHeaders;
  789. g_installData.m_pDstFileSizes = m_fileDestSizes;
  790. g_installData.m_numFiles = m_numFiles;
  791. return true;
  792. }
  793. //-----------------------------------------------------------------------------
  794. // Copies all install files to the hard drive
  795. //-----------------------------------------------------------------------------
  796. DWORD WINAPI InstallThreadFunc( LPVOID lpParam )
  797. {
  798. char mrkFilename[MAX_PATH];
  799. bool bSuccess;
  800. HANDLE hFile;
  801. g_installStartTime = GetTickCount();
  802. // started loading
  803. *(DWORD*)lpParam = 1;
  804. for ( int i = 0; i < g_installData.m_numFiles; ++i )
  805. {
  806. DWORD bytesCopied = g_copyStats.m_bytesCopied;
  807. // install has already validated, if it's in the list, copy it
  808. bSuccess = CopyFileOverlapped( g_installData.m_ppSrcFiles[i], g_installData.m_ppDstFiles[i], g_installData.m_ppxcHeaders[i], &g_copyStats );
  809. strcpy( mrkFilename, g_installData.m_ppDstFiles[i] );
  810. strcat( mrkFilename, ".mrk" );
  811. SetFileAttributes( mrkFilename, FILE_ATTRIBUTE_NORMAL );
  812. if ( bSuccess )
  813. {
  814. // add marker
  815. hFile = CreateFile( mrkFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  816. if ( hFile != INVALID_HANDLE_VALUE )
  817. {
  818. CloseHandle( hFile );
  819. }
  820. }
  821. else
  822. {
  823. // remove marker
  824. DeleteFile( mrkFilename );
  825. DeleteFile( g_installData.m_ppDstFiles[i] );
  826. // errors can't stop install
  827. // snap progress to expected completion
  828. g_copyStats.m_bytesCopied = bytesCopied + g_installData.m_pDstFileSizes[i];
  829. }
  830. }
  831. g_installElapsedTime = GetTickCount() - g_installStartTime;
  832. // finished loading
  833. *(DWORD*)lpParam = 0;
  834. return 0;
  835. }
  836. //-----------------------------------------------------------------------------
  837. // Verify disk space
  838. //-----------------------------------------------------------------------------
  839. bool CXBoxLoader::VerifyInstall( void )
  840. {
  841. memset( &g_copyStats, 0, sizeof( CopyStats_t ) );
  842. LoadLogFile();
  843. if ( !LoadInstallScript() )
  844. {
  845. return false;
  846. }
  847. return true;
  848. }
  849. //-----------------------------------------------------------------------------
  850. // Look for possible forensic log file
  851. //-----------------------------------------------------------------------------
  852. void CXBoxLoader::LoadLogFile( void )
  853. {
  854. #if defined( XBOX_FORENSIC_LOG )
  855. HRESULT hr;
  856. char *pFileData = NULL;
  857. DWORD fileSize = 0;
  858. hr = XBUtil_LoadFile( "Z:\\hl2fatal.log", (void**)&pFileData, &fileSize );
  859. if ( hr != S_OK || !fileSize )
  860. {
  861. return;
  862. }
  863. // copy and null terminate
  864. m_pLogData = (char *)malloc( fileSize+1 );
  865. int j = 0;
  866. for (int i=0; i<(int)fileSize; i++)
  867. {
  868. if ( pFileData[i] == 0x0D )
  869. continue;
  870. m_pLogData[j++] = pFileData[i];
  871. }
  872. m_pLogData[j] = '\0';
  873. free( pFileData );
  874. #endif
  875. }
  876. //-----------------------------------------------------------------------------
  877. // Starts installation to disk
  878. //-----------------------------------------------------------------------------
  879. bool CXBoxLoader::StartInstall( void )
  880. {
  881. // Start the install thread
  882. m_installThread = CreateThread( NULL, 0, &InstallThreadFunc, &m_dwLoading, 0, 0 );
  883. if ( !m_installThread )
  884. {
  885. // failed
  886. return false;
  887. }
  888. // success
  889. return true;
  890. }
  891. //-----------------------------------------------------------------------------
  892. // Shows the legal text
  893. //-----------------------------------------------------------------------------
  894. void CXBoxLoader::StartLegalScreen( int legal )
  895. {
  896. m_bDrawLegal = true;
  897. m_LegalTime = GetTickCount();
  898. m_LegalStartTime = 0;
  899. switch ( legal )
  900. {
  901. case LEGAL_MAIN:
  902. m_pLegalTexture = m_pMainLegalTexture;
  903. break;
  904. case LEGAL_SOURCE:
  905. m_pLegalTexture = m_pSourceLegalTexture;
  906. break;
  907. }
  908. }
  909. //-----------------------------------------------------------------------------
  910. // DrawLegals
  911. //-----------------------------------------------------------------------------
  912. void CXBoxLoader::DrawLegals()
  913. {
  914. unsigned int color;
  915. float t;
  916. if ( !m_bDrawLegal )
  917. return;
  918. if ( !m_LegalStartTime )
  919. {
  920. m_LegalStartTime = GetTickCount();
  921. }
  922. // fade legals
  923. t = (float)(GetTickCount() - m_LegalStartTime)/LEGAL_DISPLAY_TIME;
  924. if ( t < 0.1f )
  925. {
  926. // fade up
  927. color = LerpColor( 0xFF000000, 0xFFFFFFFF, t*10.0f );
  928. }
  929. else if ( t < 0.9f )
  930. {
  931. // hold
  932. color = 0xFFFFFFFF;
  933. }
  934. else
  935. {
  936. // fade out
  937. color = LerpColor( 0xFFFFFFFF, 0xFF000000, (t-0.9f)*10.0f );
  938. }
  939. DrawTexture( m_pLegalTexture, 0, 0, 640, 480, color );
  940. }
  941. //-----------------------------------------------------------------------------
  942. // DrawSlideshow
  943. //-----------------------------------------------------------------------------
  944. void CXBoxLoader::DrawSlideshow()
  945. {
  946. float t;
  947. if ( !m_bDrawSlideShow )
  948. return;
  949. if ( !m_SlideShowStartTime )
  950. {
  951. m_SlideShowStartTime = GetTickCount();
  952. m_SlideShowCount = -1;
  953. m_bFinalSlide = false;
  954. }
  955. if ( !m_bInstallComplete && ( GetTickCount() - m_SlideShowStartTime > SLIDESHOW_SLIDETIME ) )
  956. {
  957. // next slide
  958. m_SlideShowCount++;
  959. m_SlideShowStartTime = GetTickCount();
  960. }
  961. t = ( GetTickCount() - m_SlideShowStartTime )/(float)SLIDESHOW_FLIPTIME;
  962. if ( t >= 1.0f )
  963. t = 1.0f;
  964. if ( m_bInstallComplete && !m_bFinalSlide && t >= 1.0f )
  965. {
  966. // wait for current slide to complete
  967. // final slide must transition back to transition screen
  968. m_SlideShowStartTime = GetTickCount();
  969. m_bFinalSlide = true;
  970. t = 0;
  971. }
  972. if ( !m_bFinalSlide )
  973. {
  974. // fade next slide in
  975. unsigned int fadeInColor = LerpColor( 0x00FFFFFF, 0xFFFFFFFF, t );
  976. if ( fadeInColor != 0xFFFFFFFF && m_SlideShowCount != -1 )
  977. DrawTexture( m_pSlideShowTextures[m_SlideShowCount % MAX_SLIDESHOW_TEXTURES], 0, 0, 640, 480, 0xFFFFFFFF );
  978. DrawTexture( m_pSlideShowTextures[(m_SlideShowCount + 1) % MAX_SLIDESHOW_TEXTURES], 0, 0, 640, 480, fadeInColor );
  979. }
  980. else
  981. {
  982. // fade last slide out
  983. unsigned int fadeInColor = LerpColor( 0xFFFFFFFF, 0x00FFFFFF, t );
  984. DrawTexture( m_pSlideShowTextures[(m_SlideShowCount + 1) % MAX_SLIDESHOW_TEXTURES], 0, 0, 640, 480, fadeInColor );
  985. }
  986. if ( m_bInstallComplete && m_bFinalSlide && t >= 1.0f )
  987. {
  988. // end of slideshow
  989. m_bDrawSlideShow = false;
  990. }
  991. }
  992. //-----------------------------------------------------------------------------
  993. // DrawDebug
  994. //-----------------------------------------------------------------------------
  995. void CXBoxLoader::DrawDebug()
  996. {
  997. #ifndef _RETAIL
  998. if ( !m_bDrawDebug )
  999. return;
  1000. DrawRect( 0, 0, 640, 480, 0xC0000000 );
  1001. m_Font.Begin();
  1002. m_Font.SetScaleFactors( 0.8f, 0.8f );
  1003. int xPos = SCREEN_WIDTH/2;
  1004. int yPos = SCREEN_HEIGHT/4;
  1005. float rate;
  1006. wchar_t textBuffer[256];
  1007. swprintf( textBuffer, L"Version: %d", m_Version );
  1008. m_Font.DrawText( 40, 40, 0xffffffff, textBuffer, 0 );
  1009. wchar_t srcFilename[MAX_PATH];
  1010. wchar_t dstFilename[MAX_PATH];
  1011. ConvertToWideString( srcFilename, g_copyStats.m_srcFilename );
  1012. ConvertToWideString( dstFilename, g_copyStats.m_dstFilename );
  1013. swprintf( textBuffer, L"From: %s (%.2f MB)", srcFilename, (float)g_copyStats.m_readSize/(1024.0f*1024.0f) );
  1014. m_Font.DrawText( xPos, yPos + 20, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1015. swprintf( textBuffer, L"To: %s (%.2f MB)", dstFilename, (float)g_copyStats.m_writeSize/(1024.0f*1024.0f) );
  1016. m_Font.DrawText( xPos, yPos + 40, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1017. if ( g_copyStats.m_bufferReadTime && m_dwLoading )
  1018. rate = ( g_copyStats.m_bufferReadSize/(1024.0f*1024.0f) ) / ( g_copyStats.m_bufferReadTime * 0.001f );
  1019. else
  1020. rate = 0;
  1021. swprintf( textBuffer, L"Buffer Read: %.2f MB (%.2f MB/s) (%d)", g_copyStats.m_bufferReadSize/(1024.0f*1024.0f), rate, g_copyStats.m_numReadBuffers );
  1022. m_Font.DrawText( xPos, yPos + 80, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1023. rate = g_copyStats.m_inflateTime && m_dwLoading ? (float)g_copyStats.m_inflateSize/(g_copyStats.m_inflateTime * 0.001f) : 0;
  1024. swprintf( textBuffer, L"Inflate: %.2f MB (%.2f MB/s)", g_copyStats.m_inflateSize/(1024.0f*1024.0f), rate/(1024.0f*1024.0f) );
  1025. m_Font.DrawText( xPos, yPos + 100, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1026. if ( g_copyStats.m_bufferWriteTime && m_dwLoading )
  1027. rate = ( g_copyStats.m_bufferWriteSize/(1024.0f*1024.0f) ) / ( g_copyStats.m_bufferWriteTime * 0.001f );
  1028. else
  1029. rate = 0;
  1030. swprintf( textBuffer, L"Buffer Write: %.2f MB (%.2f MB/s) (%d)", g_copyStats.m_bufferWriteSize/(1024.0f*1024.0f), rate, g_copyStats.m_numWriteBuffers );
  1031. m_Font.DrawText( xPos, yPos + 120, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1032. rate = g_copyStats.m_totalReadTime && m_dwLoading ? (float)g_copyStats.m_totalReadSize/(g_copyStats.m_totalReadTime * 0.001f) : 0;
  1033. swprintf( textBuffer, L"Total Read: %d MB (%.2f MB/s)", g_copyStats.m_totalReadSize/(1024*1024), rate/(1024.0f*1024.0f) );
  1034. m_Font.DrawText( xPos, yPos + 160, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1035. rate = g_copyStats.m_totalWriteTime && m_dwLoading ? (float)g_copyStats.m_totalWriteSize/(g_copyStats.m_totalWriteTime * 0.001f) : 0;
  1036. swprintf( textBuffer, L"Total Write: %d MB (%.2f MB/s)", g_copyStats.m_totalWriteSize/(1024*1024), rate/(1024.0f*1024.0f) );
  1037. m_Font.DrawText( xPos, yPos + 180, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1038. float elapsed = (float)(GetTickCount() - g_installStartTime) * 0.001f;
  1039. if ( m_dwLoading )
  1040. {
  1041. if ( elapsed )
  1042. rate = g_copyStats.m_totalWriteSize/elapsed;
  1043. else
  1044. rate = 0;
  1045. }
  1046. else
  1047. {
  1048. if ( g_installElapsedTime )
  1049. rate = g_copyStats.m_totalWriteSize/(g_installElapsedTime * 0.001f);
  1050. else
  1051. rate = 0;
  1052. }
  1053. 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) );
  1054. m_Font.DrawText( xPos, yPos + 220, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1055. swprintf( textBuffer, L"Errors: %d", g_copyStats.m_copyErrors );
  1056. m_Font.DrawText( xPos, yPos + 240, 0xffffffff, textBuffer, XBFONT_CENTER_X );
  1057. m_Font.End();
  1058. #endif
  1059. }
  1060. void CXBoxLoader::DrawLog()
  1061. {
  1062. #if defined( XBOX_FORENSIC_LOG )
  1063. wchar_t textBuffer[1024];
  1064. int numChars;
  1065. if ( !m_pLogData )
  1066. return;
  1067. DrawRect( 0, 0, 640, 480, 0xC0000000 );
  1068. m_Font.Begin();
  1069. m_Font.SetScaleFactors( 0.8f, 0.8f );
  1070. char *pStart = m_pLogData;
  1071. char *pEnd = pStart;
  1072. int yPos = 40;
  1073. for (int i=0; i<20; i++)
  1074. {
  1075. pEnd = strstr( pStart, "\n" );
  1076. if ( !pEnd )
  1077. numChars = strlen( pStart );
  1078. else
  1079. numChars = pEnd-pStart;
  1080. if ( numChars )
  1081. {
  1082. for (int j=0; j<numChars; j++)
  1083. {
  1084. textBuffer[j] = pStart[j];
  1085. }
  1086. textBuffer[j] = 0;
  1087. m_Font.DrawText( 40, yPos, 0xffffffff, textBuffer, 0 );
  1088. }
  1089. if ( !pEnd )
  1090. break;
  1091. // next line
  1092. pStart = pEnd+1;
  1093. yPos += 10;
  1094. }
  1095. m_Font.End();
  1096. #endif
  1097. }
  1098. //-----------------------------------------------------------------------------
  1099. // DrawLoadingMarquee
  1100. //-----------------------------------------------------------------------------
  1101. void CXBoxLoader::DrawLoadingMarquee()
  1102. {
  1103. if ( !m_bDrawLoading )
  1104. return;
  1105. int y = 0.80f*480;
  1106. DrawTexture( m_pLoadingIconTexture, (640-64)/2, y-64, 64, 64, 0xFFFFFFFF );
  1107. // draw loading text
  1108. m_Font.Begin();
  1109. m_Font.SetScaleFactors( 0.8f, 0.8f );
  1110. m_Font.DrawText( 320, y, PROGRESS_TEXT_COLOR, GetLocalizedLoadingString(), XBFONT_CENTER_X );
  1111. m_Font.End();
  1112. }
  1113. //-----------------------------------------------------------------------------
  1114. // DrawProgressBar
  1115. //-----------------------------------------------------------------------------
  1116. void CXBoxLoader::DrawProgressBar()
  1117. {
  1118. if ( !m_bDrawProgress )
  1119. return;
  1120. if ( !m_LoadingBarStartTime )
  1121. {
  1122. m_LoadingBarStartTime = GetTickCount();
  1123. }
  1124. // slide the loading bar up
  1125. float tUp = (float)(GetTickCount() - m_LoadingBarStartTime)/LOADINGBAR_UPTIME;
  1126. if ( tUp > 1.0f)
  1127. tUp = 1.0f;
  1128. float y = 480.0f + tUp*((float)PROGRESS_Y - 480.0f);
  1129. float t0 = 0;
  1130. float t1 = 0;
  1131. int numSegments = 0;
  1132. if ( tUp == 1.0f )
  1133. {
  1134. // loading bar is up
  1135. // don't snap, animate progress to current level of completion
  1136. t0 = (float)g_copyStats.m_bytesCopied/(float)g_installData.m_totalSize;
  1137. if ( t0 > 1.0f )
  1138. t0 = 1.0f;
  1139. t1 = (float)(GetTickCount() - m_LoadingBarStartTime - LOADINGBAR_WAITTIME)/LOADINGBAR_SLIDETIME;
  1140. if ( t1 < 0.0f )
  1141. t1 = 0.0f;
  1142. else if ( t1 > 1.0f)
  1143. t1 = 1.0f;
  1144. numSegments = t0 * t1 * (float)SEGMENT_COUNT;
  1145. }
  1146. #if 0
  1147. float tDown = 0;
  1148. if ( t0 == 1.0f && t1 == 1.0f && !m_dwLoading )
  1149. {
  1150. // loading anim and copying of data are finished
  1151. // slide the loading bar down
  1152. if ( !m_LoadingBarEndTime )
  1153. {
  1154. m_LoadingBarEndTime = GetTickCount();
  1155. }
  1156. tDown = (float)(GetTickCount() - m_LoadingBarEndTime - LOADINGBAR_WAITTIME)/LOADINGBAR_UPTIME;
  1157. if ( tDown < 0.0f )
  1158. tDown = 0.0f;
  1159. else if ( tDown > 1.0f)
  1160. tDown = 1.0f;
  1161. y = PROGRESS_Y + tDown*(480.0f - (float)PROGRESS_Y);
  1162. }
  1163. if ( tDown == 1.0f )
  1164. {
  1165. // loading bar is offscreen
  1166. m_bInstallComplete = true;
  1167. }
  1168. #else
  1169. if ( t0 == 1.0f && t1 == 1.0f && !m_dwLoading )
  1170. {
  1171. m_bInstallComplete = true;
  1172. }
  1173. #endif
  1174. int x = (640-FOOTER_W)/2;
  1175. DrawTexture( m_pFooterTexture, x, y, FOOTER_W, 480 - PROGRESS_Y, PROGRESS_FOOTER_COLOR );
  1176. x += FOOTER_W - 35;
  1177. // draw left justified loading text
  1178. m_Font.Begin();
  1179. m_Font.SetScaleFactors( 0.8f, 0.8f );
  1180. int textWidth = m_Font.GetTextWidth( GetLocalizedLoadingString() );
  1181. x -= SEGMENT_W + textWidth;
  1182. m_Font.DrawText( x, y+20, PROGRESS_TEXT_COLOR, GetLocalizedLoadingString(), XBFONT_LEFT );
  1183. m_Font.End();
  1184. // draw progess bar
  1185. x -= SEGMENT_W + PROGRESS_W;
  1186. DrawRect( x, y+25, PROGRESS_W, PROGRESS_H, PROGRESS_INSET_COLOR );
  1187. for ( int i =0; i<numSegments; i++ )
  1188. {
  1189. DrawRect( x, y+25+2, SEGMENT_W, PROGRESS_H-4, PROGRESS_SEGMENT_COLOR );
  1190. x += SEGMENT_W+SEGMENT_GAP;
  1191. }
  1192. }
  1193. //-----------------------------------------------------------------------------
  1194. // Name: PlayVideoFrame()
  1195. // Desc: Plays one frame of video if a movie is currently open and if there is
  1196. // a frame available. This function is safe to call at any time.
  1197. //-----------------------------------------------------------------------------
  1198. BOOL CXBoxLoader::PlayVideoFrame()
  1199. {
  1200. if ( !m_player.IsPlaying() )
  1201. return FALSE;
  1202. const FLOAT fMovieWidth = FLOAT( m_player.GetWidth() );
  1203. const FLOAT fMovieHeight = FLOAT( m_player.GetHeight() );
  1204. // Move to the next frame.
  1205. LPDIRECT3DTEXTURE8 pTexture = 0;
  1206. pTexture = m_player.AdvanceFrameForTexturing( m_pd3dDevice );
  1207. // See if the movie is over now.
  1208. if ( !m_player.IsPlaying() )
  1209. {
  1210. if ( m_bCaptureLastMovieFrame )
  1211. {
  1212. m_bCaptureLastMovieFrame = false;
  1213. // Copy Texture
  1214. if ( m_pLastMovieFrame )
  1215. {
  1216. m_pLastMovieFrame->Release();
  1217. m_pLastMovieFrame = NULL;
  1218. }
  1219. if ( pTexture )
  1220. {
  1221. // copy the last frame
  1222. D3DSURFACE_DESC d3dSurfaceDesc;
  1223. D3DLOCKED_RECT srcRect;
  1224. D3DLOCKED_RECT dstRect;
  1225. pTexture->GetLevelDesc( 0, &d3dSurfaceDesc );
  1226. m_pd3dDevice->CreateTexture( d3dSurfaceDesc.Width, d3dSurfaceDesc.Height, 0, 0, d3dSurfaceDesc.Format, 0, &m_pLastMovieFrame );
  1227. pTexture->LockRect( 0, &srcRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE );
  1228. m_pLastMovieFrame->LockRect( 0, &dstRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE );
  1229. memcpy( dstRect.pBits, srcRect.pBits, srcRect.Pitch*d3dSurfaceDesc.Height );
  1230. }
  1231. }
  1232. // Clean up the movie, then return.
  1233. m_player.Destroy();
  1234. return FALSE;
  1235. }
  1236. // If no texture is ready, return TRUE to indicate that a movie is playing,
  1237. // but don't render anything yet.
  1238. if ( !pTexture )
  1239. return TRUE;
  1240. const FLOAT fSizeY = 480.0f;
  1241. const FLOAT fOriginX = 320.0f - ( fSizeY * .5f * fMovieWidth / fMovieHeight );
  1242. const FLOAT fOriginY = 240.0f - fSizeY * .5f;
  1243. // Draw the texture.
  1244. m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  1245. m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
  1246. m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  1247. // Draw the texture as a quad.
  1248. m_pd3dDevice->SetTexture( 0, pTexture );
  1249. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  1250. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1251. // Wrapping isn't allowed on linear textures.
  1252. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
  1253. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
  1254. FLOAT fLeft = fOriginX + 0.5f;
  1255. FLOAT fRight = fOriginX + ( fSizeY * fMovieWidth) / fMovieHeight - 0.5f;
  1256. FLOAT fTop = fOriginY + 0.5f;
  1257. FLOAT fBottom = fOriginY + fSizeY - 0.5f;
  1258. // On linear textures the texture coordinate range is from 0,0 to width,height, instead
  1259. // of 0,0 to 1,1.
  1260. m_pd3dDevice->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1 );
  1261. m_pd3dDevice->Begin( D3DPT_QUADLIST );
  1262. m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, 0, fMovieHeight );
  1263. m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fLeft, fBottom, 0.0f, 1.0f );
  1264. m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, 0, 0 );
  1265. m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fLeft, fTop, 0.0f, 1.0f );
  1266. m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, fMovieWidth, 0 );
  1267. m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fRight, fTop, 0.0f, 1.0f );
  1268. m_pd3dDevice->SetVertexData2f( D3DVSDE_TEXCOORD0, fMovieWidth, fMovieHeight );
  1269. m_pd3dDevice->SetVertexData4f( D3DVSDE_VERTEX, fRight, fBottom, 0.0f, 1.0f );
  1270. m_pd3dDevice->End();
  1271. return TRUE;
  1272. }
  1273. //-----------------------------------------------------------------------------
  1274. // LaunchHL2
  1275. //-----------------------------------------------------------------------------
  1276. void CXBoxLoader::LaunchHL2( unsigned int contextCode )
  1277. {
  1278. LAUNCH_DATA launchData;
  1279. RelaunchHeader_t *pRelaunch;
  1280. const char *pHL2Name;
  1281. memset( &launchData, 0, sizeof( LAUNCH_DATA ) );
  1282. // build the relaunch structure that HL2 uses
  1283. pRelaunch = GetRelaunchHeader( launchData.Data );
  1284. pRelaunch->magicNumber = RELAUNCH_MAGIC_NUMBER;
  1285. pRelaunch->nBytesRelaunchData = 0;
  1286. if ( ( contextCode & CONTEXTCODE_MAGICMASK ) == CONTEXTCODE_HL2MAGIC )
  1287. {
  1288. // ok to re-establish persistent data
  1289. pRelaunch->bRetail = (contextCode & CONTEXTCODE_RETAIL_MODE) > 0;
  1290. pRelaunch->bInDebugger = (contextCode & CONTEXTCODE_INDEBUGGER) > 0;
  1291. }
  1292. else
  1293. {
  1294. // ensure we launch under retail conditions
  1295. contextCode = CONTEXTCODE_NO_XBDM;
  1296. g_activeDevice = -1;
  1297. pRelaunch->bRetail = true;
  1298. pRelaunch->bInDebugger = false;
  1299. }
  1300. pRelaunch->contextCode = contextCode;
  1301. pRelaunch->activeDevice = g_activeDevice;
  1302. pRelaunch->startTime = g_loaderStartTime;
  1303. // launch the xbe that is expected
  1304. if ( contextCode & CONTEXTCODE_DEBUG_XBE )
  1305. {
  1306. // debug xbe
  1307. pHL2Name = "D:\\hl2d_xbox.xbe";
  1308. }
  1309. else if ( contextCode & CONTEXTCODE_RELEASE_XBE )
  1310. {
  1311. // release xbe
  1312. pHL2Name = "D:\\hl2r_xbox.xbe";
  1313. }
  1314. else
  1315. {
  1316. // default launch to retail xbe
  1317. pHL2Name = "D:\\hl2_xbox.xbe";
  1318. }
  1319. XLaunchNewImage( pHL2Name, &launchData );
  1320. // failed
  1321. FatalMediaError();
  1322. }
  1323. //-----------------------------------------------------------------------------
  1324. // Performs initialization
  1325. //-----------------------------------------------------------------------------
  1326. HRESULT CXBoxLoader::Initialize()
  1327. {
  1328. DWORD launchType;
  1329. LAUNCH_DATA launchData;
  1330. // no active device until set
  1331. g_activeDevice = -1;
  1332. // get launch info and command line params needed for early setting of systems
  1333. LPSTR pCmdLine = "";
  1334. DWORD retVal = XGetLaunchInfo( &launchType, &launchData );
  1335. if ( retVal == ERROR_SUCCESS )
  1336. {
  1337. if ( launchType == LDT_FROM_DASHBOARD )
  1338. {
  1339. // launched from dashboard
  1340. LD_FROM_DASHBOARD *pLaunchFromDashboard = (LD_FROM_DASHBOARD *)(&launchData);
  1341. m_contextCode = pLaunchFromDashboard->dwContext;
  1342. }
  1343. else if ( launchType == LDT_TITLE )
  1344. {
  1345. // launched directly from HL2 to do something
  1346. LAUNCH_DATA* pLaunchData = (LAUNCH_DATA *)(&launchData);
  1347. pCmdLine = (char *)pLaunchData->Data;
  1348. RelaunchHeader_t *pHeader = GetRelaunchHeader( pLaunchData->Data );
  1349. if ( pHeader->magicNumber == RELAUNCH_MAGIC_NUMBER )
  1350. {
  1351. m_contextCode = pHeader->contextCode;
  1352. g_activeDevice = pHeader->activeDevice;
  1353. }
  1354. }
  1355. else if ( launchType == LDT_FROM_DEBUGGER_CMDLINE )
  1356. {
  1357. // launched from the debugger
  1358. LAUNCH_DATA* pLaunchData = (LAUNCH_DATA *)(&launchData);
  1359. pCmdLine = (char *)pLaunchData->Data;
  1360. strlwr( pCmdLine );
  1361. // assume retail mode
  1362. m_contextCode |= CONTEXTCODE_HL2MAGIC;
  1363. m_contextCode |= CONTEXTCODE_RETAIL_MODE;
  1364. if ( strstr( pCmdLine, "-indebugger" ) )
  1365. {
  1366. m_contextCode |= CONTEXTCODE_INDEBUGGER;
  1367. }
  1368. #ifndef _RETAIL
  1369. if ( DmIsDebuggerPresent() )
  1370. {
  1371. m_contextCode |= CONTEXTCODE_INDEBUGGER;
  1372. }
  1373. #endif
  1374. if ( strstr( pCmdLine, "-debug" ) )
  1375. {
  1376. // launch to debug xbe
  1377. m_contextCode |= CONTEXTCODE_DEBUG_XBE;
  1378. }
  1379. else if ( strstr( pCmdLine, "-release" ) )
  1380. {
  1381. // launch to release xbe
  1382. m_contextCode |= CONTEXTCODE_RELEASE_XBE;
  1383. }
  1384. else
  1385. {
  1386. // default launch to retail xbe
  1387. m_contextCode |= CONTEXTCODE_RETAIL_XBE|CONTEXTCODE_NO_XBDM;
  1388. if ( strstr( pCmdLine, "-dev" ) )
  1389. {
  1390. // force dev link
  1391. m_contextCode &= ~CONTEXTCODE_NO_XBDM;
  1392. }
  1393. }
  1394. if ( strstr( pCmdLine, "-attract" ) )
  1395. {
  1396. // running the attract sequence
  1397. m_contextCode |= CONTEXTCODE_ATTRACT;
  1398. }
  1399. }
  1400. }
  1401. if ( ( m_contextCode & CONTEXTCODE_MAGICMASK ) != CONTEXTCODE_HL2MAGIC )
  1402. {
  1403. // unknown, run the install normally
  1404. // 0 is a special indicator, due to lack of valid magic
  1405. m_contextCode = 0;
  1406. }
  1407. else
  1408. {
  1409. if ( m_contextCode & CONTEXTCODE_DASHBOARD )
  1410. {
  1411. // coming from dashboard, back to HL2 - immediately!
  1412. LaunchHL2( m_contextCode );
  1413. return S_OK;
  1414. }
  1415. }
  1416. if ( FAILED( XFONT_OpenDefaultFont( &m_pDefaultTrueTypeFont ) ) )
  1417. {
  1418. return XBAPPERR_MEDIANOTFOUND;
  1419. }
  1420. // load install resources for context
  1421. // Load resource file
  1422. if ( FAILED( m_xprResource.Create( "D:\\LoaderMedia\\loader.xpr" ) ) )
  1423. {
  1424. return XBAPPERR_MEDIANOTFOUND;
  1425. }
  1426. if ( FAILED( LoadFont( &m_Font, loader_Font_OFFSET ) ) )
  1427. {
  1428. return XBAPPERR_MEDIANOTFOUND;
  1429. }
  1430. if ( !( m_contextCode & CONTEXTCODE_ATTRACT ) )
  1431. {
  1432. m_pFooterTexture = LoadTexture( loader_Footer_OFFSET );
  1433. if ( !m_pFooterTexture )
  1434. {
  1435. return XBAPPERR_MEDIANOTFOUND;
  1436. }
  1437. switch( XGetLanguage() )
  1438. {
  1439. case XC_LANGUAGE_FRENCH:
  1440. m_pMainLegalTexture = LoadTexture( loader_MainLegal_french_OFFSET );
  1441. break;
  1442. case XC_LANGUAGE_ITALIAN:
  1443. m_pMainLegalTexture = LoadTexture( loader_MainLegal_italian_OFFSET );
  1444. break;
  1445. case XC_LANGUAGE_GERMAN:
  1446. m_pMainLegalTexture = LoadTexture( loader_MainLegal_german_OFFSET );
  1447. break;
  1448. case XC_LANGUAGE_SPANISH:
  1449. m_pMainLegalTexture = LoadTexture( loader_MainLegal_spanish_OFFSET );
  1450. break;
  1451. default:
  1452. m_pMainLegalTexture = LoadTexture( loader_MainLegal_english_OFFSET );
  1453. break;
  1454. }
  1455. if ( !m_pMainLegalTexture )
  1456. {
  1457. return XBAPPERR_MEDIANOTFOUND;
  1458. }
  1459. m_pSourceLegalTexture = LoadTexture( loader_SourceLegal_OFFSET );
  1460. if ( !m_pSourceLegalTexture )
  1461. {
  1462. return XBAPPERR_MEDIANOTFOUND;
  1463. }
  1464. switch( XGetLanguage() )
  1465. {
  1466. case XC_LANGUAGE_FRENCH:
  1467. m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_french_OFFSET );
  1468. break;
  1469. case XC_LANGUAGE_ITALIAN:
  1470. m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_italian_OFFSET );
  1471. break;
  1472. case XC_LANGUAGE_GERMAN:
  1473. m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_german_OFFSET );
  1474. break;
  1475. case XC_LANGUAGE_SPANISH:
  1476. m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_spanish_OFFSET );
  1477. break;
  1478. default:
  1479. m_pSlideShowTextures[0] = LoadTexture( loader_SlideShow1_english_OFFSET );
  1480. break;
  1481. }
  1482. m_pSlideShowTextures[1] = LoadTexture( loader_SlideShow2_OFFSET );
  1483. m_pSlideShowTextures[2] = LoadTexture( loader_SlideShow3_OFFSET );
  1484. m_pSlideShowTextures[3] = LoadTexture( loader_SlideShow4_OFFSET );
  1485. m_pSlideShowTextures[4] = LoadTexture( loader_SlideShow5_OFFSET );
  1486. m_pSlideShowTextures[5] = LoadTexture( loader_SlideShow6_OFFSET );
  1487. m_pSlideShowTextures[6] = LoadTexture( loader_SlideShow7_OFFSET );
  1488. m_pSlideShowTextures[7] = LoadTexture( loader_SlideShow8_OFFSET );
  1489. m_pSlideShowTextures[8] = LoadTexture( loader_SlideShow9_OFFSET );
  1490. for ( int i=0; i<MAX_SLIDESHOW_TEXTURES; i++ )
  1491. {
  1492. if ( !m_pSlideShowTextures )
  1493. return XBAPPERR_MEDIANOTFOUND;
  1494. }
  1495. if ( !VerifyInstall() )
  1496. {
  1497. OUTPUT_DEBUG_STRING( "Install failed!\n" );
  1498. return -1;
  1499. }
  1500. }
  1501. m_pLoadingIconTexture = LoadTexture( loader_LoadingIcon_OFFSET );
  1502. if ( !m_pLoadingIconTexture )
  1503. {
  1504. return XBAPPERR_MEDIANOTFOUND;
  1505. }
  1506. return S_OK;
  1507. }
  1508. //-----------------------------------------------------------------------------
  1509. // Performs per-frame video checks
  1510. //-----------------------------------------------------------------------------
  1511. void CXBoxLoader::TickVideo()
  1512. {
  1513. if ( m_bMovieErrorIsFatal && m_player.IsFailed() )
  1514. {
  1515. FatalMediaError();
  1516. }
  1517. }
  1518. //-----------------------------------------------------------------------------
  1519. // Performs per-frame updates
  1520. //-----------------------------------------------------------------------------
  1521. HRESULT CXBoxLoader::FrameMove()
  1522. {
  1523. bool bFailed = false;
  1524. TickVideo();
  1525. if ( m_State >= 10 && g_copyStats.m_copyErrors )
  1526. {
  1527. FatalMediaError();
  1528. }
  1529. if ( m_State >= 10 && ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_START ) )
  1530. {
  1531. m_bDrawDebug ^= 1;
  1532. }
  1533. if ( m_bAllowAttractAbort && ( m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A] || ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_START ) ) )
  1534. {
  1535. StopVideo();
  1536. // allow only once, until reset
  1537. m_bAllowAttractAbort = false;
  1538. }
  1539. switch ( m_State )
  1540. {
  1541. case 0:
  1542. if ( m_contextCode & CONTEXTCODE_ATTRACT )
  1543. {
  1544. // play attract mode
  1545. m_State = 1;
  1546. }
  1547. else
  1548. {
  1549. // normal installation
  1550. m_State = 9;
  1551. }
  1552. break;
  1553. case 1:
  1554. // Play the attract video
  1555. if ( FAILED( StartVideo( "D:\\LoaderMedia\\Demo_Attract.xmv", false, false ) ) )
  1556. {
  1557. // jump to finish
  1558. m_State = 4;
  1559. }
  1560. else
  1561. {
  1562. m_State = 2;
  1563. }
  1564. break;
  1565. case 2:
  1566. if ( m_player.IsPlaying() || m_player.IsFailed() )
  1567. {
  1568. // attract is playing, wait for finish
  1569. m_State = 3;
  1570. m_bAllowAttractAbort = true;
  1571. }
  1572. break;
  1573. case 3:
  1574. if ( !m_player.IsPlaying() || m_player.IsFailed() )
  1575. {
  1576. // attract is over or aborted
  1577. m_State = 4;
  1578. }
  1579. break;
  1580. case 4:
  1581. // place loading
  1582. m_bDrawLoading = true;
  1583. m_FrameCounter = 0;
  1584. m_State = 5;
  1585. break;
  1586. case 5:
  1587. // wait for two frames to pass to ensure loading is rendered
  1588. if ( m_FrameCounter > 2 )
  1589. {
  1590. m_bLaunch = true;
  1591. m_State = 6;
  1592. }
  1593. break;
  1594. case 6:
  1595. // idle
  1596. m_State = 6;
  1597. break;
  1598. case 9:
  1599. // Play the opening Valve video
  1600. StartVideo( "D:\\LoaderMedia\\Valve_Leader.xmv", true, true );
  1601. // Start the async installation process
  1602. if ( !StartInstall() )
  1603. {
  1604. OUTPUT_DEBUG_STRING( "Install failed!\n" );
  1605. bFailed = true;
  1606. break;
  1607. }
  1608. m_State = 10;
  1609. break;
  1610. case 10:
  1611. if ( m_player.IsPlaying() )
  1612. {
  1613. // intro is playing, wait for finish
  1614. m_State = 15;
  1615. }
  1616. break;
  1617. case 15:
  1618. if ( !m_player.IsPlaying() )
  1619. {
  1620. // intro is over
  1621. m_State = 20;
  1622. }
  1623. break;
  1624. case 20:
  1625. // start legals
  1626. StartLegalScreen( LEGAL_SOURCE );
  1627. m_State = 25;
  1628. break;
  1629. case 25:
  1630. if ( m_bDrawLegal && GetTickCount() - m_LegalTime > LEGAL_DISPLAY_TIME )
  1631. {
  1632. // advance to next legal
  1633. StartLegalScreen( LEGAL_MAIN );
  1634. m_State = 30;
  1635. }
  1636. break;
  1637. case 30:
  1638. if ( m_bDrawLegal && GetTickCount() - m_LegalTime > LEGAL_DISPLAY_TIME )
  1639. {
  1640. // end of all legals
  1641. if ( IsTargetFileValid( "Z:\\LoaderMedia\\Title_Load.xmv", 0 ) )
  1642. {
  1643. m_bDrawLegal = false;
  1644. m_State = 40;
  1645. }
  1646. }
  1647. break;
  1648. case 40:
  1649. // play the gordon/alyx hl2 game movie
  1650. m_bCaptureLastMovieFrame = true;
  1651. StartVideo( "Z:\\LoaderMedia\\Title_Load.xmv", true, true );
  1652. m_State = 50;
  1653. break;
  1654. case 50:
  1655. if ( m_player.IsPlaying() )
  1656. {
  1657. // title movie is playing, wait for finish
  1658. m_State = 60;
  1659. }
  1660. break;
  1661. case 60:
  1662. if ( m_player.GetElapsedTime() >= 8000 && !m_bDrawProgress )
  1663. {
  1664. // wait for known audio click, then put up progress bar
  1665. // start the loading bar animation
  1666. m_bDrawProgress = true;
  1667. }
  1668. if ( m_bInstallComplete && m_bDrawProgress )
  1669. {
  1670. // install has completed
  1671. if ( m_player.IsPlaying() )
  1672. {
  1673. // force the movie to end
  1674. m_player.TerminatePlayback();
  1675. }
  1676. m_State = 70;
  1677. }
  1678. else if ( !m_bInstallComplete && !m_player.IsPlaying() )
  1679. {
  1680. // intro movie has finished, but install is still running
  1681. // start up slideshow cycler
  1682. m_bDrawSlideShow = true;
  1683. m_State = 70;
  1684. }
  1685. break;
  1686. case 70:
  1687. // wait for movie or slideshow to stop
  1688. if ( !m_player.IsPlaying() && !m_bDrawSlideShow )
  1689. {
  1690. m_bLaunch = true;
  1691. m_State = 80;
  1692. }
  1693. break;
  1694. case 80:
  1695. // idle
  1696. break;
  1697. }
  1698. if ( bFailed )
  1699. {
  1700. FatalMediaError();
  1701. }
  1702. return S_OK;
  1703. }
  1704. //-----------------------------------------------------------------------------
  1705. // Renders the scene
  1706. //-----------------------------------------------------------------------------
  1707. HRESULT CXBoxLoader::Render()
  1708. {
  1709. m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0L );
  1710. // Play a frame from a video.
  1711. BOOL bPlayedFrame = PlayVideoFrame();
  1712. // hold the last frame of the title movie
  1713. if ( m_State >= 60 && !bPlayedFrame )
  1714. {
  1715. DrawTexture( m_pLastMovieFrame, 0, 0, 640, 480, 0xFFFFFFFF );
  1716. }
  1717. DrawSlideshow();
  1718. DrawLoadingMarquee();
  1719. DrawProgressBar();
  1720. DrawLegals();
  1721. DrawDebug();
  1722. DrawLog();
  1723. if ( m_bLaunch )
  1724. {
  1725. // The installation has finished
  1726. // Persist the image before launching hl2
  1727. m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  1728. m_pd3dDevice->PersistDisplay();
  1729. // Make sure the installation thread has completely exited
  1730. if ( m_installThread )
  1731. {
  1732. WaitForSingleObject( m_installThread, INFINITE );
  1733. CloseHandle( m_installThread );
  1734. }
  1735. LaunchHL2( m_contextCode );
  1736. return S_OK;
  1737. }
  1738. // Present the scene
  1739. m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  1740. m_FrameCounter++;
  1741. return S_OK;
  1742. }
  1743. //-----------------------------------------------------------------------------
  1744. // Entry point to the program.
  1745. //-----------------------------------------------------------------------------
  1746. VOID __cdecl main()
  1747. {
  1748. CXBoxLoader xbApp;
  1749. if ( FAILED( xbApp.Create() ) )
  1750. {
  1751. xbApp.FatalMediaError();
  1752. }
  1753. xbApp.Run();
  1754. }