diff --git a/saco/d3d9/common/DXUTgui.cpp b/saco/d3d9/common/DXUTgui.cpp index ecfb1c7..d9c4779 100644 --- a/saco/d3d9/common/DXUTgui.cpp +++ b/saco/d3d9/common/DXUTgui.cpp @@ -7675,6 +7675,7 @@ bool CUniBuffer::SetText( LPCTSTR wszText ) WCHAR szBuffer[2048]; ConvertAnsiToWide(wszText, szBuffer, 2048); SetText(szBuffer); + return true; } diff --git a/saco/d3d9/d3dutil.cpp b/saco/d3d9/d3dutil.cpp new file mode 100644 index 0000000..4e7c347 --- /dev/null +++ b/saco/d3d9/d3dutil.cpp @@ -0,0 +1,311 @@ +//----------------------------------------------------------------------------- +// File: D3DUtil.cpp +// +// Desc: Shortcut macros and functions for using DirectX objects +// +// Copyright (c) Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#define D3D_OVERLOADS +#include +#include "include/D3DUtil.h" + +#ifndef _T +#define _T TEXT +#endif + +//----------------------------------------------------------------------------- +// Name: D3DUtil_GetDXSDKMediaPath() +// Desc: Returns the DirectX SDK media path, as stored in the system registry +// during the SDK install. +//----------------------------------------------------------------------------- +// MATCH +const TCHAR* D3DUtil_GetDXSDKMediaPath() +{ + static TCHAR strNull[2] = _T(""); + static TCHAR strPath[MAX_PATH + 20]; + HKEY hKey; + DWORD type, size=MAX_PATH; + + // Open the appropriate registry key + LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\DirectX SDK"), + 0, KEY_READ, &hKey ); + if( ERROR_SUCCESS != result ) + return strNull; + + result = RegQueryValueEx( hKey, _T("DX9S4SDK Samples Path"), NULL, + &type, (BYTE*)strPath, &size ); + + if( ERROR_SUCCESS != result ) + { + result = RegQueryValueEx( hKey, _T("DX81SDK Samples Path"), NULL, + &type, (BYTE*)strPath, &size ); + + if( ERROR_SUCCESS != result ) + { + result = RegQueryValueEx( hKey, _T("DX8SDK Samples Path"), NULL, + &type, (BYTE*)strPath, &size ); + + if( ERROR_SUCCESS != result ) + { + RegCloseKey( hKey ); + return strNull; + } + } + } + + RegCloseKey( hKey ); + lstrcat( strPath, _T("\\D3DIM\\Media\\") ); + + return strPath; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitSurfaceDesc() +// Desc: Helper function called to build a DDSURFACEDESC2 structure, +// typically before calling CreateSurface() or GetSurfaceDesc() +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags, + DWORD dwCaps ) +{ + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = dwFlags; + ddsd.ddsCaps.dwCaps = dwCaps; + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitMaterial() +// Desc: Helper function called to build a D3DMATERIAL7 structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b, + FLOAT a ) +{ + ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) ); + mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r; + mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g; + mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b; + mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitLight() +// Desc: Initializes a D3DLIGHT7 structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType, + FLOAT x, FLOAT y, FLOAT z ) +{ + ZeroMemory( &light, sizeof(D3DLIGHT7) ); + light.dltType = ltType; + light.dcvDiffuse.r = 1.0f; + light.dcvDiffuse.g = 1.0f; + light.dcvDiffuse.b = 1.0f; + light.dcvSpecular = light.dcvDiffuse; + light.dvPosition.x = light.dvDirection.x = x; + light.dvPosition.y = light.dvDirection.y = y; + light.dvPosition.z = light.dvDirection.z = z; + light.dvAttenuation0 = 1.0f; + light.dvRange = D3DLIGHT_RANGE_MAX; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetViewMatrix() +// Desc: Given an eye point, a lookat point, and an up vector, this +// function builds a 4x4 view matrix. +//----------------------------------------------------------------------------- +// MATCH +HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, + D3DVECTOR& vAt, D3DVECTOR& vWorldUp ) +{ + // Get the z basis vector, which points straight ahead. This is the + // difference from the eyepoint to the lookat point. + D3DVECTOR vView = vAt - vFrom; + + FLOAT fLength = Magnitude( vView ); + if( fLength < 1e-6f ) + return E_INVALIDARG; + + // Normalize the z basis vector + vView /= fLength; + + // Get the dot product, and calculate the projection of the z basis + // vector onto the up vector. The projection is the y basis vector. + FLOAT fDotProduct = DotProduct( vWorldUp, vView ); + + D3DVECTOR vUp = vWorldUp - fDotProduct * vView; + + // If this vector has near-zero length because the input specified a + // bogus up vector, let's try a default up vector + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + { + vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView; + + // If we still have near-zero length, resort to a different axis. + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + { + vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView; + + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + return E_INVALIDARG; + } + } + + // Normalize the y basis vector + vUp /= fLength; + + // The x basis vector is found simply with the cross product of the y + // and z basis vectors + D3DVECTOR vRight = CrossProduct( vUp, vView ); + + // Start building the matrix. The first three rows contains the basis + // vectors used to rotate the view to point at the lookat point + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x; + mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y; + mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z; + + // Do the translation values (rotations are still about the eyepoint) + mat._41 = - DotProduct( vFrom, vRight ); + mat._42 = - DotProduct( vFrom, vUp ); + mat._43 = - DotProduct( vFrom, vView ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetProjectionMatrix() +// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built +// from the field-of-view (fov, in y), aspect ratio, near plane (D), +// and far plane (F). Note that the projection matrix is normalized for +// element [3][4] to be 1.0. This is performed so that W-based range fog +// will work correctly. +//----------------------------------------------------------------------------- +// MATCH +HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect, + FLOAT fNearPlane, FLOAT fFarPlane ) +{ + if( fabs(fFarPlane-fNearPlane) < 0.01f ) + return E_INVALIDARG; + if( fabs(sin(fFOV/2)) < 0.01f ) + return E_INVALIDARG; + + FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) ); + FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) ); + FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane ); + + ZeroMemory( &mat, sizeof(D3DMATRIX) ); + mat._11 = w; + mat._22 = h; + mat._33 = Q; + mat._34 = 1.0f; + mat._43 = -Q*fNearPlane; + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateXMatrix() +// Desc: Create Rotation matrix about X axis +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._22 = cosf( fRads ); + mat._23 = sinf( fRads ); + mat._32 = -sinf( fRads ); + mat._33 = cosf( fRads ); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateYMatrix() +// Desc: Create Rotation matrix about Y axis +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = cosf( fRads ); + mat._13 = -sinf( fRads ); + mat._31 = sinf( fRads ); + mat._33 = cosf( fRads ); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateZMatrix() +// Desc: Create Rotation matrix about Z axis +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = cosf( fRads ); + mat._12 = sinf( fRads ); + mat._21 = -sinf( fRads ); + mat._22 = cosf( fRads ); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotationMatrix +// Desc: Create a Rotation matrix about vector direction +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads ) +{ + FLOAT fCos = cosf( fRads ); + FLOAT fSin = sinf( fRads ); + D3DVECTOR v = Normalize( vDir ); + + mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos; + mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin); + mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin); + + mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin); + mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ; + mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin); + + mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin); + mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin); + mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos; + + mat._14 = mat._24 = mat._34 = 0.0f; + mat._41 = mat._42 = mat._43 = 0.0f; + mat._44 = 1.0f; +} + + +//----------------------------------------------------------------------------- +// Name: _DbgOut() +// Desc: Outputs a message to the debug stream +//----------------------------------------------------------------------------- +// MATCH +HRESULT _DbgOut( CHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg ) +{ + TCHAR buffer[256]; + wsprintf( buffer, _T("%hs(%ld): "), strFile, dwLine ); + OutputDebugString( buffer ); + OutputDebugString( strMsg ); + + if( hr != (HRESULT) S_OK ) + { + wsprintf( buffer, _T("(hr=%08lx)\n"), hr ); + OutputDebugString( buffer ); + } + + OutputDebugString( _T("\n") ); + + return hr; +} + diff --git a/saco/d3d9/dxutil.cpp b/saco/d3d9/dxutil.cpp new file mode 100644 index 0000000..72e1e79 --- /dev/null +++ b/saco/d3d9/dxutil.cpp @@ -0,0 +1,1381 @@ +//----------------------------------------------------------------------------- +// File: DXUtil.cpp +// +// Desc: Shortcut macros and functions for using DX objects +// +// Copyright (c) Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include +#include +#include "include/dxutil.h" + +#ifdef UNICODE + typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd); +#else + typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd); +#endif + +bool DXUtil_FindMediaSearchParentDirs( TCHAR* strSearchPath, int cchSearch, TCHAR* strStartAt, TCHAR* strLeafName ); +bool DXUtil_FindMediaSearchTypicalDirs( TCHAR* strSearchPath, int cchSearch, LPCTSTR strLeaf, TCHAR* strExePath, TCHAR* strExeName, TCHAR* strMediaDir ); + + +#ifndef UNDER_CE +//----------------------------------------------------------------------------- +// Name: DXUtil_GetDXSDKMediaPathCch() +// Desc: Returns the DirectX SDK media path +// cchDest is the size in TCHARs of strDest. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//----------------------------------------------------------------------------- +HRESULT DXUtil_GetDXSDKMediaPathCch( TCHAR* strDest, int cchDest ) +{ + if( strDest == NULL || cchDest < 1 ) + return E_INVALIDARG; + + lstrcpy( strDest, TEXT("") ); + + // Open the appropriate registry key + HKEY hKey; + LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\DirectX SDK"), + 0, KEY_READ, &hKey ); + if( ERROR_SUCCESS != lResult ) + return E_FAIL; + + DWORD dwType; + DWORD dwSize = cchDest * sizeof(TCHAR); + lResult = RegQueryValueEx( hKey, _T("DX9S4SDK Samples Path"), NULL, + &dwType, (BYTE*)strDest, &dwSize ); + strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small + RegCloseKey( hKey ); + + if( ERROR_SUCCESS != lResult ) + return E_FAIL; + + const TCHAR* strMedia = _T("\\Media\\"); + if( lstrlen(strDest) + lstrlen(strMedia) < cchDest ) + _tcscat( strDest, strMedia ); + else + return E_INVALIDARG; + + return S_OK; +} +#endif // !UNDER_CE + + + +#ifndef UNDER_CE +//----------------------------------------------------------------------------- +// Name: DXUtil_FindMediaFileCch() +// Desc: Trys to find the location of a SDK media file +// cchDest is the size in TCHARs of strDestPath. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//----------------------------------------------------------------------------- +HRESULT DXUtil_FindMediaFileCch( TCHAR* strDestPath, int cchDest, LPCTSTR strFilename ) +{ + bool bFound; + TCHAR strSearchFor[MAX_PATH]; + + if( NULL==strFilename || strFilename[0] == 0 || NULL==strDestPath || cchDest < 10 ) + return E_INVALIDARG; + + // Get the DirectX SDK's media dir if the SDK is installed + TCHAR strMediaDir[MAX_PATH] = {0}; + DXUtil_GetDXSDKMediaPathCch( strMediaDir, MAX_PATH ); + + // Get the exe name, and exe path + TCHAR strExePath[MAX_PATH] = {0}; + TCHAR strExeName[MAX_PATH] = {0}; + TCHAR* strLastSlash = NULL; + GetModuleFileName( NULL, strExePath, MAX_PATH ); + strExePath[MAX_PATH-1]=0; + strLastSlash = _tcsrchr( strExePath, TEXT('\\') ); + if( strLastSlash ) + { + lstrcpyn( strExeName, &strLastSlash[1], MAX_PATH ); + + // Chop the exe name from the exe path + *strLastSlash = 0; + + // Chop the .exe from the exe name + strLastSlash = _tcsrchr( strExeName, TEXT('.') ); + if( strLastSlash ) + *strLastSlash = 0; + } + + // Typical directories: + // .\ + // ..\ + // ..\..\ + // %EXE_DIR%\ + // %EXE_DIR%\..\ + // %EXE_DIR%\..\..\ + // %EXE_DIR%\..\%EXE_NAME% + // %EXE_DIR%\..\..\%EXE_NAME% + // DXSDK media path + + // Typical directory search + bFound = DXUtil_FindMediaSearchTypicalDirs( strDestPath, cchDest, strFilename, strExePath, strExeName, strMediaDir ); + if( bFound ) + return S_OK; + + // Typical directory search again, but also look in a subdir called "\media\" + _sntprintf( strSearchFor, MAX_PATH, TEXT("media\\%s"), strFilename ); strSearchFor[MAX_PATH-1] = 0; + bFound = DXUtil_FindMediaSearchTypicalDirs( strDestPath, cchDest, strSearchFor, strExePath, strExeName, strMediaDir ); + if( bFound ) + return S_OK; + + TCHAR strLeafName[MAX_PATH] = {0}; + + // Search all parent directories starting at .\ and using strFilename as the leaf name + _tcsncpy( strLeafName, strFilename, MAX_PATH ); strLeafName[MAX_PATH-1] = 0; + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, TEXT("."), strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at the exe's dir and using strFilename as the leaf name + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at .\ and using "media\strFilename" as the leaf name + _sntprintf( strLeafName, MAX_PATH, TEXT("media\\%s"), strFilename ); strLeafName[MAX_PATH-1] = 0; + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, TEXT("."), strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at the exe's dir and using "media\strFilename" as the leaf name + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); + if( bFound ) + return S_OK; + + // On failure, return the file as the path but also return an error code + _tcsncpy( strDestPath, strFilename, cchDest ); + strDestPath[cchDest-1] = 0; + + return E_FAIL; +} + + + +//-------------------------------------------------------------------------------------- +// Search a set of typical directories +//-------------------------------------------------------------------------------------- +// MATCH +bool DXUtil_FindMediaSearchTypicalDirs( TCHAR* strSearchPath, int cchSearch, LPCTSTR strLeaf, + TCHAR* strExePath, TCHAR* strExeName, TCHAR* strMediaDir ) +{ + // Typical directories: + // .\ + // ..\ + // ..\..\ + // %EXE_DIR%\ + // %EXE_DIR%\..\ + // %EXE_DIR%\..\..\ + // %EXE_DIR%\..\%EXE_NAME% + // %EXE_DIR%\..\..\%EXE_NAME% + // DXSDK media path + + // Search in .\ + _tcsncpy( strSearchPath, strLeaf, cchSearch ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\ + _sntprintf( strSearchPath, cchSearch, TEXT("..\\%s"), strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("..\\..\\%s"), strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("..\\..\\%s"), strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\ + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\%s"), strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\%s"), strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\..\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\..\\%s"), strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\%s\\%s"), strExePath, strExeName, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\..\..\%EXE_NAME%\". This matches the DirectX SDK layout + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\..\\%s\\%s"), strExePath, strExeName, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in DirectX SDK's media dir + _sntprintf( strSearchPath, cchSearch, TEXT("%s%s"), strMediaDir, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + return false; +} + + + +//-------------------------------------------------------------------------------------- +// Search parent directories starting at strStartAt, and appending strLeafName +// at each parent directory. It stops at the root directory. +//-------------------------------------------------------------------------------------- +// MATCH +bool DXUtil_FindMediaSearchParentDirs( TCHAR* strSearchPath, int cchSearch, TCHAR* strStartAt, TCHAR* strLeafName ) +{ + TCHAR strFullPath[MAX_PATH] = {0}; + TCHAR strFullFileName[MAX_PATH] = {0}; + TCHAR strSearch[MAX_PATH] = {0}; + TCHAR* strFilePart = NULL; + + GetFullPathName( strStartAt, MAX_PATH, strFullPath, &strFilePart ); + if( strFilePart == NULL ) + return false; + + while( strFilePart != NULL ) + { + _sntprintf( strFullFileName, MAX_PATH, TEXT("%s\\%s"), strFullPath, strLeafName ); strFullFileName[MAX_PATH-1] = 0; + if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF ) + { + _tcsncpy( strSearchPath, strFullFileName, cchSearch ); strSearchPath[cchSearch-1] = 0; + return true; + } + + _sntprintf( strSearch, MAX_PATH, TEXT("%s\\.."), strFullPath ); strSearch[MAX_PATH-1] = 0; + GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart ); + } + + return false; +} +#endif // !UNDER_CE + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadStringRegKeyCch() +// Desc: Helper function to read a registry key string +// cchDest is the size in TCHARs of strDest. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//----------------------------------------------------------------------------- +// MATCH +HRESULT DXUtil_ReadStringRegKeyCch( HKEY hKey, LPCTSTR strRegName, TCHAR* strDest, + DWORD cchDest, LPCTSTR strDefault ) +{ + DWORD dwType; + DWORD cbDest = cchDest * sizeof(TCHAR); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (BYTE*)strDest, &cbDest ) ) + { + _tcsncpy( strDest, strDefault, cchDest ); + strDest[cchDest-1] = 0; + return S_FALSE; + } + else + { + if( dwType != REG_SZ ) + { + _tcsncpy( strDest, strDefault, cchDest ); + strDest[cchDest-1] = 0; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteStringRegKey() +// Desc: Helper function to write a registry key string +//----------------------------------------------------------------------------- +// MATCH +HRESULT DXUtil_WriteStringRegKey( HKEY hKey, LPCTSTR strRegName, + LPCTSTR strValue ) +{ + if( NULL == strValue ) + return E_INVALIDARG; + + DWORD cbValue = ((DWORD)_tcslen(strValue)+1) * sizeof(TCHAR); + + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_SZ, + (BYTE*)strValue, cbValue ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadFloatRegKey() +// Desc: Helper function to read a registry key string +//----------------------------------------------------------------------------- +// MATCH +HRESULT DXUtil_ReadFloatRegKey( HKEY hKey, LPCTSTR strRegName, FLOAT* pfDest, FLOAT fDefault ) +{ + if( NULL == pfDest ) + return E_INVALIDARG; + + TCHAR sz[256]; + float fResult; + + TCHAR strDefault[256]; + _sntprintf( strDefault, 256, TEXT("%f"), fDefault ); + strDefault[255] = 0; + + if( SUCCEEDED( DXUtil_ReadStringRegKeyCch( hKey, strRegName, sz, 256, strDefault ) ) ) + { + int nResult = _stscanf( sz, TEXT("%f"), &fResult ); + if( nResult == 1 ) + { + *pfDest = fResult; + return S_OK; + } + } + + *pfDest = fDefault; + return S_FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteFloatRegKey() +// Desc: Helper function to write a registry key string +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteFloatRegKey( HKEY hKey, LPCTSTR strRegName, FLOAT fValue ) +{ + TCHAR strValue[256]; + _sntprintf( strValue, 256, TEXT("%f"), fValue ); + strValue[255] = 0; + + return DXUtil_WriteStringRegKey( hKey, strRegName, strValue ); +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadIntRegKey() +// Desc: Helper function to read a registry key int +//----------------------------------------------------------------------------- +HRESULT DXUtil_ReadIntRegKey( HKEY hKey, LPCTSTR strRegName, DWORD* pdwDest, + DWORD dwDefault ) +{ + DWORD dwType; + DWORD dwLength = sizeof(DWORD); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (BYTE*)pdwDest, &dwLength ) ) + { + *pdwDest = dwDefault; + return S_FALSE; + } + else + { + if( dwType != REG_DWORD ) + { + *pdwDest = dwDefault; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteIntRegKey() +// Desc: Helper function to write a registry key int +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteIntRegKey( HKEY hKey, LPCTSTR strRegName, DWORD dwValue ) +{ + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, + (BYTE*)&dwValue, sizeof(DWORD) ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadBoolRegKey() +// Desc: Helper function to read a registry key BOOL +//----------------------------------------------------------------------------- +HRESULT DXUtil_ReadBoolRegKey( HKEY hKey, LPCTSTR strRegName, BOOL* pbDest, + BOOL bDefault ) +{ + DWORD dwType; + DWORD dwLength = sizeof(BOOL); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (BYTE*)pbDest, &dwLength ) ) + { + *pbDest = bDefault; + return S_FALSE; + } + else + { + if( dwType != REG_DWORD ) + { + *pbDest = bDefault; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteBoolRegKey() +// Desc: Helper function to write a registry key BOOL +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteBoolRegKey( HKEY hKey, LPCTSTR strRegName, BOOL bValue ) +{ + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, + (BYTE*)&bValue, sizeof(BOOL) ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadGuidRegKey() +// Desc: Helper function to read a registry key guid +//----------------------------------------------------------------------------- +HRESULT DXUtil_ReadGuidRegKey( HKEY hKey, LPCTSTR strRegName, GUID* pGuidDest, + GUID& guidDefault ) +{ + DWORD dwType; + DWORD dwLength = sizeof(GUID); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (LPBYTE) pGuidDest, &dwLength ) ) + { + *pGuidDest = guidDefault; + return S_FALSE; + } + else + { + if( dwType != REG_BINARY ) + { + *pGuidDest = guidDefault; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteGuidRegKey() +// Desc: Helper function to write a registry key guid +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteGuidRegKey( HKEY hKey, LPCTSTR strRegName, GUID guidValue ) +{ + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_BINARY, + (BYTE*)&guidValue, sizeof(GUID) ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_Timer() +// Desc: Performs timer opertations. Use the following commands: +// TIMER_RESET - to reset the timer +// TIMER_START - to start the timer +// TIMER_STOP - to stop (or pause) the timer +// TIMER_ADVANCE - to advance the timer by 0.1 seconds +// TIMER_GETABSOLUTETIME - to get the absolute system time +// TIMER_GETAPPTIME - to get the current time +// TIMER_GETELAPSEDTIME - to get the time that elapsed between +// TIMER_GETELAPSEDTIME calls +//----------------------------------------------------------------------------- +FLOAT __stdcall DXUtil_Timer( TIMER_COMMAND command ) +{ + static BOOL m_bTimerInitialized = FALSE; + static BOOL m_bUsingQPF = FALSE; + static BOOL m_bTimerStopped = TRUE; + static LONGLONG m_llQPFTicksPerSec = 0; + + // Initialize the timer + if( FALSE == m_bTimerInitialized ) + { + m_bTimerInitialized = TRUE; + + // Use QueryPerformanceFrequency() to get frequency of timer. If QPF is + // not supported, we will timeGetTime() which returns milliseconds. + LARGE_INTEGER qwTicksPerSec; + m_bUsingQPF = QueryPerformanceFrequency( &qwTicksPerSec ); + if( m_bUsingQPF ) + m_llQPFTicksPerSec = qwTicksPerSec.QuadPart; + } + + if( m_bUsingQPF ) + { + static LONGLONG m_llStopTime = 0; + static LONGLONG m_llLastElapsedTime = 0; + static LONGLONG m_llBaseTime = 0; + double fTime; + double fElapsedTime; + LARGE_INTEGER qwTime; + + // Get either the current time or the stop time, depending + // on whether we're stopped and what command was sent + if( m_llStopTime != 0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME) + qwTime.QuadPart = m_llStopTime; + else + QueryPerformanceCounter( &qwTime ); + + // Return the elapsed time + if( command == TIMER_GETELAPSEDTIME ) + { + fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec; + m_llLastElapsedTime = qwTime.QuadPart; + return (FLOAT) fElapsedTime; + } + + // Return the current time + if( command == TIMER_GETAPPTIME ) + { + double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec; + return (FLOAT) fAppTime; + } + + // Reset the timer + if( command == TIMER_RESET ) + { + m_llBaseTime = qwTime.QuadPart; + m_llLastElapsedTime = qwTime.QuadPart; + m_llStopTime = 0; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Start the timer + if( command == TIMER_START ) + { + if( m_bTimerStopped ) + m_llBaseTime += qwTime.QuadPart - m_llStopTime; + m_llStopTime = 0; + m_llLastElapsedTime = qwTime.QuadPart; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Stop the timer + if( command == TIMER_STOP ) + { + if( !m_bTimerStopped ) + { + m_llStopTime = qwTime.QuadPart; + m_llLastElapsedTime = qwTime.QuadPart; + m_bTimerStopped = TRUE; + } + return 0.0f; + } + + // Advance the timer by 1/10th second + if( command == TIMER_ADVANCE ) + { + m_llStopTime += m_llQPFTicksPerSec/10; + return 0.0f; + } + + if( command == TIMER_GETABSOLUTETIME ) + { + fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec; + return (FLOAT) fTime; + } + + return -1.0f; // Invalid command specified + } + else + { + // Get the time using timeGetTime() + static double m_fLastElapsedTime = 0.0; + static double m_fBaseTime = 0.0; + static double m_fStopTime = 0.0; + double fTime; + double fElapsedTime; + + // Get either the current time or the stop time, depending + // on whether we're stopped and what command was sent + if( m_fStopTime != 0.0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME) + fTime = m_fStopTime; + else + fTime = GETTIMESTAMP() * 0.001; + + // Return the elapsed time + if( command == TIMER_GETELAPSEDTIME ) + { + fElapsedTime = (double) (fTime - m_fLastElapsedTime); + m_fLastElapsedTime = fTime; + return (FLOAT) fElapsedTime; + } + + // Return the current time + if( command == TIMER_GETAPPTIME ) + { + return (FLOAT) (fTime - m_fBaseTime); + } + + // Reset the timer + if( command == TIMER_RESET ) + { + m_fBaseTime = fTime; + m_fLastElapsedTime = fTime; + m_fStopTime = 0; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Start the timer + if( command == TIMER_START ) + { + if( m_bTimerStopped ) + m_fBaseTime += fTime - m_fStopTime; + m_fStopTime = 0.0f; + m_fLastElapsedTime = fTime; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Stop the timer + if( command == TIMER_STOP ) + { + if( !m_bTimerStopped ) + { + m_fStopTime = fTime; + m_fLastElapsedTime = fTime; + m_bTimerStopped = TRUE; + } + return 0.0f; + } + + // Advance the timer by 1/10th second + if( command == TIMER_ADVANCE ) + { + m_fStopTime += 0.1f; + return 0.0f; + } + + if( command == TIMER_GETABSOLUTETIME ) + { + return (FLOAT) fTime; + } + + return -1.0f; // Invalid command specified + } +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertAnsiStringToWideCch() +// Desc: This is a UNICODE conversion utility to convert a CHAR string into a +// WCHAR string. +// cchDestChar is the size in TCHARs of wstrDestination. Be careful not to +// pass in sizeof(strDest) +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertAnsiStringToWideCch( WCHAR* wstrDestination, const CHAR* strSource, + int cchDestChar ) +{ + if( wstrDestination==NULL || strSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + + int nResult = MultiByteToWideChar( CP_ACP, 0, strSource, -1, + wstrDestination, cchDestChar ); + wstrDestination[cchDestChar-1] = 0; + + if( nResult == 0 ) + return E_FAIL; + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertWideStringToAnsi() +// Desc: This is a UNICODE conversion utility to convert a WCHAR string into a +// CHAR string. +// cchDestChar is the size in TCHARs of strDestination +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertWideStringToAnsiCch( CHAR* strDestination, const WCHAR* wstrSource, + int cchDestChar ) +{ + if( strDestination==NULL || wstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + + int nResult = WideCharToMultiByte( CP_ACP, 0, wstrSource, -1, strDestination, + cchDestChar*sizeof(CHAR), NULL, NULL ); + strDestination[cchDestChar-1] = 0; + + if( nResult == 0 ) + return E_FAIL; + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertGenericStringToAnsi() +// Desc: This is a UNICODE conversion utility to convert a TCHAR string into a +// CHAR string. +// cchDestChar is the size in TCHARs of strDestination +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertGenericStringToAnsiCch( CHAR* strDestination, const TCHAR* tstrSource, + int cchDestChar ) +{ + if( strDestination==NULL || tstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + return DXUtil_ConvertWideStringToAnsiCch( strDestination, tstrSource, cchDestChar ); +#else + strncpy( strDestination, tstrSource, cchDestChar ); + strDestination[cchDestChar-1] = '\0'; + return S_OK; +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertGenericStringToWide() +// Desc: This is a UNICODE conversion utility to convert a TCHAR string into a +// WCHAR string. +// cchDestChar is the size in TCHARs of wstrDestination. Be careful not to +// pass in sizeof(strDest) +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertGenericStringToWideCch( WCHAR* wstrDestination, const TCHAR* tstrSource, + int cchDestChar ) +{ + if( wstrDestination==NULL || tstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + wcsncpy( wstrDestination, tstrSource, cchDestChar ); + wstrDestination[cchDestChar-1] = L'\0'; + return S_OK; +#else + return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, tstrSource, cchDestChar ); +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertAnsiStringToGeneric() +// Desc: This is a UNICODE conversion utility to convert a CHAR string into a +// TCHAR string. +// cchDestChar is the size in TCHARs of tstrDestination. Be careful not to +// pass in sizeof(strDest) on UNICODE builds +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertAnsiStringToGenericCch( TCHAR* tstrDestination, const CHAR* strSource, + int cchDestChar ) +{ + if( tstrDestination==NULL || strSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + return DXUtil_ConvertAnsiStringToWideCch( tstrDestination, strSource, cchDestChar ); +#else + strncpy( tstrDestination, strSource, cchDestChar ); + tstrDestination[cchDestChar-1] = '\0'; + return S_OK; +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertAnsiStringToGeneric() +// Desc: This is a UNICODE conversion utility to convert a WCHAR string into a +// TCHAR string. +// cchDestChar is the size in TCHARs of tstrDestination. Be careful not to +// pass in sizeof(strDest) on UNICODE builds +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertWideStringToGenericCch( TCHAR* tstrDestination, const WCHAR* wstrSource, + int cchDestChar ) +{ + if( tstrDestination==NULL || wstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + wcsncpy( tstrDestination, wstrSource, cchDestChar ); + tstrDestination[cchDestChar-1] = L'\0'; + return S_OK; +#else + return DXUtil_ConvertWideStringToAnsiCch( tstrDestination, wstrSource, cchDestChar ); +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_LaunchReadme() +// Desc: Finds and opens the readme for this sample +//----------------------------------------------------------------------------- +VOID DXUtil_LaunchReadme( HWND hWnd, LPCTSTR strLoc ) +{ +#ifdef UNDER_CE + // This is not available on PocketPC + MessageBox( hWnd, TEXT("For operating instructions, please open the ") + TEXT("readme.txt file included with the project."), + TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK ); + + return; +#endif + + const int NUM_FILENAMES = 2; + LPCTSTR strFilenames[] = + { + TEXT("readme.htm"), + TEXT("readme.txt") + }; + + TCHAR strReadmePath[1024]; + TCHAR strExeName[MAX_PATH]; + TCHAR strExePath[MAX_PATH]; + TCHAR strSamplePath[MAX_PATH]; + TCHAR* strLastSlash = NULL; + + for( int i=0; i < NUM_FILENAMES; i++ ) + { + LPCTSTR strFilename = strFilenames[i]; + bool bSuccess = false; + bool bFound = false; + + lstrcpy( strReadmePath, TEXT("") ); + lstrcpy( strExePath, TEXT("") ); + lstrcpy( strExeName, TEXT("") ); + lstrcpy( strSamplePath, TEXT("") ); + + // If the user provided a location for the readme, check there first. + if( strLoc ) + { + HKEY hKey; + LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\DirectX SDK"), + 0, KEY_READ, &hKey ); + if( ERROR_SUCCESS == lResult ) + { + DWORD dwType; + DWORD dwSize = MAX_PATH * sizeof(TCHAR); + lResult = RegQueryValueEx( hKey, _T("DX9S4SDK Samples Path"), NULL, + &dwType, (BYTE*)strSamplePath, &dwSize ); + strSamplePath[MAX_PATH-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small + + if( ERROR_SUCCESS == lResult ) + { + _sntprintf( strReadmePath, 1023, TEXT("%s\\C++\\%s\\%s"), + strSamplePath, strLoc, strFilename ); + strReadmePath[1023] = 0; + + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + } + + RegCloseKey( hKey ); + } + + // Get the exe name, and exe path + GetModuleFileName( NULL, strExePath, MAX_PATH ); + strExePath[MAX_PATH-1]=0; + + strLastSlash = _tcsrchr( strExePath, TEXT('\\') ); + if( strLastSlash ) + { + _tcsncpy( strExeName, &strLastSlash[1], MAX_PATH ); + strExeName[MAX_PATH-1]=0; + + // Chop the exe name from the exe path + *strLastSlash = 0; + + // Chop the .exe from the exe name + strLastSlash = _tcsrchr( strExeName, TEXT('.') ); + if( strLastSlash ) + *strLastSlash = 0; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\BumpMapping\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\BumpMapping\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\EnvMapping\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\EnvMapping\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\Meshes\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\Meshes\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\StencilBuffer\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\StencilBuffer\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\" + _tcscpy( strReadmePath, strExePath ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\.." + _tcscpy( strReadmePath, strExePath ); + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\.." + _tcscpy( strReadmePath, strExePath ); + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( bFound ) + { + // GetProcAddress for ShellExecute, so we don't have to include shell32.lib + // in every project that uses dxutil.cpp + LPShellExecute pShellExecute = NULL; + HINSTANCE hInstShell32 = LoadLibrary(TEXT("shell32.dlTEXT(")); + if (hInstShell32 != NULL) + { + #ifdef UNICODE + pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteW")); + #else + pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteA")); + #endif + if( pShellExecute != NULL ) + { + if( pShellExecute( hWnd, TEXT("open"), strReadmePath, NULL, NULL, SW_SHOW ) > (HINSTANCE) 32 ) + bSuccess = true; + } + + FreeLibrary(hInstShell32); + } + } + + if( bSuccess ) + return; + } + + // Tell the user that the readme couldn't be opened + MessageBox( hWnd, TEXT("Could not find readme"), + TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_Trace() +// Desc: Outputs to the debug stream a formatted string with a variable- +// argument list. +//----------------------------------------------------------------------------- +VOID DXUtil_Trace( LPCTSTR strMsg, ... ) +{ +#if defined(DEBUG) | defined(_DEBUG) + TCHAR strBuffer[512]; + + va_list args; + va_start(args, strMsg); + _vsntprintf( strBuffer, 512, strMsg, args ); + va_end(args); + + OutputDebugString( strBuffer ); +#else + UNREFERENCED_PARAMETER(strMsg); +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertStringToGUID() +// Desc: Converts a string to a GUID +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertStringToGUID( const TCHAR* strSrc, GUID* pGuidDest ) +{ + UINT aiTmp[10]; + + if( _stscanf( strSrc, TEXT("{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}"), + &pGuidDest->Data1, + &aiTmp[0], &aiTmp[1], + &aiTmp[2], &aiTmp[3], + &aiTmp[4], &aiTmp[5], + &aiTmp[6], &aiTmp[7], + &aiTmp[8], &aiTmp[9] ) != 11 ) + { + ZeroMemory( pGuidDest, sizeof(GUID) ); + return E_FAIL; + } + else + { + pGuidDest->Data2 = (USHORT) aiTmp[0]; + pGuidDest->Data3 = (USHORT) aiTmp[1]; + pGuidDest->Data4[0] = (BYTE) aiTmp[2]; + pGuidDest->Data4[1] = (BYTE) aiTmp[3]; + pGuidDest->Data4[2] = (BYTE) aiTmp[4]; + pGuidDest->Data4[3] = (BYTE) aiTmp[5]; + pGuidDest->Data4[4] = (BYTE) aiTmp[6]; + pGuidDest->Data4[5] = (BYTE) aiTmp[7]; + pGuidDest->Data4[6] = (BYTE) aiTmp[8]; + pGuidDest->Data4[7] = (BYTE) aiTmp[9]; + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertGUIDToStringCch() +// Desc: Converts a GUID to a string +// cchDestChar is the size in TCHARs of strDest. Be careful not to +// pass in sizeof(strDest) on UNICODE builds +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertGUIDToStringCch( const GUID* pGuidSrc, TCHAR* strDest, int cchDestChar ) +{ + int nResult = _sntprintf( strDest, cchDestChar, TEXT("{%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X}"), + pGuidSrc->Data1, pGuidSrc->Data2, pGuidSrc->Data3, + pGuidSrc->Data4[0], pGuidSrc->Data4[1], + pGuidSrc->Data4[2], pGuidSrc->Data4[3], + pGuidSrc->Data4[4], pGuidSrc->Data4[5], + pGuidSrc->Data4[6], pGuidSrc->Data4[7] ); + + if( nResult < 0 ) + return E_FAIL; + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList constructor +// Desc: +//----------------------------------------------------------------------------- +CArrayList::CArrayList( ArrayListType Type, UINT BytesPerEntry ) +{ + if( Type == AL_REFERENCE ) + BytesPerEntry = sizeof(void*); + m_ArrayListType = Type; + m_pData = NULL; + m_BytesPerEntry = BytesPerEntry; + m_NumEntries = 0; + m_NumEntriesAllocated = 0; +} + + + +//----------------------------------------------------------------------------- +// Name: CArrayList destructor +// Desc: +//----------------------------------------------------------------------------- +CArrayList::~CArrayList( void ) +{ + if( m_pData != NULL ) + delete[] m_pData; +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::Add +// Desc: Adds pEntry to the list. +//----------------------------------------------------------------------------- +HRESULT CArrayList::Add( void* pEntry ) +{ + if( m_BytesPerEntry == 0 ) + return E_FAIL; + if( m_pData == NULL || m_NumEntries + 1 > m_NumEntriesAllocated ) + { + void* pDataNew; + UINT NumEntriesAllocatedNew; + if( m_NumEntriesAllocated == 0 ) + NumEntriesAllocatedNew = 16; + else + NumEntriesAllocatedNew = m_NumEntriesAllocated * 2; + pDataNew = new BYTE[NumEntriesAllocatedNew * m_BytesPerEntry]; + if( pDataNew == NULL ) + return E_OUTOFMEMORY; + if( m_pData != NULL ) + { + CopyMemory( pDataNew, m_pData, m_NumEntries * m_BytesPerEntry ); + delete[] m_pData; + } + m_pData = pDataNew; + m_NumEntriesAllocated = NumEntriesAllocatedNew; + } + + if( m_ArrayListType == AL_VALUE ) + CopyMemory( (BYTE*)m_pData + (m_NumEntries * m_BytesPerEntry), pEntry, m_BytesPerEntry ); + else + *(((void**)m_pData) + m_NumEntries) = pEntry; + m_NumEntries++; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::Remove +// Desc: Remove the item at Entry in the list, and collapse the array. +//----------------------------------------------------------------------------- +void CArrayList::Remove( UINT Entry ) +{ + // Decrement count + m_NumEntries--; + + // Find the entry address + BYTE* pData = (BYTE*)m_pData + (Entry * m_BytesPerEntry); + + // Collapse the array + MoveMemory( pData, pData + m_BytesPerEntry, ( m_NumEntries - Entry ) * m_BytesPerEntry ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::GetPtr +// Desc: Returns a pointer to the Entry'th entry in the list. +//----------------------------------------------------------------------------- +void* CArrayList::GetPtr( UINT Entry ) +{ + if( m_ArrayListType == AL_VALUE ) + return (BYTE*)m_pData + (Entry * m_BytesPerEntry); + else + return *(((void**)m_pData) + Entry); +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::Contains +// Desc: Returns whether the list contains an entry identical to the +// specified entry data. +//----------------------------------------------------------------------------- +bool CArrayList::Contains( void* pEntryData ) +{ + for( UINT iEntry = 0; iEntry < m_NumEntries; iEntry++ ) + { + if( m_ArrayListType == AL_VALUE ) + { + if( memcmp( GetPtr(iEntry), pEntryData, m_BytesPerEntry ) == 0 ) + return true; + } + else + { + if( GetPtr(iEntry) == pEntryData ) + return true; + } + } + return false; +} + + + + +//----------------------------------------------------------------------------- +// Name: BYTE helper functions +// Desc: cchDestChar is the size in BYTEs of strDest. Be careful not to +// pass use sizeof() if the strDest is a string pointer. +// eg. +// TCHAR* sz = new TCHAR[100]; // sizeof(sz) == 4 +// TCHAR sz2[100]; // sizeof(sz2) == 200 +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertAnsiStringToWideCb( WCHAR* wstrDestination, const CHAR* strSource, int cbDestChar ) +{ + return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, strSource, cbDestChar / sizeof(WCHAR) ); +} + +HRESULT DXUtil_ConvertWideStringToAnsiCb( CHAR* strDestination, const WCHAR* wstrSource, int cbDestChar ) +{ + return DXUtil_ConvertWideStringToAnsiCch( strDestination, wstrSource, cbDestChar / sizeof(CHAR) ); +} + +HRESULT DXUtil_ConvertGenericStringToAnsiCb( CHAR* strDestination, const TCHAR* tstrSource, int cbDestChar ) +{ + return DXUtil_ConvertGenericStringToAnsiCch( strDestination, tstrSource, cbDestChar / sizeof(CHAR) ); +} + +HRESULT DXUtil_ConvertGenericStringToWideCb( WCHAR* wstrDestination, const TCHAR* tstrSource, int cbDestChar ) +{ + return DXUtil_ConvertGenericStringToWideCch( wstrDestination, tstrSource, cbDestChar / sizeof(WCHAR) ); +} + +HRESULT DXUtil_ConvertAnsiStringToGenericCb( TCHAR* tstrDestination, const CHAR* strSource, int cbDestChar ) +{ + return DXUtil_ConvertAnsiStringToGenericCch( tstrDestination, strSource, cbDestChar / sizeof(TCHAR) ); +} + +HRESULT DXUtil_ConvertWideStringToGenericCb( TCHAR* tstrDestination, const WCHAR* wstrSource, int cbDestChar ) +{ + return DXUtil_ConvertWideStringToGenericCch( tstrDestination, wstrSource, cbDestChar / sizeof(TCHAR) ); +} + +HRESULT DXUtil_ReadStringRegKeyCb( HKEY hKey, LPCTSTR strRegName, TCHAR* strDest, DWORD cbDest, LPCTSTR strDefault ) +{ + return DXUtil_ReadStringRegKeyCch( hKey, strRegName, strDest, cbDest / sizeof(TCHAR), strDefault ); +} + +HRESULT DXUtil_ConvertGUIDToStringCb( const GUID* pGuidSrc, TCHAR* strDest, int cbDestChar ) +{ + return DXUtil_ConvertGUIDToStringCch( pGuidSrc, strDest, cbDestChar / sizeof(TCHAR) ); +} + +#ifndef UNDER_CE +HRESULT DXUtil_GetDXSDKMediaPathCb( TCHAR* szDest, int cbDest ) +{ + return DXUtil_GetDXSDKMediaPathCch( szDest, cbDest / sizeof(TCHAR) ); +} + +HRESULT DXUtil_FindMediaFileCb( TCHAR* szDestPath, int cbDest, LPCTSTR strFilename ) +{ + return DXUtil_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename ); +} +#endif // !UNDER_CE diff --git a/saco/game/common.h b/saco/game/common.h index db41a12..98d591e 100644 --- a/saco/game/common.h +++ b/saco/game/common.h @@ -88,8 +88,8 @@ typedef struct _ENTITY_TYPE MATRIX4X4 *mat; // 20-24 DWORD *pdwRenderWare; // 24-28 - - char _gap1C[6]; + DWORD dwProcessingFlags; // 28-32 + char _gap20[2]; WORD nModelIndex; // 34-36 char _gap24[18]; diff --git a/saco/game/game.cpp b/saco/game/game.cpp index 068ef0d..ce5ffb4 100644 --- a/saco/game/game.cpp +++ b/saco/game/game.cpp @@ -816,6 +816,20 @@ void CGame::AddToLocalMoney(int iAmount) //----------------------------------------------------------- +void CGame::ResetLocalMoney() +{ + int iMoney = GetLocalMoney(); + if(!iMoney) return; + + if(iMoney < 0) { + AddToLocalMoney(abs(iMoney)); + } else { + AddToLocalMoney(-(iMoney)); + } +} + +//----------------------------------------------------------- + int CGame::GetLocalMoney() { return *(int *)0xB7CE50; diff --git a/saco/game/game.h b/saco/game/game.h index 7c80fe1..8b3e70f 100644 --- a/saco/game/game.h +++ b/saco/game/game.h @@ -3,7 +3,9 @@ #include "address.h" #include "common.h" +#include "vehicle.h" #include "playerped.h" +#include "actorped.h" #include "audio.h" #include "camera.h" #include "scripting.h" @@ -81,6 +83,7 @@ public: void DisableMarker(DWORD dwMarkerID); void AddToLocalMoney(int iAmount); + void ResetLocalMoney(); int GetLocalMoney(); BYTE GetActiveInterior(); @@ -97,6 +100,8 @@ public: //----------------------------------------------------------- + CCamera *GetCamera() { return m_pGameCamera; }; + void FUNC_10062570() { field_55++; }; CPlayerPed *FindPlayerPed() { diff --git a/saco/main.h b/saco/main.h index c6d4035..d7397e8 100644 --- a/saco/main.h +++ b/saco/main.h @@ -7,6 +7,9 @@ #define SAFE_DELETE(p) { if (p) { delete (p); (p) = NULL; } } +#define IDC_CMDEDIT 1 + +#define MAX_PLAYER_NAME 24 #define MAX_SETTINGS_STRING 256 #define GTASA_VERSION_UNKNOWN 0 @@ -29,6 +32,7 @@ typedef struct _GAME_SETTINGS { #include "d3d9/include/d3d9.h" #include "d3d9/include/d3dx9core.h" +#include "d3d9/common/dxstdafx.h" #include "game/game.h" #include "../raknet/RakClientInterface.h" diff --git a/saco/net/localplayer.cpp b/saco/net/localplayer.cpp index f4b4cb4..72d13da 100644 --- a/saco/net/localplayer.cpp +++ b/saco/net/localplayer.cpp @@ -3,6 +3,7 @@ #include "../game/util.h" extern CGame *pGame; +extern CNetGame *pNetGame; //---------------------------------------------------------- diff --git a/saco/net/netgame.h b/saco/net/netgame.h index 62967e0..9c52196 100644 --- a/saco/net/netgame.h +++ b/saco/net/netgame.h @@ -76,6 +76,8 @@ public: BOOL GetWalkStyle() { return field_3D5->bUseCJWalk; }; CPlayerPool * GetPlayerPool() { return m_pPools->pPlayerPool; }; + CGangZonePool * GetGangZonePool() { return m_pPools->pGangZonePool; }; + RakClientInterface * GetRakClient() { return m_pRakClient; }; void ResetMapIcons(); void SetMapIcon(BYTE byteIndex, float fX, float fY, float fZ, BYTE byteIcon, DWORD dwColor, int iStyle); diff --git a/saco/net/netrpc.cpp b/saco/net/netrpc.cpp index 7c98a84..798cdaf 100644 --- a/saco/net/netrpc.cpp +++ b/saco/net/netrpc.cpp @@ -17,13 +17,13 @@ void GameModeRestart(RPCParameters *rpcParams) {} void ConnectionRejected(RPCParameters *rpcParams) {} void ClientMessage(RPCParameters *rpcParams) {} void WorldTime(RPCParameters *rpcParams) {} -void Unk5F(RPCParameters *rpcParams) {} -void Unk3F(RPCParameters *rpcParams) {} -void Unk97(RPCParameters *rpcParams) {} +void Pickup(RPCParameters *rpcParams) {} +void DestroyPickup(RPCParameters *rpcParams) {} +void DestroyWeaponPickup(RPCParameters *rpcParams) {} void ScmEvent(RPCParameters *rpcParams) {} void Weather(RPCParameters *rpcParams) {} -void Unk1D(RPCParameters *rpcParams) {} -void Unk1E(RPCParameters *rpcParams) {} +void SetTimeEx(RPCParameters *rpcParams) {} +void ToggleClock(RPCParameters *rpcParams) {} void Unk3C(RPCParameters *rpcParams) {} void WorldPlayerAdd(RPCParameters *rpcParams) {} void WorldPlayerDeath(RPCParameters *rpcParams) {} @@ -68,13 +68,13 @@ void RegisterRPCs(RakClientInterface * pRakClient) REGISTER_STATIC_RPC(pRakClient,ConnectionRejected); REGISTER_STATIC_RPC(pRakClient,ClientMessage); REGISTER_STATIC_RPC(pRakClient,WorldTime); - REGISTER_STATIC_RPC(pRakClient,Unk5F); - REGISTER_STATIC_RPC(pRakClient,Unk3F); - REGISTER_STATIC_RPC(pRakClient,Unk97); + REGISTER_STATIC_RPC(pRakClient,Pickup); + REGISTER_STATIC_RPC(pRakClient,DestroyPickup); + REGISTER_STATIC_RPC(pRakClient,DestroyWeaponPickup); REGISTER_STATIC_RPC(pRakClient,ScmEvent); REGISTER_STATIC_RPC(pRakClient,Weather); - REGISTER_STATIC_RPC(pRakClient,Unk1D); - REGISTER_STATIC_RPC(pRakClient,Unk1E); + REGISTER_STATIC_RPC(pRakClient,SetTimeEx); + REGISTER_STATIC_RPC(pRakClient,ToggleClock); REGISTER_STATIC_RPC(pRakClient,Unk3C); REGISTER_STATIC_RPC(pRakClient,WorldPlayerAdd); REGISTER_STATIC_RPC(pRakClient,WorldPlayerDeath); @@ -136,13 +136,13 @@ void UnRegisterRPCs(RakClientInterface * pRakClient) UNREGISTER_STATIC_RPC(pRakClient,ConnectionRejected); UNREGISTER_STATIC_RPC(pRakClient,ClientMessage); UNREGISTER_STATIC_RPC(pRakClient,WorldTime); - UNREGISTER_STATIC_RPC(pRakClient,Unk5F); - UNREGISTER_STATIC_RPC(pRakClient,Unk3F); - UNREGISTER_STATIC_RPC(pRakClient,Unk97); + UNREGISTER_STATIC_RPC(pRakClient,Pickup); + UNREGISTER_STATIC_RPC(pRakClient,DestroyPickup); + UNREGISTER_STATIC_RPC(pRakClient,DestroyWeaponPickup); UNREGISTER_STATIC_RPC(pRakClient,ScmEvent); UNREGISTER_STATIC_RPC(pRakClient,Weather); - UNREGISTER_STATIC_RPC(pRakClient,Unk1D); - UNREGISTER_STATIC_RPC(pRakClient,Unk1E); + UNREGISTER_STATIC_RPC(pRakClient,SetTimeEx); + UNREGISTER_STATIC_RPC(pRakClient,ToggleClock); UNREGISTER_STATIC_RPC(pRakClient,EditAttachedObject); UNREGISTER_STATIC_RPC(pRakClient,EditObject); UNREGISTER_STATIC_RPC(pRakClient,SelectObject); diff --git a/saco/net/playerpool.h b/saco/net/playerpool.h index bb777c9..50a7d66 100644 --- a/saco/net/playerpool.h +++ b/saco/net/playerpool.h @@ -3,6 +3,8 @@ #include +#define INVALID_PLAYER_ID 0xFFFF + //---------------------------------------------------- class CPlayerPool diff --git a/saco/net/remoteplayer.cpp b/saco/net/remoteplayer.cpp index 48eeb0a..77489b1 100644 --- a/saco/net/remoteplayer.cpp +++ b/saco/net/remoteplayer.cpp @@ -13,7 +13,7 @@ CRemotePlayer::CRemotePlayer() { field_1E7 = 0; field_10A = 0; - field_1E5 = -1; + m_PlayerID = INVALID_PLAYER_ID; field_1DD = 0; field_1B8 = 0; field_109 = -1; diff --git a/saco/net/remoteplayer.h b/saco/net/remoteplayer.h index ea40118..ceb3f5f 100644 --- a/saco/net/remoteplayer.h +++ b/saco/net/remoteplayer.h @@ -43,7 +43,7 @@ private: DWORD field_1D9; int field_1DD; int field_1E1; - short field_1E5; + PLAYERID m_PlayerID; short field_1E7; int field_1E9; int field_1ED; diff --git a/saco/saco.vcproj b/saco/saco.vcproj index cd9c9a1..fd6c7c9 100644 --- a/saco/saco.vcproj +++ b/saco/saco.vcproj @@ -192,6 +192,12 @@ + + + + @@ -228,6 +234,12 @@ + + + + + + + + @@ -899,6 +917,12 @@ + + + +