source-engine/tier0/xbox/xbox_win32stubs.cpp

618 lines
12 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: XBox win32 replacements - Mocks trivial windows flow
//
//=============================================================================//
#include "pch_tier0.h"
#include "xbox/xbox_win32stubs.h"
#include "tier0/memdbgon.h"
// On the 360, threads can run on any of 6 logical processors
DWORD g_dwProcessAffinityMask = 0x3F;
#define HWND_MAGIC 0x12345678
struct xWndClass_t
{
char* pClassName;
WNDPROC wndProc;
xWndClass_t* pNext;
};
struct xWnd_t
{
xWndClass_t* pWndClass;
int x;
int y;
int w;
int h;
long windowLongs[GWL_MAX];
int show;
int nMagic;
xWnd_t* pNext;
};
static xWndClass_t* g_pWndClasses;
static xWnd_t* g_pWnds;
static HWND g_focusWindow;
inline bool IsWndValid( HWND hWnd )
{
if ( !hWnd || ((xWnd_t*)hWnd)->nMagic != HWND_MAGIC )
return false;
return true;
}
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
XBX_Error( lpText );
Assert( 0 );
return (0);
}
LONG GetWindowLong(HWND hWnd, int nIndex)
{
LONG oldLong;
if ( !IsWndValid( hWnd ) )
return 0;
switch (nIndex)
{
case GWL_WNDPROC:
case GWL_USERDATA:
case GWL_STYLE:
case GWL_EXSTYLE:
oldLong = ((xWnd_t*)hWnd)->windowLongs[nIndex];
break;
default:
// not implemented
Assert( 0 );
return 0;
}
return oldLong;
}
LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex)
{
UINT idx;
switch ( nIndex )
{
case GWLP_WNDPROC:
idx = GWL_WNDPROC;
break;
case GWLP_USERDATA:
idx = GWL_USERDATA;
break;
default:
// not implemented
Assert(0);
return 0;
}
return GetWindowLong( hWnd, idx );
}
LONG_PTR GetWindowLongPtrW(HWND hWnd, int nIndex)
{
AssertMsg( false, "GetWindowLongPtrW does not exist on Xbox 360." );
return GetWindowLongPtr( hWnd, nIndex );
}
LONG SetWindowLong(HWND hWnd, int nIndex, LONG dwNewLong)
{
LONG oldLong;
if ( !IsWndValid( hWnd ) )
return 0;
switch ( nIndex )
{
case GWL_WNDPROC:
case GWL_USERDATA:
case GWL_STYLE:
oldLong = ((xWnd_t*)hWnd)->windowLongs[nIndex];
((xWnd_t*)hWnd)->windowLongs[nIndex] = dwNewLong;
break;
default:
// not implemented
Assert( 0 );
return 0;
}
return oldLong;
}
LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
{
UINT idx;
switch ( nIndex )
{
case GWLP_WNDPROC:
idx = GWL_WNDPROC;
break;
case GWLP_USERDATA:
idx = GWL_USERDATA;
break;
default:
// not implemented
Assert( 0 );
return 0;
}
return SetWindowLong( hWnd, idx, dwNewLong );
}
LONG_PTR SetWindowLongPtrW(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
{
AssertMsg( false, "SetWindowLongPtrW does not exist on Xbox 360." );
return SetWindowLongPtr( hWnd, nIndex, dwNewLong );
}
HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
// find classname
xWndClass_t* pWndClass = g_pWndClasses;
while ( pWndClass )
{
if ( !stricmp( lpClassName, pWndClass->pClassName ) )
break;
pWndClass = pWndClass->pNext;
}
if ( !pWndClass )
{
// no such class
return (HWND)NULL;
}
// allocate and setup
xWnd_t* pWnd = new xWnd_t;
memset( pWnd, 0, sizeof(xWnd_t) );
pWnd->pWndClass = pWndClass;
pWnd->windowLongs[GWL_WNDPROC] = (LONG)pWndClass->wndProc;
pWnd->windowLongs[GWL_STYLE] = dwStyle;
pWnd->x = x;
pWnd->y = y;
pWnd->w = nWidth;
pWnd->h = nHeight;
pWnd->nMagic = HWND_MAGIC;
// link into list
pWnd->pNext = g_pWnds;
g_pWnds = pWnd;
// force the focus
g_focusWindow = (HWND)pWnd;
// send the expected message sequence
SendMessage( (HWND)pWnd, WM_CREATE, 0, 0 );
SendMessage( (HWND)pWnd, WM_ACTIVATEAPP, TRUE, 0 );
return (HWND)pWnd;
}
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)
{
return CreateWindow( lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam );
}
BOOL DestroyWindow( HWND hWnd )
{
if ( !IsWndValid( hWnd ) )
return FALSE;
xWnd_t* pPrev = g_pWnds;
xWnd_t* pCur = g_pWnds;
while ( pCur )
{
if ( pCur == (xWnd_t*)hWnd )
{
if ( pPrev == g_pWnds )
{
// at head of list, fixup
g_pWnds = pCur->pNext;
}
else
{
// remove from chain
pPrev->pNext = pCur->pNext;
}
pCur->nMagic = 0;
delete pCur;
break;
}
// advance through list
pPrev = pCur;
pCur = pCur->pNext;
}
return TRUE;
}
ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx)
{
// create
xWndClass_t* pWndClass = new xWndClass_t;
memset(pWndClass, 0, sizeof(xWndClass_t));
pWndClass->pClassName = new char[strlen(lpwcx->lpszClassName)+1];
strcpy(pWndClass->pClassName, lpwcx->lpszClassName);
pWndClass->wndProc = lpwcx->lpfnWndProc;
// insert into list
pWndClass->pNext = g_pWndClasses;
g_pWndClasses = pWndClass;
return (ATOM)pWndClass;
}
ATOM RegisterClass(CONST WNDCLASS *lpwc)
{
// create
xWndClass_t* pWndClass = new xWndClass_t;
memset(pWndClass, 0, sizeof(xWndClass_t));
pWndClass->pClassName = new char[strlen(lpwc->lpszClassName)+1];
strcpy(pWndClass->pClassName, lpwc->lpszClassName);
pWndClass->wndProc = lpwc->lpfnWndProc;
// insert into list
pWndClass->pNext = g_pWndClasses;
g_pWndClasses = pWndClass;
return (ATOM)pWndClass;
}
HWND GetFocus(VOID)
{
if ( !IsWndValid( g_focusWindow ) )
return NULL;
return g_focusWindow;
}
HWND SetFocus( HWND hWnd )
{
HWND hOldFocus = g_focusWindow;
if ( IsWndValid( hWnd ) )
{
g_focusWindow = hWnd;
}
return hOldFocus;
}
LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
return (lpPrevWndFunc(hWnd, Msg, wParam, lParam));
}
int GetSystemMetrics(int nIndex)
{
XVIDEO_MODE videoMode;
XGetVideoMode( &videoMode );
// default to having the backbuffer the same as the mode resolution.
int nFrameBufferWidth, nFrameBufferHeight;
nFrameBufferWidth = videoMode.dwDisplayWidth;
nFrameBufferHeight = videoMode.dwDisplayHeight;
// override for cases where we need to have a different backbuffer either for memory reasons
// or for dealing with anamorphic modes.
if ( !videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 640 && videoMode.dwDisplayHeight == 576 )
{
// PAL normal
nFrameBufferWidth = 640;
nFrameBufferHeight = 480;
}
else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 640 && videoMode.dwDisplayHeight == 576 )
{
// PAL widescreen
nFrameBufferWidth = 848;
nFrameBufferHeight = 480;
}
else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 640 && videoMode.dwDisplayHeight == 480 )
{
// anamorphic
nFrameBufferWidth = 848;
nFrameBufferHeight = 480;
}
else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 1024 && videoMode.dwDisplayHeight == 768 )
{
// anamorphic
nFrameBufferWidth = 1280;
nFrameBufferHeight = 720;
}
else if ( videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 760 )
{
nFrameBufferWidth = 1280;
nFrameBufferHeight = 720;
}
else if ( videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 768 )
{
nFrameBufferWidth = 1280;
nFrameBufferHeight = 720;
}
else if ( !videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 1024 )
{
nFrameBufferWidth = 1024;
nFrameBufferHeight = 768;
}
else if ( videoMode.fIsWideScreen && videoMode.dwDisplayWidth == 1280 && videoMode.dwDisplayHeight == 1024 )
{
// anamorphic
nFrameBufferWidth = 1280;
nFrameBufferHeight = 720;
}
else if ( videoMode.dwDisplayWidth == 1360 && videoMode.dwDisplayHeight == 768 )
{
nFrameBufferWidth = 1280;
nFrameBufferHeight = 720;
}
else if ( videoMode.dwDisplayWidth == 1920 && videoMode.dwDisplayHeight == 1080 )
{
nFrameBufferWidth = 1280;
nFrameBufferHeight = 720;
}
switch ( nIndex )
{
case SM_CXFIXEDFRAME:
case SM_CYFIXEDFRAME:
case SM_CYSIZE:
return 0;
case SM_CXSCREEN:
return nFrameBufferWidth;
case SM_CYSCREEN:
return nFrameBufferHeight;
}
// not implemented
Assert( 0 );
return 0;
}
BOOL ShowWindow(HWND hWnd, int nCmdShow)
{
if ( !IsWndValid( hWnd ) )
return FALSE;
((xWnd_t*)hWnd)->show = nCmdShow;
if ((nCmdShow == SW_SHOWDEFAULT) || (nCmdShow == SW_SHOWNORMAL) || (nCmdShow == SW_SHOW))
g_focusWindow = hWnd;
return TRUE;
}
LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if ( !IsWndValid( hWnd ) )
return 0L;
xWnd_t* pWnd = (xWnd_t*)hWnd;
WNDPROC wndProc = (WNDPROC)pWnd->windowLongs[GWL_WNDPROC];
Assert( wndProc );
LRESULT result = wndProc(hWnd, Msg, wParam, lParam);
return result;
}
LRESULT SendMessageTimeout( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult )
{
*lpdwResult = SendMessage( hWnd, Msg, wParam, lParam );
return -1;
}
BOOL GetClientRect(HWND hWnd, LPRECT lpRect)
{
if ( !IsWndValid( hWnd ) )
return FALSE;
xWnd_t* pWnd = (xWnd_t*)hWnd;
lpRect->left = 0;
lpRect->top = 0;
lpRect->right = pWnd->w;
lpRect->bottom = pWnd->h;
return TRUE;
}
int GetDeviceCaps(HDC hdc, int nIndex)
{
switch (nIndex)
{
case HORZRES:
return GetSystemMetrics( SM_CXSCREEN );
case VERTRES:
return GetSystemMetrics( SM_CYSCREEN );
case VREFRESH:
return 60;
}
Assert( 0 );
return 0;
}
BOOL SetWindowPos( HWND hWnd, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags )
{
if ( !IsWndValid( hWnd ) )
return FALSE;
xWnd_t* pWnd = (xWnd_t*)hWnd;
if ( !( uFlags & SWP_NOMOVE ) )
{
pWnd->x = x;
pWnd->y = y;
}
if ( !( uFlags & SWP_NOSIZE ) )
{
pWnd->w = cx;
pWnd->h = cy;
}
return TRUE;
}
int XBX_unlink( const char* filename )
{
bool bSuccess = DeleteFile( filename ) != 0;
if ( !bSuccess )
{
if ( GetLastError() == ERROR_FILE_NOT_FOUND )
{
// not a real failure
return 0;
}
}
// 0 = sucess, -1 = failure
return bSuccess ? 0 : -1;
}
int XBX_mkdir( const char *pszDir )
{
char dirPath[MAX_PATH];
char* ptr;
BOOL bSuccess;
// prime and skip to first seperator after the drive path
// must create directory one path at a time
bSuccess = false;
strcpy( dirPath, pszDir );
ptr = strchr( dirPath, '\\' );
while ( ptr )
{
ptr = strchr( ptr+1, '\\' );
if ( ptr )
{
*ptr = '\0';
bSuccess = CreateDirectory( dirPath, XBOX_DONTCARE );
if ( !bSuccess && GetLastError() == ERROR_ALREADY_EXISTS )
{
// not a real error
bSuccess = true;
}
*ptr = '\\';
}
}
return ( bSuccess ? 0 : -1 );
}
char *XBX_getcwd( char *buf, size_t size )
{
if ( !buf )
{
buf = (char*)malloc( 4 );
}
strncpy( buf, "D:", size );
return buf;
}
int XBX_access( const char *path, int mode )
{
if ( !path )
{
return -1;
}
// get the fatx attributes
DWORD dwAttr = GetFileAttributes( path );
if ( dwAttr == (DWORD)-1 )
{
return -1;
}
if ( mode == 0 )
{
// is file exist?
return 0;
}
else if ( mode == 2 )
{
// is file write only?
return -1;
}
else if ( mode == 4 )
{
// is file read only?
if ( dwAttr & FILE_ATTRIBUTE_READONLY )
return 0;
else
return -1;
}
else if ( mode == 6 )
{
// is file read and write?
if ( !( dwAttr & FILE_ATTRIBUTE_READONLY ) )
return 0;
else
return -1;
}
return -1;
}
DWORD XBX_GetCurrentDirectory( DWORD nBufferLength, LPTSTR lpBuffer )
{
XBX_getcwd( lpBuffer, nBufferLength );
return strlen( lpBuffer );
}
DWORD XBX_GetModuleFileName( HMODULE hModule, LPTSTR lpFilename, DWORD nSize )
{
int len;
char *pStr;
char *pEnd;
char xexName[MAX_PATH];
if ( hModule == GetModuleHandle( NULL ) )
{
// isolate xex of command line
pStr = GetCommandLine();
if ( pStr )
{
// cull possible quotes around xex
if ( pStr[0] == '\"' )
{
pStr++;
pEnd = strchr( pStr, '\"' );
if ( !pEnd )
{
// no ending matching quote
return 0;
}
}
else
{
// find possible first argument
pEnd = strchr( lpFilename, ' ' );
if ( !pEnd )
{
pEnd = pStr+strlen( pStr );
}
}
len = pEnd-pStr;
memcpy( xexName, pStr, len );
xexName[len] = '\0';
len = _snprintf( lpFilename, nSize, "D:\\%s", xexName );
if ( len == -1 )
lpFilename[nSize-1] = '\0';
return strlen( lpFilename );
}
}
return 0;
}