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.

362 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "stdafx.h"
  7. #include "resource.h"
  8. #include "Splash.h"
  9. #define SPLASH_MIN_SHOW_TIME_MS 500
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include <tier0/memdbgon.h>
  12. // Sorry Tom... :(
  13. //#define HAMMER_TIME 1
  14. #ifdef HAMMER_TIME
  15. #include <io.h>
  16. #include <fcntl.h>
  17. #include <sys/stat.h>
  18. #include "StatusBarIDs.h"
  19. unsigned char g_CantTouchThis[] =
  20. {
  21. 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xF0, 0x4D, 0x54,
  22. 0x72, 0x6B, 0x00, 0x00, 0x00, 0x13, 0x00, 0xFF, 0x58, 0x04, 0x04, 0x02, 0x18, 0x08, 0x00, 0xFF,
  23. 0x51, 0x03, 0x06, 0xC8, 0x1C, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00,
  24. 0x6E, 0x00, 0xFF, 0x03, 0x05, 0x45, 0x20, 0x50, 0x6E, 0x6F, 0x00, 0xC1, 0x02, 0x84, 0x58, 0x91,
  25. 0x48, 0x39, 0x00, 0x4C, 0x43, 0x00, 0x51, 0x47, 0x3C, 0x48, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x51,
  26. 0x00, 0x3C, 0x48, 0x33, 0x00, 0x4C, 0x44, 0x00, 0x51, 0x48, 0x3C, 0x48, 0x00, 0x00, 0x4C, 0x00,
  27. 0x00, 0x51, 0x00, 0x82, 0x2C, 0x47, 0x2E, 0x00, 0x4A, 0x3B, 0x00, 0x4F, 0x3B, 0x3C, 0x47, 0x00,
  28. 0x00, 0x4A, 0x00, 0x00, 0x4F, 0x00, 0x3C, 0x47, 0x37, 0x00, 0x4A, 0x4B, 0x00, 0x4F, 0x46, 0x3C,
  29. 0x47, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x4F, 0x00, 0x82, 0x2C, 0x48, 0x3C, 0x00, 0x4C, 0x41, 0x00,
  30. 0x51, 0x39, 0x3C, 0x48, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x51, 0x00, 0x00, 0xFF, 0x2F, 0x00, 0x4D,
  31. 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x29, 0x00, 0xFF, 0x03, 0x0A, 0x4C, 0x65, 0x61, 0x64, 0x20,
  32. 0x73, 0x79, 0x6E, 0x74, 0x68, 0x00, 0xC0, 0x5A, 0x00, 0xB0, 0x01, 0x3C, 0x87, 0x40, 0x90, 0x53,
  33. 0x78, 0x81, 0x34, 0x53, 0x00, 0x81, 0x34, 0x54, 0x78, 0x78, 0x54, 0x00, 0x00, 0xFF, 0x2F, 0x00,
  34. 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x14, 0x00, 0xFF, 0x03, 0x09, 0x62, 0x61, 0x63, 0x20,
  35. 0x76, 0x6F, 0x63, 0x20, 0x32, 0x00, 0xC2, 0x5B, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B,
  36. 0x00, 0x00, 0x00, 0x14, 0x00, 0xFF, 0x03, 0x09, 0x62, 0x61, 0x6B, 0x20, 0x76, 0x6F, 0x63, 0x20,
  37. 0x31, 0x00, 0xC3, 0x55, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x45,
  38. 0x00, 0xFF, 0x03, 0x04, 0x62, 0x61, 0x73, 0x73, 0x00, 0xC4, 0x21, 0x10, 0x94, 0x32, 0x5E, 0x81,
  39. 0x71, 0x30, 0x58, 0x0F, 0x32, 0x00, 0x68, 0x2F, 0x57, 0x0A, 0x30, 0x00, 0x65, 0x2D, 0x60, 0x09,
  40. 0x2F, 0x00, 0x53, 0x2D, 0x00, 0x82, 0x04, 0x28, 0x62, 0x74, 0x28, 0x00, 0x08, 0x2B, 0x62, 0x7D,
  41. 0x2B, 0x00, 0x81, 0x71, 0x2F, 0x65, 0x81, 0x05, 0x2D, 0x66, 0x09, 0x2F, 0x00, 0x81, 0x21, 0x2D,
  42. 0x00, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0xFF, 0x03,
  43. 0x0F, 0x62, 0x61, 0x6B, 0x20, 0x76, 0x6F, 0x63, 0x20, 0x42, 0x72, 0x65, 0x61, 0x6B, 0x49, 0x74,
  44. 0x00, 0xC5, 0x55, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x14, 0x00,
  45. 0xFF, 0x03, 0x09, 0x62, 0x61, 0x6B, 0x20, 0x76, 0x6F, 0x63, 0x20, 0x32, 0x00, 0xC2, 0x55, 0x00,
  46. 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x13, 0x00, 0xFF, 0x03, 0x0B, 0x62,
  47. 0x72, 0x65, 0x61, 0x6B, 0x49, 0x74, 0x44, 0x6F, 0x77, 0x6E, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54,
  48. 0x72, 0x6B, 0x00, 0x00, 0x00, 0x13, 0x00, 0xFF, 0x03, 0x0B, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x49,
  49. 0x74, 0x44, 0x6F, 0x77, 0x6E, 0x00, 0xFF, 0x2F, 0x00, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00,
  50. 0xB1, 0x00, 0xFF, 0x03, 0x0C, 0x44, 0x72, 0x75, 0x6D, 0x20, 0x6D, 0x61, 0x63, 0x68, 0x69, 0x6E,
  51. 0x65, 0x00, 0x99, 0x2A, 0x43, 0x00, 0x24, 0x71, 0x78, 0x2A, 0x00, 0x00, 0x24, 0x00, 0x00, 0x2A,
  52. 0x51, 0x78, 0x2A, 0x00, 0x00, 0x27, 0x7F, 0x00, 0x39, 0x7F, 0x00, 0x2A, 0x5F, 0x78, 0x2A, 0x00,
  53. 0x00, 0x2A, 0x58, 0x00, 0x24, 0x68, 0x78, 0x27, 0x00, 0x00, 0x39, 0x00, 0x00, 0x2A, 0x00, 0x00,
  54. 0x24, 0x00, 0x00, 0x2A, 0x4D, 0x00, 0x24, 0x71, 0x78, 0x2A, 0x00, 0x00, 0x24, 0x00, 0x00, 0x2A,
  55. 0x5A, 0x78, 0x2A, 0x00, 0x00, 0x27, 0x7F, 0x00, 0x39, 0x7F, 0x00, 0x2A, 0x40, 0x78, 0x2A, 0x00,
  56. 0x00, 0x2A, 0x40, 0x78, 0x27, 0x00, 0x00, 0x39, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x2A, 0x47, 0x00,
  57. 0x24, 0x71, 0x78, 0x2A, 0x00, 0x00, 0x24, 0x00, 0x00, 0x2A, 0x4C, 0x78, 0x2A, 0x00, 0x00, 0x27,
  58. 0x7F, 0x00, 0x39, 0x7F, 0x00, 0x2A, 0x4C, 0x78, 0x2A, 0x00, 0x00, 0x2A, 0x50, 0x00, 0x24, 0x67,
  59. 0x78, 0x27, 0x00, 0x00, 0x39, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x24, 0x00, 0x00, 0x2A, 0x50, 0x00,
  60. 0x24, 0x73, 0x78, 0x2A, 0x00, 0x00, 0x24, 0x00, 0x00, 0x2A, 0x50, 0x78, 0x2A, 0x00, 0x00, 0xFF,
  61. 0x2F, 0x00
  62. };
  63. /////////////////////////////////////////////////////////////////////////////
  64. #include <mmsystem.h>
  65. int m_uiMIDIPlayerID = 0;
  66. void CloseMIDIPlayer()
  67. {
  68. // Close the MIDI player, if possible
  69. if (m_uiMIDIPlayerID != 0)
  70. {
  71. mciSendCommand(m_uiMIDIPlayerID, MCI_CLOSE, 0, NULL);
  72. m_uiMIDIPlayerID = 0;
  73. }
  74. }
  75. void PlayMIDISong(LPTSTR szMIDIFileName, BOOL bRestart)
  76. {
  77. // See if the MIDI player needs to be opened
  78. if (m_uiMIDIPlayerID == 0)
  79. {
  80. // Open the MIDI player by specifying the device and filename
  81. MCI_OPEN_PARMS mciOpenParms;
  82. mciOpenParms.lpstrDeviceType = "sequencer";
  83. mciOpenParms.lpstrElementName = szMIDIFileName;
  84. if (mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
  85. (DWORD)&mciOpenParms) == 0)
  86. // Get the ID for the MIDI player
  87. m_uiMIDIPlayerID = mciOpenParms.wDeviceID;
  88. else
  89. // There was a problem, so just return
  90. return;
  91. }
  92. // Restart the MIDI song, if necessary
  93. if (bRestart)
  94. {
  95. MCI_SEEK_PARMS mciSeekParms;
  96. if (mciSendCommand(m_uiMIDIPlayerID, MCI_SEEK, MCI_SEEK_TO_START,
  97. (DWORD)&mciSeekParms) != 0)
  98. // There was a problem, so close the MIDI player
  99. CloseMIDIPlayer();
  100. }
  101. // Play the MIDI song
  102. MCI_PLAY_PARMS mciPlayParms;
  103. if (mciSendCommand(m_uiMIDIPlayerID, MCI_PLAY, MCI_WAIT,
  104. (DWORD)&mciPlayParms) != 0)
  105. // There was a problem, so close the MIDI player
  106. CloseMIDIPlayer();
  107. }
  108. void CantTouchThisThread( void * )
  109. {
  110. int file = _open( "hamrtime.mid", _O_BINARY| _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE );
  111. if ( file != -1 )
  112. {
  113. AfxGetApp()->GetMainWnd()->SetWindowText( "Hammer time!" );
  114. SetStatusText(SBI_PROMPT, "Stop, Hammer time!");
  115. bool fPlay = ( _write( file, g_CantTouchThis, sizeof( g_CantTouchThis ) ) == sizeof( g_CantTouchThis ) );
  116. _close( file );
  117. PlayMIDISong("hamrtime.mid", false );
  118. CloseMIDIPlayer();
  119. _unlink( "hamrtime.mid" );
  120. SetStatusText(SBI_PROMPT, "You can't touch this");
  121. AfxGetApp()->GetMainWnd()->SetWindowText( "Hammer" );
  122. Sleep(1500);
  123. SetStatusText(SBI_PROMPT, "For Help, press F1");
  124. }
  125. }
  126. void CantTouchThis()
  127. {
  128. if ( !AfxGetApp()->GetProfileInt("General", "Hammer time", 0))
  129. {
  130. AfxGetApp()->WriteProfileInt("General", "Hammer time", 1);
  131. _beginthread( CantTouchThisThread, 0, NULL );
  132. }
  133. }
  134. #else
  135. #define CantTouchThis() ((void)0)
  136. #endif
  137. static CSplashWnd *s_pSplashWnd = NULL;
  138. static bool s_bShowSplashWnd = true;
  139. BEGIN_MESSAGE_MAP(CSplashWnd, CWnd)
  140. //{{AFX_MSG_MAP(CSplashWnd)
  141. ON_WM_CREATE()
  142. ON_WM_PAINT()
  143. ON_WM_TIMER()
  144. //}}AFX_MSG_MAP
  145. END_MESSAGE_MAP()
  146. //-----------------------------------------------------------------------------
  147. // Purpose:
  148. //-----------------------------------------------------------------------------
  149. CSplashWnd::CSplashWnd()
  150. {
  151. m_bHideRequested = false;
  152. m_bMinTimerExpired = false;
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Purpose:
  156. //-----------------------------------------------------------------------------
  157. CSplashWnd::~CSplashWnd()
  158. {
  159. // Clear the static window pointer.
  160. Assert(s_pSplashWnd == this);
  161. s_pSplashWnd = NULL;
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose:
  165. // Input : bEnable -
  166. //-----------------------------------------------------------------------------
  167. void CSplashWnd::EnableSplashScreen(bool bEnable)
  168. {
  169. s_bShowSplashWnd = bEnable;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Purpose:
  173. // Input : pParentWnd -
  174. //-----------------------------------------------------------------------------
  175. void CSplashWnd::ShowSplashScreen(CWnd* pParentWnd /*= NULL*/)
  176. {
  177. if (!s_bShowSplashWnd || s_pSplashWnd != NULL)
  178. return;
  179. // Allocate a new splash screen, and create the window.
  180. s_pSplashWnd = new CSplashWnd;
  181. if (s_pSplashWnd->Create(pParentWnd))
  182. {
  183. s_pSplashWnd->UpdateWindow();
  184. CantTouchThis();
  185. }
  186. else
  187. {
  188. delete s_pSplashWnd;
  189. }
  190. }
  191. //-----------------------------------------------------------------------------
  192. // Purpose: Called by the app to hide the splash screen.
  193. //-----------------------------------------------------------------------------
  194. void CSplashWnd::HideSplashScreen()
  195. {
  196. if (!s_pSplashWnd)
  197. return;
  198. // Only do the hide if we've been up for long enough. Otherwise, it'll be
  199. // done in the OnTimer callback.
  200. if (s_pSplashWnd->m_bMinTimerExpired)
  201. {
  202. s_pSplashWnd->DoHide();
  203. }
  204. else
  205. {
  206. s_pSplashWnd->m_bHideRequested = true;
  207. }
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Purpose: Guarantees that the splash screen stays up long enough to see.
  211. //-----------------------------------------------------------------------------
  212. void CSplashWnd::OnTimer(UINT nIDEvent)
  213. {
  214. m_bMinTimerExpired = true;
  215. KillTimer(nIDEvent);
  216. if (m_bHideRequested)
  217. {
  218. DoHide();
  219. }
  220. }
  221. //-----------------------------------------------------------------------------
  222. // Purpose:
  223. //-----------------------------------------------------------------------------
  224. void CSplashWnd::DoHide()
  225. {
  226. DestroyWindow();
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose:
  230. //-----------------------------------------------------------------------------
  231. BOOL CSplashWnd::PreTranslateAppMessage(MSG* pMsg)
  232. {
  233. if (s_pSplashWnd == NULL)
  234. return FALSE;
  235. // If we get a keyboard or mouse message, hide the splash screen.
  236. if (pMsg->message == WM_KEYDOWN ||
  237. pMsg->message == WM_SYSKEYDOWN ||
  238. pMsg->message == WM_LBUTTONDOWN ||
  239. pMsg->message == WM_RBUTTONDOWN ||
  240. pMsg->message == WM_MBUTTONDOWN ||
  241. pMsg->message == WM_NCLBUTTONDOWN ||
  242. pMsg->message == WM_NCRBUTTONDOWN ||
  243. pMsg->message == WM_NCMBUTTONDOWN)
  244. {
  245. s_pSplashWnd->HideSplashScreen();
  246. return TRUE; // message handled here
  247. }
  248. return FALSE; // message not handled
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose:
  252. // Input : pParentWnd -
  253. // Output : Returns TRUE on success, FALSE on failure.
  254. //-----------------------------------------------------------------------------
  255. BOOL CSplashWnd::Create(CWnd* pParentWnd /*= NULL*/)
  256. {
  257. if (!m_bitmap.LoadBitmap(IDB_SPLASH))
  258. return FALSE;
  259. BITMAP bm;
  260. m_bitmap.GetBitmap(&bm);
  261. return CreateEx(0,
  262. AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
  263. NULL, WS_POPUP | WS_VISIBLE, 0, 0, bm.bmWidth, bm.bmHeight, pParentWnd->GetSafeHwnd(), NULL);
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Purpose:
  267. //-----------------------------------------------------------------------------
  268. void CSplashWnd::PostNcDestroy()
  269. {
  270. delete this;
  271. }
  272. //-----------------------------------------------------------------------------
  273. // Purpose:
  274. //-----------------------------------------------------------------------------
  275. int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
  276. {
  277. if (CWnd::OnCreate(lpCreateStruct) == -1)
  278. return -1;
  279. // Center the window.
  280. CenterWindow();
  281. // set topmost
  282. SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
  283. SWP_NOREDRAW);
  284. // Set a timer to destroy the splash screen.
  285. SetTimer(1, SPLASH_MIN_SHOW_TIME_MS, NULL);
  286. return 0;
  287. }
  288. //-----------------------------------------------------------------------------
  289. // Purpose:
  290. //-----------------------------------------------------------------------------
  291. void CSplashWnd::OnPaint()
  292. {
  293. CPaintDC dc(this);
  294. CDC dcImage;
  295. if (!dcImage.CreateCompatibleDC(&dc))
  296. return;
  297. BITMAP bm;
  298. m_bitmap.GetBitmap(&bm);
  299. // Paint the image.
  300. CBitmap* pOldBitmap = dcImage.SelectObject(&m_bitmap);
  301. dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcImage, 0, 0, SRCCOPY);
  302. dcImage.SelectObject(pOldBitmap);
  303. }