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.

617 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: XBox win32 replacements - Mocks trivial windows flow
  4. //
  5. //=============================================================================//
  6. #include "pch_tier0.h"
  7. #include "xbox/xbox_win32stubs.h"
  8. #include "tier0/memdbgon.h"
  9. // On the 360, threads can run on any of 6 logical processors
  10. DWORD g_dwProcessAffinityMask = 0x3F;
  11. #define HWND_MAGIC 0x12345678
  12. struct xWndClass_t
  13. {
  14. char* pClassName;
  15. WNDPROC wndProc;
  16. xWndClass_t* pNext;
  17. };
  18. struct xWnd_t
  19. {
  20. xWndClass_t* pWndClass;
  21. int x;
  22. int y;
  23. int w;
  24. int h;
  25. long windowLongs[GWL_MAX];
  26. int show;
  27. int nMagic;
  28. xWnd_t* pNext;
  29. };
  30. static xWndClass_t* g_pWndClasses;
  31. static xWnd_t* g_pWnds;
  32. static HWND g_focusWindow;
  33. inline bool IsWndValid( HWND hWnd )
  34. {
  35. if ( !hWnd || ((xWnd_t*)hWnd)->nMagic != HWND_MAGIC )
  36. return false;
  37. return true;
  38. }
  39. int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
  40. {
  41. XBX_Error( lpText );
  42. Assert( 0 );
  43. return (0);
  44. }
  45. LONG GetWindowLong(HWND hWnd, int nIndex)
  46. {
  47. LONG oldLong;
  48. if ( !IsWndValid( hWnd ) )
  49. return 0;
  50. switch (nIndex)
  51. {
  52. case GWL_WNDPROC:
  53. case GWL_USERDATA:
  54. case GWL_STYLE:
  55. case GWL_EXSTYLE:
  56. oldLong = ((xWnd_t*)hWnd)->windowLongs[nIndex];
  57. break;
  58. default:
  59. // not implemented
  60. Assert( 0 );
  61. return 0;
  62. }
  63. return oldLong;
  64. }
  65. LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex)
  66. {
  67. UINT idx;
  68. switch ( nIndex )
  69. {
  70. case GWLP_WNDPROC:
  71. idx = GWL_WNDPROC;
  72. break;
  73. case GWLP_USERDATA:
  74. idx = GWL_USERDATA;
  75. break;
  76. default:
  77. // not implemented
  78. Assert(0);
  79. return 0;
  80. }
  81. return GetWindowLong( hWnd, idx );
  82. }
  83. LONG_PTR GetWindowLongPtrW(HWND hWnd, int nIndex)
  84. {
  85. AssertMsg( false, "GetWindowLongPtrW does not exist on Xbox 360." );
  86. return GetWindowLongPtr( hWnd, nIndex );
  87. }
  88. LONG SetWindowLong(HWND hWnd, int nIndex, LONG dwNewLong)
  89. {
  90. LONG oldLong;
  91. if ( !IsWndValid( hWnd ) )
  92. return 0;
  93. switch ( nIndex )
  94. {
  95. case GWL_WNDPROC:
  96. case GWL_USERDATA:
  97. case GWL_STYLE:
  98. oldLong = ((xWnd_t*)hWnd)->windowLongs[nIndex];
  99. ((xWnd_t*)hWnd)->windowLongs[nIndex] = dwNewLong;
  100. break;
  101. default:
  102. // not implemented
  103. Assert( 0 );
  104. return 0;
  105. }
  106. return oldLong;
  107. }
  108. LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
  109. {
  110. UINT idx;
  111. switch ( nIndex )
  112. {
  113. case GWLP_WNDPROC:
  114. idx = GWL_WNDPROC;
  115. break;
  116. case GWLP_USERDATA:
  117. idx = GWL_USERDATA;
  118. break;
  119. default:
  120. // not implemented
  121. Assert( 0 );
  122. return 0;
  123. }
  124. return SetWindowLong( hWnd, idx, dwNewLong );
  125. }
  126. LONG_PTR SetWindowLongPtrW(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
  127. {
  128. AssertMsg( false, "SetWindowLongPtrW does not exist on Xbox 360." );
  129. return SetWindowLongPtr( hWnd, nIndex, dwNewLong );
  130. }
  131. HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
  132. {
  133. // find classname
  134. xWndClass_t* pWndClass = g_pWndClasses;
  135. while ( pWndClass )
  136. {
  137. if ( !stricmp( lpClassName, pWndClass->pClassName ) )
  138. break;
  139. pWndClass = pWndClass->pNext;
  140. }
  141. if ( !pWndClass )
  142. {
  143. // no such class
  144. return (HWND)NULL;
  145. }
  146. // allocate and setup
  147. xWnd_t* pWnd = new xWnd_t;
  148. memset( pWnd, 0, sizeof(xWnd_t) );
  149. pWnd->pWndClass = pWndClass;
  150. pWnd->windowLongs[GWL_WNDPROC] = (LONG)pWndClass->wndProc;
  151. pWnd->windowLongs[GWL_STYLE] = dwStyle;
  152. pWnd->x = x;
  153. pWnd->y = y;
  154. pWnd->w = nWidth;
  155. pWnd->h = nHeight;
  156. pWnd->nMagic = HWND_MAGIC;
  157. // link into list
  158. pWnd->pNext = g_pWnds;
  159. g_pWnds = pWnd;
  160. // force the focus
  161. g_focusWindow = (HWND)pWnd;
  162. // send the expected message sequence
  163. SendMessage( (HWND)pWnd, WM_CREATE, 0, 0 );
  164. SendMessage( (HWND)pWnd, WM_ACTIVATEAPP, TRUE, 0 );
  165. return (HWND)pWnd;
  166. }
  167. HWND CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
  168. {
  169. return CreateWindow( lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam );
  170. }
  171. BOOL DestroyWindow( HWND hWnd )
  172. {
  173. if ( !IsWndValid( hWnd ) )
  174. return FALSE;
  175. xWnd_t* pPrev = g_pWnds;
  176. xWnd_t* pCur = g_pWnds;
  177. while ( pCur )
  178. {
  179. if ( pCur == (xWnd_t*)hWnd )
  180. {
  181. if ( pPrev == g_pWnds )
  182. {
  183. // at head of list, fixup
  184. g_pWnds = pCur->pNext;
  185. }
  186. else
  187. {
  188. // remove from chain
  189. pPrev->pNext = pCur->pNext;
  190. }
  191. pCur->nMagic = 0;
  192. delete pCur;
  193. break;
  194. }
  195. // advance through list
  196. pPrev = pCur;
  197. pCur = pCur->pNext;
  198. }
  199. return TRUE;
  200. }
  201. ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx)
  202. {
  203. // create
  204. xWndClass_t* pWndClass = new xWndClass_t;
  205. memset(pWndClass, 0, sizeof(xWndClass_t));
  206. pWndClass->pClassName = new char[strlen(lpwcx->lpszClassName)+1];
  207. strcpy(pWndClass->pClassName, lpwcx->lpszClassName);
  208. pWndClass->wndProc = lpwcx->lpfnWndProc;
  209. // insert into list
  210. pWndClass->pNext = g_pWndClasses;
  211. g_pWndClasses = pWndClass;
  212. return (ATOM)pWndClass;
  213. }
  214. ATOM RegisterClass(CONST WNDCLASS *lpwc)
  215. {
  216. // create
  217. xWndClass_t* pWndClass = new xWndClass_t;
  218. memset(pWndClass, 0, sizeof(xWndClass_t));
  219. pWndClass->pClassName = new char[strlen(lpwc->lpszClassName)+1];
  220. strcpy(pWndClass->pClassName, lpwc->lpszClassName);
  221. pWndClass->wndProc = lpwc->lpfnWndProc;
  222. // insert into list
  223. pWndClass->pNext = g_pWndClasses;
  224. g_pWndClasses = pWndClass;
  225. return (ATOM)pWndClass;
  226. }
  227. HWND GetFocus(VOID)
  228. {
  229. if ( !IsWndValid( g_focusWindow ) )
  230. return NULL;
  231. return g_focusWindow;
  232. }
  233. HWND SetFocus( HWND hWnd )
  234. {
  235. HWND hOldFocus = g_focusWindow;
  236. if ( IsWndValid( hWnd ) )
  237. {
  238. g_focusWindow = hWnd;
  239. }
  240. return hOldFocus;
  241. }
  242. LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  243. {
  244. return (lpPrevWndFunc(hWnd, Msg, wParam, lParam));
  245. }
  246. int GetSystemMetrics(int nIndex)
  247. {
  248. XVIDEO_MODE videoMode;
  249. XGetVideoMode( &videoMode );
  250. // default to having the backbuffer the same as the mode resolution.
  251. int nFrameBufferWidth, nFrameBufferHeight;
  252. nFrameBufferWidth = videoMode.dwDisplayWidth;
  253. nFrameBufferHeight = videoMode.dwDisplayHeight;
  254. // override for cases where we need to have a different backbuffer either for memory reasons
  255. // or for dealing with anamorphic modes.
  256. if ( !videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 640 && videoMode.dwDisplayHeight == 576 )
  257. {
  258. // PAL normal
  259. nFrameBufferWidth = 640;
  260. nFrameBufferHeight = 480;
  261. }
  262. else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 640 && videoMode.dwDisplayHeight == 576 )
  263. {
  264. // PAL widescreen
  265. nFrameBufferWidth = 848;
  266. nFrameBufferHeight = 480;
  267. }
  268. else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 640 && videoMode.dwDisplayHeight == 480 )
  269. {
  270. // anamorphic
  271. nFrameBufferWidth = 848;
  272. nFrameBufferHeight = 480;
  273. }
  274. else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 1024 && videoMode.dwDisplayHeight == 768 )
  275. {
  276. // anamorphic
  277. nFrameBufferWidth = 1280;
  278. nFrameBufferHeight = 720;
  279. }
  280. else if ( videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 760 )
  281. {
  282. nFrameBufferWidth = 1280;
  283. nFrameBufferHeight = 720;
  284. }
  285. else if ( videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 768 )
  286. {
  287. nFrameBufferWidth = 1280;
  288. nFrameBufferHeight = 720;
  289. }
  290. else if ( !videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 1024 )
  291. {
  292. nFrameBufferWidth = 1024;
  293. nFrameBufferHeight = 768;
  294. }
  295. else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 1024 )
  296. {
  297. // anamorphic
  298. nFrameBufferWidth = 1280;
  299. nFrameBufferHeight = 720;
  300. }
  301. else if ( videoMode.dwDisplayWidth == 1360 && videoMode.dwDisplayHeight == 768 )
  302. {
  303. nFrameBufferWidth = 1280;
  304. nFrameBufferHeight = 720;
  305. }
  306. else if ( videoMode.dwDisplayWidth == 1920 && videoMode.dwDisplayHeight == 1080 )
  307. {
  308. nFrameBufferWidth = 1280;
  309. nFrameBufferHeight = 720;
  310. }
  311. switch ( nIndex )
  312. {
  313. case SM_CXFIXEDFRAME:
  314. case SM_CYFIXEDFRAME:
  315. case SM_CYSIZE:
  316. return 0;
  317. case SM_CXSCREEN:
  318. return nFrameBufferWidth;
  319. case SM_CYSCREEN:
  320. return nFrameBufferHeight;
  321. }
  322. // not implemented
  323. Assert( 0 );
  324. return 0;
  325. }
  326. BOOL ShowWindow(HWND hWnd, int nCmdShow)
  327. {
  328. if ( !IsWndValid( hWnd ) )
  329. return FALSE;
  330. ((xWnd_t*)hWnd)->show = nCmdShow;
  331. if ((nCmdShow == SW_SHOWDEFAULT) || (nCmdShow == SW_SHOWNORMAL) || (nCmdShow == SW_SHOW))
  332. g_focusWindow = hWnd;
  333. return TRUE;
  334. }
  335. LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  336. {
  337. if ( !IsWndValid( hWnd ) )
  338. return 0L;
  339. xWnd_t* pWnd = (xWnd_t*)hWnd;
  340. WNDPROC wndProc = (WNDPROC)pWnd->windowLongs[GWL_WNDPROC];
  341. Assert( wndProc );
  342. LRESULT result = wndProc(hWnd, Msg, wParam, lParam);
  343. return result;
  344. }
  345. LRESULT SendMessageTimeout( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult )
  346. {
  347. *lpdwResult = SendMessage( hWnd, Msg, wParam, lParam );
  348. return -1;
  349. }
  350. BOOL GetClientRect(HWND hWnd, LPRECT lpRect)
  351. {
  352. if ( !IsWndValid( hWnd ) )
  353. return FALSE;
  354. xWnd_t* pWnd = (xWnd_t*)hWnd;
  355. lpRect->left = 0;
  356. lpRect->top = 0;
  357. lpRect->right = pWnd->w;
  358. lpRect->bottom = pWnd->h;
  359. return TRUE;
  360. }
  361. int GetDeviceCaps(HDC hdc, int nIndex)
  362. {
  363. switch (nIndex)
  364. {
  365. case HORZRES:
  366. return GetSystemMetrics( SM_CXSCREEN );
  367. case VERTRES:
  368. return GetSystemMetrics( SM_CYSCREEN );
  369. case VREFRESH:
  370. return 60;
  371. }
  372. Assert( 0 );
  373. return 0;
  374. }
  375. BOOL SetWindowPos( HWND hWnd, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags )
  376. {
  377. if ( !IsWndValid( hWnd ) )
  378. return FALSE;
  379. xWnd_t* pWnd = (xWnd_t*)hWnd;
  380. if ( !( uFlags & SWP_NOMOVE ) )
  381. {
  382. pWnd->x = x;
  383. pWnd->y = y;
  384. }
  385. if ( !( uFlags & SWP_NOSIZE ) )
  386. {
  387. pWnd->w = cx;
  388. pWnd->h = cy;
  389. }
  390. return TRUE;
  391. }
  392. int XBX_unlink( const char* filename )
  393. {
  394. bool bSuccess = DeleteFile( filename ) != 0;
  395. if ( !bSuccess )
  396. {
  397. if ( GetLastError() == ERROR_FILE_NOT_FOUND )
  398. {
  399. // not a real failure
  400. return 0;
  401. }
  402. }
  403. // 0 = sucess, -1 = failure
  404. return bSuccess ? 0 : -1;
  405. }
  406. int XBX_mkdir( const char *pszDir )
  407. {
  408. char dirPath[MAX_PATH];
  409. char* ptr;
  410. BOOL bSuccess;
  411. // prime and skip to first seperator after the drive path
  412. // must create directory one path at a time
  413. bSuccess = false;
  414. strcpy( dirPath, pszDir );
  415. ptr = strchr( dirPath, '\\' );
  416. while ( ptr )
  417. {
  418. ptr = strchr( ptr+1, '\\' );
  419. if ( ptr )
  420. {
  421. *ptr = '\0';
  422. bSuccess = CreateDirectory( dirPath, XBOX_DONTCARE );
  423. if ( !bSuccess && GetLastError() == ERROR_ALREADY_EXISTS )
  424. {
  425. // not a real error
  426. bSuccess = true;
  427. }
  428. *ptr = '\\';
  429. }
  430. }
  431. return ( bSuccess ? 0 : -1 );
  432. }
  433. char *XBX_getcwd( char *buf, size_t size )
  434. {
  435. if ( !buf )
  436. {
  437. buf = (char*)malloc( 4 );
  438. }
  439. strncpy( buf, "D:", size );
  440. return buf;
  441. }
  442. int XBX_access( const char *path, int mode )
  443. {
  444. if ( !path )
  445. {
  446. return -1;
  447. }
  448. // get the fatx attributes
  449. DWORD dwAttr = GetFileAttributes( path );
  450. if ( dwAttr == (DWORD)-1 )
  451. {
  452. return -1;
  453. }
  454. if ( mode == 0 )
  455. {
  456. // is file exist?
  457. return 0;
  458. }
  459. else if ( mode == 2 )
  460. {
  461. // is file write only?
  462. return -1;
  463. }
  464. else if ( mode == 4 )
  465. {
  466. // is file read only?
  467. if ( dwAttr & FILE_ATTRIBUTE_READONLY )
  468. return 0;
  469. else
  470. return -1;
  471. }
  472. else if ( mode == 6 )
  473. {
  474. // is file read and write?
  475. if ( !( dwAttr & FILE_ATTRIBUTE_READONLY ) )
  476. return 0;
  477. else
  478. return -1;
  479. }
  480. return -1;
  481. }
  482. DWORD XBX_GetCurrentDirectory( DWORD nBufferLength, LPTSTR lpBuffer )
  483. {
  484. XBX_getcwd( lpBuffer, nBufferLength );
  485. return strlen( lpBuffer );
  486. }
  487. DWORD XBX_GetModuleFileName( HMODULE hModule, LPTSTR lpFilename, DWORD nSize )
  488. {
  489. int len;
  490. char *pStr;
  491. char *pEnd;
  492. char xexName[MAX_PATH];
  493. if ( hModule == GetModuleHandle( NULL ) )
  494. {
  495. // isolate xex of command line
  496. pStr = GetCommandLine();
  497. if ( pStr )
  498. {
  499. // cull possible quotes around xex
  500. if ( pStr[0] == '\"' )
  501. {
  502. pStr++;
  503. pEnd = strchr( pStr, '\"' );
  504. if ( !pEnd )
  505. {
  506. // no ending matching quote
  507. return 0;
  508. }
  509. }
  510. else
  511. {
  512. // find possible first argument
  513. pEnd = strchr( lpFilename, ' ' );
  514. if ( !pEnd )
  515. {
  516. pEnd = pStr+strlen( pStr );
  517. }
  518. }
  519. len = pEnd-pStr;
  520. memcpy( xexName, pStr, len );
  521. xexName[len] = '\0';
  522. len = _snprintf( lpFilename, nSize, "D:\\%s", xexName );
  523. if ( len == -1 )
  524. lpFilename[nSize-1] = '\0';
  525. return strlen( lpFilename );
  526. }
  527. }
  528. return 0;
  529. }