This commit is contained in:
nephacks 2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

319
.gitignore vendored
View File

@ -1,34 +1,301 @@
# ---> C++
# Prerequisites
*.d
#Ignore my HL2 Install Directory
/HL2_base/
# Compiled Object files
*.slo
*.lo
*.o
#Ignore the sapi folder.
src/utils/sapi51/
#Specifically Ignore Builds
game/*/bin/
game/bin/*.exe
game/bin/*.dll
game/bin/*/*.dll
installer/files/hlvr/bin/
installer/output/*.exe
installer/output/*.zip
#Not Marulu's DLL
!d3d9.dll
#Ignore list, made of the many untracked files
game/*/cfg/config.cfg
game/*/cfg/server_blacklist.txt
game/*/gamestate.txt
game/*/maps/graphs/
game/*/save/
game/*/screenshots/
game/*/downloadlists/
game/*/stats.txt
game/*/voice_ban.dt
src/game/client/Release_*/
src/game/server/Release_*/
mapdev/
decompiled 0.42/
*.sentinel
#Lib files that are generated by game.sln
src/lib/public/mathlib.lib
src/lib/public/raytrace.lib
src/lib/public/tier1.lib
src/lib/public/vgui_controls.lib
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug_*/
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease_*/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
# Precompiled Headers
*.gch
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Chutzpah Test files
_Chutzpah*
# Fortran module files
*.mod
*.smod
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Executables
*.exe
*.out
*.app
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# Solutions must be rebuilt by each user, per-machine
*.vcxproj
*.vcxproj.filters
*.vcxproj.vpc_crc
*.sln

View File

@ -0,0 +1,5 @@
In steam console type
download_depot 730 731 7043469183016184477
download_depot 730 732 4047004309608881181
Then move those directories to the appropriate place

2
CreateSolution.bat Normal file
View File

@ -0,0 +1,2 @@
devtools\bin\vpc.exe /csgo +csgo_partner /mksln csgo_partner.sln
pause

View File

@ -0,0 +1,982 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a group of app systems that all have the same lifetime
// that need to be connected/initialized, etc. in a well-defined order
//
// $Revision: $
// $NoKeywords: $
//===========================================================================//
#include "tier0/platform.h"
#include "appframework/ilaunchermgr.h"
#if defined( PLATFORM_PS3)
#include "ps3/ps3_helpers.h"
#endif
#include "tier0/platwindow.h"
#include "appframework/IAppSystemGroup.h"
#include "appframework/iappsystem.h"
#include "interface.h"
#include "filesystem.h"
#include "filesystem_init.h"
#include <algorithm>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
extern ILoggingListener *g_pDefaultLoggingListener;
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CAppSystemGroup::CAppSystemGroup( CAppSystemGroup *pAppSystemParent ) : m_SystemDict(false, 0, 16)
{
m_pParentAppSystem = pAppSystemParent;
}
//-----------------------------------------------------------------------------
// Actually loads a DLL
//-----------------------------------------------------------------------------
CSysModule *CAppSystemGroup::LoadModuleDLL( const char *pDLLName )
{
return Sys_LoadModule( pDLLName );
}
//-----------------------------------------------------------------------------
// Methods to load + unload DLLs
//-----------------------------------------------------------------------------
AppModule_t CAppSystemGroup::LoadModule( const char *pDLLName )
{
// Remove the extension when creating the name.
int nLen = Q_strlen( pDLLName ) + 1;
char *pModuleName = (char*)stackalloc( nLen );
Q_StripExtension( pDLLName, pModuleName, nLen );
// See if we already loaded it...
for ( int i = m_Modules.Count(); --i >= 0; )
{
if ( m_Modules[i].m_pModuleName )
{
if ( !Q_stricmp( pModuleName, m_Modules[i].m_pModuleName ) )
return i;
}
}
CSysModule *pSysModule = LoadModuleDLL( pDLLName );
if (!pSysModule)
{
#ifdef _X360
Warning("AppFramework : Unable to load module %s! (err #%d)\n", pDLLName, GetLastError() );
#else
Warning("AppFramework : Unable to load module %s!\n", pDLLName );
#endif
return APP_MODULE_INVALID;
}
int nIndex = m_Modules.AddToTail();
m_Modules[nIndex].m_pModule = pSysModule;
m_Modules[nIndex].m_Factory = 0;
m_Modules[nIndex].m_pModuleName = (char*)malloc( nLen );
Q_strncpy( m_Modules[nIndex].m_pModuleName, pModuleName, nLen );
return nIndex;
}
int CAppSystemGroup::ReloadModule( const char * pDLLName )
{
// Remove the extension when creating the name.
int nLen = Q_strlen( pDLLName ) + 1;
char *pModuleName = (char*)stackalloc( nLen );
Q_StripExtension( pDLLName, pModuleName, nLen );
// See if we already loaded it...
for ( int i = m_Modules.Count(); --i >= 0; )
{
Module_t &module = m_Modules[i];
if ( module.m_pModuleName && !Q_stricmp( pModuleName, module.m_pModuleName ) )
{
// found the module, reload
Msg("Unloading module %s, dll %s\n", pModuleName, pDLLName );
Sys_UnloadModule( m_Modules[i].m_pModule );
Msg("Module %s unloaded, reloading\n", pModuleName );
CSysModule *pSysModule = NULL;
CreateInterfaceFn fnFactory = NULL;
while( !pSysModule )
{
pSysModule = LoadModuleDLL( pDLLName );
if( !pSysModule )
{
Warning("Cannot load, retrying in 5 seconds..\n");
ThreadSleep( 5000 );
}
fnFactory = Sys_GetFactory( pSysModule ) ;
if( !fnFactory )
{
Error( "Could not get factory from %s\n", pModuleName );
}
( *fnFactory )( "Reload Interface", NULL ); // let the CreateInterface function work and do after-reload stuff
}
Msg( "Reload complete, module %p->%p, factory %llx->%llx\n", module.m_pModule, pSysModule, (uint64)(uintp)module.m_Factory, (uint64)(uintp)fnFactory );
module.m_pModule = pSysModule;
if( module.m_Factory )
{ // don't reload factory pointer unless it was initialized to non-NULL
module.m_Factory = fnFactory;
}
return 0; // no error
}
}
Warning( "No such module: '%s' in appsystem @%p. Dumping available modules:\n", pModuleName, this );
for ( int i = 0; i < m_Modules.Count(); ++i )
{
Module_t &module = m_Modules[i];
#ifdef _PS3
Msg( "%25s %llx %p %6d %6d bytes\n", module.m_pModuleName, (uint64)module.m_Factory, module.m_pModule, ( ( PS3_PrxLoadParametersBase_t *)module.m_pModule )->sysPrxId, ( ( PS3_PrxLoadParametersBase_t *)module.m_pModule )->cbSize );
#else
Msg("%25s %p %p\n", module.m_pModuleName, (void*)module.m_Factory, module.m_pModule );
#endif
}
return m_pParentAppSystem ? m_pParentAppSystem->ReloadModule( pDLLName ) : -1;
}
AppModule_t CAppSystemGroup::LoadModule( CreateInterfaceFn factory )
{
if (!factory)
{
Warning("AppFramework : Unable to load module %p!\n", factory );
return APP_MODULE_INVALID;
}
// See if we already loaded it...
for ( int i = m_Modules.Count(); --i >= 0; )
{
if ( m_Modules[i].m_Factory )
{
if ( m_Modules[i].m_Factory == factory )
return i;
}
}
int nIndex = m_Modules.AddToTail();
m_Modules[nIndex].m_pModule = NULL;
m_Modules[nIndex].m_Factory = factory;
m_Modules[nIndex].m_pModuleName = NULL;
return nIndex;
}
void CAppSystemGroup::UnloadAllModules()
{
// NOTE: Iterate in reverse order so they are unloaded in opposite order
// from loading
for (int i = m_Modules.Count(); --i >= 0; )
{
if ( m_Modules[i].m_pModule )
{
Sys_UnloadModule( m_Modules[i].m_pModule );
}
if ( m_Modules[i].m_pModuleName )
{
free( m_Modules[i].m_pModuleName );
}
}
m_Modules.RemoveAll();
}
//-----------------------------------------------------------------------------
// Methods to add/remove various global singleton systems
//-----------------------------------------------------------------------------
IAppSystem *CAppSystemGroup::AddSystem( AppModule_t module, const char *pInterfaceName )
{
if (module == APP_MODULE_INVALID)
return NULL;
int nFoundIndex = m_SystemDict.Find( pInterfaceName );
if ( nFoundIndex != m_SystemDict.InvalidIndex() )
{
Warning("AppFramework : Attempted to add two systems with the same interface name %s!\n", pInterfaceName );
return m_Systems[ m_SystemDict[nFoundIndex] ];
}
Assert( (module >= 0) && (module < m_Modules.Count()) );
CreateInterfaceFn pFactory = m_Modules[module].m_pModule ? Sys_GetFactory( m_Modules[module].m_pModule ) : m_Modules[module].m_Factory;
int retval;
void *pSystem = pFactory( pInterfaceName, &retval );
if ((retval != IFACE_OK) || (!pSystem))
{
Warning("AppFramework : Unable to create system %s!\n", pInterfaceName );
return NULL;
}
IAppSystem *pAppSystem = static_cast<IAppSystem*>(pSystem);
int sysIndex = m_Systems.AddToTail( pAppSystem );
// Inserting into the dict will help us do named lookup later
MEM_ALLOC_CREDIT();
m_SystemDict.Insert( pInterfaceName, sysIndex );
return pAppSystem;
}
static const char *g_StageLookup[] =
{
"CREATION",
"LOADING DEPENDENCIES",
"CONNECTION",
"PREINITIALIZATION",
"INITIALIZATION",
"POSTINITIALIZATION",
"RUNNING",
"PRESHUTDOWN",
"SHUTDOWN",
"POSTSHUTDOWN",
"DISCONNECTION",
"DESTRUCTION",
};
void CAppSystemGroup::ReportStartupFailure( int nErrorStage, int nSysIndex )
{
COMPILE_TIME_ASSERT( APPSYSTEM_GROUP_STAGE_COUNT == ARRAYSIZE( g_StageLookup ) );
const char *pszStageDesc = "Unknown";
if ( nErrorStage >= 0 && nErrorStage < ( int )ARRAYSIZE( g_StageLookup ) )
{
pszStageDesc = g_StageLookup[ nErrorStage ];
}
const char *pszSystemName = "(Unknown)";
for ( int i = m_SystemDict.First(); i != m_SystemDict.InvalidIndex(); i = m_SystemDict.Next( i ) )
{
if ( m_SystemDict[ i ] != nSysIndex )
continue;
pszSystemName = m_SystemDict.GetElementName( i );
break;
}
// Walk the dictionary
Warning( "System (%s) failed during stage %s\n", pszSystemName, pszStageDesc );
}
void CAppSystemGroup::AddSystem( IAppSystem *pAppSystem, const char *pInterfaceName )
{
if ( !pAppSystem )
return;
int sysIndex = m_Systems.AddToTail( pAppSystem );
// Inserting into the dict will help us do named lookup later
MEM_ALLOC_CREDIT();
m_SystemDict.Insert( pInterfaceName, sysIndex );
}
void CAppSystemGroup::RemoveAllSystems()
{
// NOTE: There's no deallcation here since we don't really know
// how the allocation has happened. We could add a deallocation method
// to the code in interface.h; although when the modules are unloaded
// the deallocation will happen anyways
m_Systems.RemoveAll();
m_SystemDict.RemoveAll();
}
//-----------------------------------------------------------------------------
// Simpler method of doing the LoadModule/AddSystem thing.
//-----------------------------------------------------------------------------
bool CAppSystemGroup::AddSystems( AppSystemInfo_t *pSystemList )
{
while ( pSystemList->m_pModuleName[0] )
{
AppModule_t module = LoadModule( pSystemList->m_pModuleName );
IAppSystem *pSystem = AddSystem( module, pSystemList->m_pInterfaceName );
if ( !pSystem )
{
Warning( "Unable to load interface %s from %s, requested from EXE.\n", pSystemList->m_pInterfaceName, pSystemList->m_pModuleName );
return false;
}
++pSystemList;
}
return true;
}
//-----------------------------------------------------------------------------
// Methods to find various global singleton systems
//-----------------------------------------------------------------------------
void *CAppSystemGroup::FindSystem( const char *pSystemName )
{
unsigned short i = m_SystemDict.Find( pSystemName );
if (i != m_SystemDict.InvalidIndex())
return m_Systems[m_SystemDict[i]];
// If it's not an interface we know about, it could be an older
// version of an interface, or maybe something implemented by
// one of the instantiated interfaces...
// QUESTION: What order should we iterate this in?
// It controls who wins if multiple ones implement the same interface
for ( i = 0; i < m_Systems.Count(); ++i )
{
void *pInterface = m_Systems[i]->QueryInterface( pSystemName );
if (pInterface)
return pInterface;
}
int nExternalCount = m_NonAppSystemFactories.Count();
for ( i = 0; i < nExternalCount; ++i )
{
void *pInterface = m_NonAppSystemFactories[i]( pSystemName, NULL );
if (pInterface)
return pInterface;
}
if ( m_pParentAppSystem )
{
void* pInterface = m_pParentAppSystem->FindSystem( pSystemName );
if ( pInterface )
return pInterface;
}
// No dice..
return NULL;
}
//-----------------------------------------------------------------------------
// Adds a factory to the system so other stuff can query it. Triggers a connect systems
//-----------------------------------------------------------------------------
void CAppSystemGroup::AddNonAppSystemFactory( CreateInterfaceFn fn )
{
m_NonAppSystemFactories.AddToTail( fn );
}
//-----------------------------------------------------------------------------
// Removes a factory, triggers a disconnect call if it succeeds
//-----------------------------------------------------------------------------
void CAppSystemGroup::RemoveNonAppSystemFactory( CreateInterfaceFn fn )
{
m_NonAppSystemFactories.FindAndRemove( fn );
}
//-----------------------------------------------------------------------------
// Causes the systems to reconnect to an interface
//-----------------------------------------------------------------------------
void CAppSystemGroup::ReconnectSystems( const char *pInterfaceName )
{
// Let the libraries regrab the specified interface
for (int i = 0; i < m_Systems.Count(); ++i )
{
IAppSystem *pSystem = m_Systems[i];
pSystem->Reconnect( GetFactory(), pInterfaceName );
}
}
//-----------------------------------------------------------------------------
// Gets at the parent appsystem group
//-----------------------------------------------------------------------------
CAppSystemGroup *CAppSystemGroup::GetParent()
{
return m_pParentAppSystem;
}
//-----------------------------------------------------------------------------
// Deals with sorting dependencies and finding circular dependencies
//-----------------------------------------------------------------------------
void CAppSystemGroup::ComputeDependencies( LibraryDependencies_t &depend )
{
bool bDone = false;
while ( !bDone )
{
bDone = true;
// If i depends on j, then i depends on what j depends on
// Add secondary dependencies to i. We stop when no dependencies are added
int nCount = depend.GetNumStrings();
for ( int i = 0; i < nCount; ++i )
{
int nDependentCount = depend[i].GetNumStrings();
for ( int j = 0; j < nDependentCount; ++j )
{
int nIndex = depend.Find( depend[i].String( j ) );
if ( nIndex == UTL_INVAL_SYMBOL )
continue;
int nSecondaryDepCount = depend[nIndex].GetNumStrings();
for ( int k = 0; k < nSecondaryDepCount; ++k )
{
// Don't bother if we already contain the secondary dependency
const char *pSecondaryDependency = depend[nIndex].String( k );
if ( depend[i].Find( pSecondaryDependency ) != UTL_INVAL_SYMBOL )
continue;
// Check for circular dependency
if ( !Q_stricmp( pSecondaryDependency, depend.String( i ) ) )
{
Warning( "Encountered a circular dependency with library %s!\n", pSecondaryDependency );
continue;
}
bDone = false;
depend[i].AddString( pSecondaryDependency );
nDependentCount = depend[i].GetNumStrings();
}
}
}
}
}
//-----------------------------------------------------------------------------
// Sorts dependencies
//-----------------------------------------------------------------------------
CAppSystemGroup::LibraryDependencies_t *CAppSystemGroup::sm_pSortDependencies;
bool CAppSystemGroup::SortLessFunc( const int &left, const int &right )
{
const char *pLeftInterface = sm_pSortDependencies->String( left );
const char *pRightInterface = sm_pSortDependencies->String( right );
bool bRightDependsOnLeft = ( (*sm_pSortDependencies)[pRightInterface].Find( pLeftInterface ) != UTL_INVAL_SYMBOL );
return ( bRightDependsOnLeft );
}
void CAppSystemGroup::SortDependentLibraries( LibraryDependencies_t &depend )
{
int nCount = depend.GetNumStrings();
int *pIndices = (int*)stackalloc( depend.GetNumStrings() * sizeof(int) );
for ( int i = 0; i < nCount; ++i )
{
pIndices[i] = i;
}
// Sort by dependency. Can't use fancy stl algorithms here because the sort func isn't strongly transitive.
// Using lame bubble sort instead. We could speed this up using a proper depth-first graph walk, but it's not worth the effort.
sm_pSortDependencies = &depend;
bool bChanged = true;
while ( bChanged )
{
bChanged = false;
for ( int i = 1; i < nCount; i++ )
{
for ( int j = 0; j < i; j++ )
{
if ( SortLessFunc( pIndices[i], pIndices[j] ) )
{
int nTmp = pIndices[i];
pIndices[i] = pIndices[j];
pIndices[j] = nTmp;
bChanged = true;
}
}
}
}
sm_pSortDependencies = NULL;
// This logic will make it so it respects the specified initialization order
// in the face of no dependencies telling the system otherwise.
// Doing this just for safety to reduce the amount of changed code
bool bDone = false;
while ( !bDone )
{
bDone = true;
for ( int i = 1; i < nCount; ++i )
{
int nLeft = pIndices[i-1];
int nRight = pIndices[i];
if ( nRight > nLeft )
continue;
const char *pLeftInterface = depend.String( nLeft );
const char *pRightInterface = depend.String( nRight );
bool bRightDependsOnLeft = ( depend[pRightInterface].Find( pLeftInterface ) != UTL_INVAL_SYMBOL );
if ( bRightDependsOnLeft )
continue;
Assert ( UTL_INVAL_SYMBOL == depend[pRightInterface].Find( pLeftInterface ) );
V_swap( pIndices[i], pIndices[i-1] );
bDone = false;
}
}
// Reorder appsystem list + dictionary indexing
Assert( m_Systems.Count() == nCount );
int nTempSize = nCount * sizeof(IAppSystem*);
IAppSystem **pTemp = (IAppSystem**)stackalloc( nTempSize );
memcpy( pTemp, m_Systems.Base(), nTempSize );
for ( int i = 0; i < nCount; ++i )
{
m_Systems[i] = pTemp[ pIndices[i] ];
}
// Remap system indices
for ( uint16 i = m_SystemDict.First(); i != m_SystemDict.InvalidIndex(); i = m_SystemDict.Next( i ) )
{
int j = 0;
for ( ; j < nCount; ++j )
{
if ( pIndices[j] == m_SystemDict[i] )
{
m_SystemDict[i] = j;
break;
}
}
Assert( j != nCount );
}
( void )stackfree( pTemp );
( void )stackfree( pIndices );
}
//-----------------------------------------------------------------------------
// Finds appsystem names
//-----------------------------------------------------------------------------
const char *CAppSystemGroup::FindSystemName( int nIndex )
{
for ( uint16 i = m_SystemDict.First(); i != m_SystemDict.InvalidIndex(); i = m_SystemDict.Next( i ) )
{
if ( m_SystemDict[i] == nIndex )
return m_SystemDict.GetElementName( i );
}
return NULL;
}
//-----------------------------------------------------------------------------
// Method to load all dependent systems
//-----------------------------------------------------------------------------
bool CAppSystemGroup::LoadDependentSystems()
{
LibraryDependencies_t dependencies;
// First, load dependencies.
for ( int i = 0; i < m_Systems.Count(); ++i )
{
IAppSystem *pSystem = m_Systems[i];
const char *pInterfaceName = FindSystemName( i );
dependencies.AddString( pInterfaceName );
const AppSystemInfo_t *pDependencies = pSystem->GetDependencies();
if ( !pDependencies )
continue;
for ( ; pDependencies->m_pInterfaceName && pDependencies->m_pInterfaceName[0]; ++pDependencies )
{
dependencies[ pInterfaceName ].AddString( pDependencies->m_pInterfaceName );
CreateInterfaceFn factory = GetFactory();
if ( factory( pDependencies->m_pInterfaceName, NULL ) )
continue;
AppModule_t module = LoadModule( pDependencies->m_pModuleName );
IAppSystem *pSystem = AddSystem( module, pDependencies->m_pInterfaceName );
if ( !pSystem )
{
Warning( "Unable to load interface %s from %s (Dependency of %s)\n", pDependencies->m_pInterfaceName, pDependencies->m_pModuleName, pInterfaceName );
return false;
}
}
}
ComputeDependencies( dependencies );
SortDependentLibraries( dependencies );
return true;
}
//-----------------------------------------------------------------------------
// Method to connect/disconnect all systems
//-----------------------------------------------------------------------------
bool CAppSystemGroup::ConnectSystems()
{
// Let the libraries grab any other interfaces they may need
for (int i = 0; i < m_Systems.Count(); ++i )
{
IAppSystem *pSystem = m_Systems[i];
if ( !pSystem->Connect( GetFactory() ) )
{
ReportStartupFailure( CONNECTION, i );
return false;
}
}
return true;
}
void CAppSystemGroup::DisconnectSystems()
{
// Disconnect in reverse order of connection
for (int i = m_Systems.Count(); --i >= 0; )
{
m_Systems[i]->Disconnect();
}
}
//-----------------------------------------------------------------------------
// Method to initialize/shutdown all systems
//-----------------------------------------------------------------------------
InitReturnVal_t CAppSystemGroup::InitSystems()
{
for (int nSystemsInitialized = 0; nSystemsInitialized < m_Systems.Count(); ++nSystemsInitialized )
{
InitReturnVal_t nRetVal = m_Systems[nSystemsInitialized]->Init();
if ( nRetVal != INIT_OK )
{
for( int nSystemsRewind = nSystemsInitialized; nSystemsRewind-->0; )
{
m_Systems[nSystemsRewind]->Shutdown();
}
ReportStartupFailure( INITIALIZATION, nSystemsInitialized );
return nRetVal;
}
}
return INIT_OK;
}
void CAppSystemGroup::ShutdownSystems()
{
// Shutdown in reverse order of initialization
for (int i = m_Systems.Count(); --i >= 0; )
{
m_Systems[i]->Shutdown();
}
}
//-----------------------------------------------------------------------------
// Window management
//-----------------------------------------------------------------------------
void* CAppSystemGroup::CreateAppWindow( void *hInstance, const char *pTitle, bool bWindowed, int w, int h, bool bResizing )
{
#if defined( PLATFORM_WINDOWS ) || defined( PLATFORM_OSX )
int nFlags = 0;
if ( !bWindowed )
{
nFlags |= WINDOW_CREATE_FULLSCREEN;
}
if ( bResizing )
{
nFlags |= WINDOW_CREATE_RESIZING;
}
PlatWindow_t hWnd = Plat_CreateWindow( hInstance, pTitle, w, h, nFlags );
if ( hWnd == PLAT_WINDOW_INVALID )
return NULL;
int CenterX, CenterY;
Plat_GetDesktopResolution( &CenterX, &CenterY );
CenterX = ( CenterX - w ) / 2;
CenterY = ( CenterY - h ) / 2;
CenterX = (CenterX < 0) ? 0: CenterX;
CenterY = (CenterY < 0) ? 0: CenterY;
// In VCR modes, keep it in the upper left so mouse coordinates are always relative to the window.
Plat_SetWindowPos( hWnd, CenterX, CenterY );
return hWnd;
#elif defined( PLATFORM_OSX )
extern ICocoaMgr *g_pCocoaMgr;
g_pCocoaMgr->CreateGameWindow( pTitle, bWindowed, w, h );
return (void*)Sys_GetFactoryThis(); // Other stuff will query for ICocoaBridge out of this.
#elif defined( PLATFORM_LINUX )
#ifndef DEDICATED
// PBTODO
// extern IGLXMgr *g_pGLXMgr;
// g_pGLXMgr->CreateWindow( pTitle, bWindowed, w, h );
return (void*)Sys_GetFactoryThis(); // Other stuff will query for ICocoaBridge out of this.
#endif
#endif
return NULL;
}
void CAppSystemGroup::SetAppWindowTitle( void* hWnd, const char *pTitle )
{
Plat_SetWindowTitle( (PlatWindow_t)hWnd, pTitle );
}
//-----------------------------------------------------------------------------
// Returns the stage at which the app system group ran into an error
//-----------------------------------------------------------------------------
CAppSystemGroup::AppSystemGroupStage_t CAppSystemGroup::GetCurrentStage() const
{
return m_nCurrentStage;
}
//-----------------------------------------------------------------------------
// Gets at a factory that works just like FindSystem
//-----------------------------------------------------------------------------
// This function is used to make this system appear to the outside world to
// function exactly like the currently existing factory system
CAppSystemGroup *s_pCurrentAppSystem;
void *AppSystemCreateInterfaceFn(const char *pName, int *pReturnCode)
{
void *pInterface = s_pCurrentAppSystem->FindSystem( pName );
if ( pReturnCode )
{
*pReturnCode = pInterface ? IFACE_OK : IFACE_FAILED;
}
return pInterface;
}
//-----------------------------------------------------------------------------
// Gets at a class factory for the topmost appsystem group in an appsystem stack
//-----------------------------------------------------------------------------
CreateInterfaceFn CAppSystemGroup::GetFactory()
{
return AppSystemCreateInterfaceFn;
}
//-----------------------------------------------------------------------------
// Main application loop
//-----------------------------------------------------------------------------
int CAppSystemGroup::Run()
{
// The factory now uses this app system group
s_pCurrentAppSystem = this;
// Load, connect, init
int nRetVal = OnStartup();
// NOTE: In case of OnStartup Failure
// On PS/3, not unloading the PRXes in order will cause crashes on quit, which is a TRC failure
// We probably should, but don't have to do this on all platforms, since it's not required to clean-up crash-free.
if ( m_nCurrentStage == RUNNING )
{
// Main loop implemented by the application
// FIXME: HACK workaround to avoid vgui porting
nRetVal = Main();
}
// Shutdown, disconnect, unload
OnShutdown();
// The factory now uses the parent's app system group
s_pCurrentAppSystem = GetParent();
return nRetVal;
}
//-----------------------------------------------------------------------------
// Virtual methods for override
//-----------------------------------------------------------------------------
int CAppSystemGroup::Startup()
{
return OnStartup();
}
void CAppSystemGroup::Shutdown()
{
return OnShutdown();
}
//-----------------------------------------------------------------------------
// Use this version in cases where you can't control the main loop and
// expect to be ticked
//-----------------------------------------------------------------------------
int CAppSystemGroup::OnStartup()
{
// The factory now uses this app system group
s_pCurrentAppSystem = this;
// Call an installed application creation function
m_nCurrentStage = CREATION;
if ( !Create() )
return -1;
// Load dependent libraries
m_nCurrentStage = DEPENDENCIES;
if ( !LoadDependentSystems() )
return -1;
// Let all systems know about each other
m_nCurrentStage = CONNECTION;
if ( !ConnectSystems() )
return -1;
// Allow the application to do some work before init
m_nCurrentStage = PREINITIALIZATION;
if ( !PreInit() )
return -1;
// Call Init on all App Systems
m_nCurrentStage = INITIALIZATION;
int nRetVal = InitSystems();
if ( nRetVal != INIT_OK )
return -1;
m_nCurrentStage = POSTINITIALIZATION;
if ( !PostInit() )
return -1;
m_nCurrentStage = RUNNING;
return nRetVal;
}
void CAppSystemGroup::OnShutdown()
{
// The factory now uses this app system group
s_pCurrentAppSystem = this;
switch( m_nCurrentStage )
{
case RUNNING:
case POSTINITIALIZATION:
break;
case PREINITIALIZATION:
case INITIALIZATION:
goto disconnect;
case CREATION:
case DEPENDENCIES:
case CONNECTION:
goto destroy;
default:
break;
}
// Allow the application to do some work before shutdown
m_nCurrentStage = PRESHUTDOWN;
PreShutdown();
// Cal Shutdown on all App Systems
m_nCurrentStage = SHUTDOWN;
ShutdownSystems();
// Allow the application to do some work after shutdown
m_nCurrentStage = POSTSHUTDOWN;
PostShutdown();
disconnect:
// Systems should disconnect from each other
m_nCurrentStage = DISCONNECTION;
DisconnectSystems();
destroy:
// Unload all DLLs loaded in the AppCreate block
m_nCurrentStage = DESTRUCTION;
RemoveAllSystems();
// Have to do this because the logging listeners & response policies may live in modules which are being unloaded
// @TODO: this seems like a bad legacy practice... app systems should unload their spew handlers gracefully.
LoggingSystem_ResetCurrentLoggingState();
Assert( g_pDefaultLoggingListener != NULL );
LoggingSystem_RegisterLoggingListener( g_pDefaultLoggingListener );
UnloadAllModules();
// Call an installed application destroy function
Destroy();
}
//-----------------------------------------------------------------------------
//
// This class represents a group of app systems that are loaded through steam
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSteamAppSystemGroup::CSteamAppSystemGroup( IFileSystem *pFileSystem, CAppSystemGroup *pAppSystemParent )
{
m_pFileSystem = pFileSystem;
m_pGameInfoPath[0] = 0;
}
//-----------------------------------------------------------------------------
// Used by CSteamApplication to set up necessary pointers if we can't do it in the constructor
//-----------------------------------------------------------------------------
void CSteamAppSystemGroup::Setup( IFileSystem *pFileSystem, CAppSystemGroup *pParentAppSystem )
{
m_pFileSystem = pFileSystem;
m_pParentAppSystem = pParentAppSystem;
}
//-----------------------------------------------------------------------------
// Loads the module from Steam
//-----------------------------------------------------------------------------
CSysModule *CSteamAppSystemGroup::LoadModuleDLL( const char *pDLLName )
{
return m_pFileSystem->LoadModule( pDLLName );
}
//-----------------------------------------------------------------------------
// Returns the game info path
//-----------------------------------------------------------------------------
const char *CSteamAppSystemGroup::GetGameInfoPath() const
{
return m_pGameInfoPath;
}
//-----------------------------------------------------------------------------
// Sets up the search paths
//-----------------------------------------------------------------------------
bool CSteamAppSystemGroup::SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool )
{
CFSSteamSetupInfo steamInfo;
steamInfo.m_pDirectoryName = pStartingDir;
steamInfo.m_bOnlyUseDirectoryName = bOnlyUseStartingDir;
steamInfo.m_bToolsMode = bIsTool;
steamInfo.m_bSetSteamDLLPath = true;
steamInfo.m_bSteam = m_pFileSystem->IsSteam();
if ( FileSystem_SetupSteamEnvironment( steamInfo ) != FS_OK )
return false;
CFSMountContentInfo fsInfo;
fsInfo.m_pFileSystem = m_pFileSystem;
fsInfo.m_bToolsMode = bIsTool;
fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath;
if ( FileSystem_MountContent( fsInfo ) != FS_OK )
return false;
// Finally, load the search paths for the "GAME" path.
CFSSearchPathsInit searchPathsInit;
searchPathsInit.m_pDirectoryName = steamInfo.m_GameInfoPath;
searchPathsInit.m_pFileSystem = fsInfo.m_pFileSystem;
if ( FileSystem_LoadSearchPaths( searchPathsInit ) != FS_OK )
return false;
FileSystem_AddSearchPath_Platform( fsInfo.m_pFileSystem, steamInfo.m_GameInfoPath );
Q_strncpy( m_pGameInfoPath, steamInfo.m_GameInfoPath, sizeof(m_pGameInfoPath) );
return true;
}

View File

@ -0,0 +1,119 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/vguimatsysapp.h"
#include "vgui/IVGui.h"
#include "vgui/ISurface.h"
#include "vgui_controls/controls.h"
#include "vgui/IScheme.h"
#include "vgui/ILocalize.h"
#include "tier0/dbg.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "tier3/tier3.h"
#include "inputsystem/iinputstacksystem.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CVguiMatSysApp::CVguiMatSysApp()
{
m_hAppInputContext = INPUT_CONTEXT_HANDLE_INVALID;
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CVguiMatSysApp::Create()
{
if ( !BaseClass::Create() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSTACKSYSTEM_INTERFACE_VERSION },
// NOTE: This has to occur before vgui2.dll so it replaces vgui2's surface implementation
{ "vguimatsurface.dll", VGUI_SURFACE_INTERFACE_VERSION },
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
return AddSystems( appSystems );
}
void CVguiMatSysApp::Destroy()
{
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CVguiMatSysApp::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
ConnectTier3Libraries( &factory, 1 );
if ( !vgui::VGui_InitInterfacesList( "CVguiSteamApp", &factory, 1 ) )
return false;
if ( !g_pMatSystemSurface )
{
Warning( "CVguiMatSysApp::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
g_pMatSystemSurface->EnableWindowsMessages( true );
return true;
}
bool CVguiMatSysApp::PostInit()
{
if ( !BaseClass::PostInit() )
return false;
m_hAppInputContext = g_pInputStackSystem->PushInputContext();
InputContextHandle_t hVGuiInputContext = g_pInputStackSystem->PushInputContext();
g_pMatSystemSurface->SetInputContext( hVGuiInputContext );
g_pMatSystemSurface->EnableWindowsMessages( true );
return true;
}
void CVguiMatSysApp::PreShutdown()
{
g_pMatSystemSurface->EnableWindowsMessages( false );
g_pMatSystemSurface->SetInputContext( NULL );
if ( m_hAppInputContext != INPUT_CONTEXT_HANDLE_INVALID )
{
g_pInputStackSystem->PopInputContext(); // Vgui
g_pInputStackSystem->PopInputContext(); // App
}
BaseClass::PreShutdown();
}
void CVguiMatSysApp::PostShutdown()
{
DisconnectTier3Libraries();
BaseClass::PostShutdown();
}
InputContextHandle_t CVguiMatSysApp::GetAppInputContext()
{
return m_hAppInputContext;
}
#endif // _WIN32

235
appframework/WinApp.cpp Normal file
View File

@ -0,0 +1,235 @@
//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======//
//
// Purpose: An application framework
//
//=============================================================================//
#include "appframework/AppFramework.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "interface.h"
#include "filesystem.h"
#include "appframework/IAppSystemGroup.h"
#include "filesystem_init.h"
#include "vstdlib/cvar.h"
#include "tier2/tier2.h"
#ifdef _X360
#include "xbox/xbox_win32stubs.h"
#include "xbox/xbox_console.h"
#include "xbox/xbox_launch.h"
#endif
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Globals...
//-----------------------------------------------------------------------------
void* s_HInstance;
static CSimpleWindowsLoggingListener s_SimpleWindowsLoggingListener;
static CSimpleLoggingListener s_SimpleLoggingListener;
ILoggingListener *g_pDefaultLoggingListener = &s_SimpleLoggingListener;
//-----------------------------------------------------------------------------
// HACK: Since I don't want to refit vgui yet...
//-----------------------------------------------------------------------------
void *GetAppInstance()
{
return s_HInstance;
}
//-----------------------------------------------------------------------------
// Sets the application instance, should only be used if you're not calling AppMain.
//-----------------------------------------------------------------------------
void SetAppInstance( void* hInstance )
{
s_HInstance = hInstance;
}
//-----------------------------------------------------------------------------
// Version of AppMain used by windows applications
//-----------------------------------------------------------------------------
int AppMain( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleWindowsLoggingListener;
s_HInstance = hInstance;
#ifdef WIN32
// Prepend the module filename since most apps expect arg 0 to be that.
char szModuleFilename[MAX_PATH];
Plat_GetModuleFilename( szModuleFilename, sizeof( szModuleFilename ) );
int nAllocLen = strlen( lpCmdLine ) + strlen( szModuleFilename ) + 4;
char *pNewCmdLine = new char[nAllocLen]; // 2 for quotes, 1 for a space, and 1 for a null-terminator.
_snprintf( pNewCmdLine, nAllocLen, "\"%s\" %s", szModuleFilename, lpCmdLine );
// Setup ICommandLine.
CommandLine()->CreateCmdLine( pNewCmdLine );
delete [] pNewCmdLine;
#else
CommandLine()->CreateCmdLine( lpCmdLine );
#endif
return pAppSystemGroup->Run();
}
//-----------------------------------------------------------------------------
// Version of AppMain used by console applications
//-----------------------------------------------------------------------------
int AppMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleLoggingListener;
s_HInstance = NULL;
CommandLine()->CreateCmdLine( argc, argv );
return pAppSystemGroup->Run();
}
//-----------------------------------------------------------------------------
// Used to startup/shutdown the application
//-----------------------------------------------------------------------------
int AppStartup( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleWindowsLoggingListener;
s_HInstance = hInstance;
CommandLine()->CreateCmdLine( lpCmdLine );
return pAppSystemGroup->Startup();
}
int AppStartup( int argc, char **argv, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleLoggingListener;
s_HInstance = NULL;
CommandLine()->CreateCmdLine( argc, argv );
return pAppSystemGroup->Startup();
}
void AppShutdown( CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
pAppSystemGroup->Shutdown();
}
//-----------------------------------------------------------------------------
//
// Default implementation of an application meant to be run using Steam
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSteamApplication::CSteamApplication( CSteamAppSystemGroup *pAppSystemGroup )
{
m_pChildAppSystemGroup = pAppSystemGroup;
m_pFileSystem = NULL;
m_bSteam = false;
}
//-----------------------------------------------------------------------------
// Create necessary interfaces
//-----------------------------------------------------------------------------
bool CSteamApplication::Create()
{
FileSystem_SetErrorMode( FS_ERRORMODE_AUTO );
char pFileSystemDLL[MAX_PATH];
if ( !GetFileSystemDLLName( pFileSystemDLL, MAX_PATH, m_bSteam ) )
return false;
FileSystem_SetupSteamInstallPath();
// Add in the cvar factory
AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() );
AddSystem( cvarModule, CVAR_INTERFACE_VERSION );
AppModule_t fileSystemModule = LoadModule( pFileSystemDLL );
m_pFileSystem = (IFileSystem*)AddSystem( fileSystemModule, FILESYSTEM_INTERFACE_VERSION );
if ( !m_pFileSystem )
{
if( !IsPS3() )
Error( "Unable to load %s", pFileSystemDLL );
return false;
}
return true;
}
bool CSteamApplication::GetFileSystemDLLName( char *pOut, int nMaxBytes, bool &bIsSteam )
{
return FileSystem_GetFileSystemDLLName( pOut, nMaxBytes, bIsSteam ) == FS_OK;
}
//-----------------------------------------------------------------------------
// The file system pointer is invalid at this point
//-----------------------------------------------------------------------------
void CSteamApplication::Destroy()
{
m_pFileSystem = NULL;
}
//-----------------------------------------------------------------------------
// Pre-init, shutdown
//-----------------------------------------------------------------------------
bool CSteamApplication::PreInit()
{
return true;
}
void CSteamApplication::PostShutdown()
{
}
//-----------------------------------------------------------------------------
// Run steam main loop
//-----------------------------------------------------------------------------
int CSteamApplication::Main()
{
// Now that Steam is loaded, we can load up main libraries through steam
if ( FileSystem_SetBasePaths( m_pFileSystem ) != FS_OK )
return 0;
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Run();
}
//-----------------------------------------------------------------------------
// Use this version in cases where you can't control the main loop and
// expect to be ticked
//-----------------------------------------------------------------------------
int CSteamApplication::Startup()
{
int nRetVal = BaseClass::Startup();
if ( GetCurrentStage() != RUNNING )
return nRetVal;
if ( FileSystem_SetBasePaths( m_pFileSystem ) != FS_OK )
return 0;
// Now that Steam is loaded, we can load up main libraries through steam
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Startup();
}
void CSteamApplication::Shutdown()
{
m_pChildAppSystemGroup->Shutdown();
BaseClass::Shutdown();
}

View File

@ -0,0 +1,40 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\appframework\AppSystemGroup.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\AppSystemGroup.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\AppSystemGroup.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Release output file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\appframework\matsysapp.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\matsysapp.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\matsysapp.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\appframework\VguiMatSysApp.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\VguiMatSysApp.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\VguiMatSysApp.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\appframework\WinApp.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\WinApp.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\WinApp.cpp
Containing unity file:
PCH file:

View File

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------------
// APPFRAMEWORK.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$General
{
$AdditionalProjectDependencies "$BASE;togl" [!$IS_LIB_PROJECT && $GL]
}
$Compiler
{
$PreprocessorDefinitions "$BASE;VERSION_SAFE_STEAM_API_INTERFACES" [($WINDOWS && $GL) || $LINUXALL]
$PreprocessorDefinitions "$BASE;ALLOW_TEXT_MODE=1" [$CSTRIKE_TRUNK_BUILD||$CSTRIKE_STAGING_BUILD]
}
$Linker [$OSXALL && !$IS_LIB_PROJECT]
{
$SystemFrameworks "Carbon;OpenGL;Quartz;Cocoa;IOKit"
}
}
$Project "appframework"
{
$Folder "Source Files"
{
$File "AppSystemGroup.cpp"
$File "$SRCDIR\public\filesystem_init.cpp"
$File "VguiMatSysApp.cpp" [$WINDOWS]
$File "matsysapp.cpp" [$WINDOWS]
$File "WinApp.cpp" [$WINDOWS]
$File "posixapp.cpp" [$POSIX]
$File "sdlmgr.cpp" [$SDL]
$File "cocoamgr.mm" [!$SDL && $OSXALL]
$File "glmrendererinfo_osx.mm" [$SDL && $OSXALL]
}
$Folder "Interface"
{
$File "$SRCDIR\public\appframework\AppFramework.h"
$File "$SRCDIR\public\appframework\iappsystem.h"
$File "$SRCDIR\public\appframework\IAppSystemGroup.h"
$File "$SRCDIR\public\appframework\tier2app.h"
$File "$SRCDIR\public\appframework\tier3app.h"
$File "$SRCDIR\public\appframework\matsysapp.h"
$File "$SRCDIR\public\appframework\VguiMatSysApp.h"
$File "$SRCDIR\public\appframework\ilaunchermgr.h"
}
$Folder "Link Libraries"
{
$ImpLib togl [!$IS_LIB_PROJECT && $GL]
$ImpLib SDL2 [!$IS_LIB_PROJECT && $SDL]
}
}

View File

@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "appframework.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "appframework.vcxproj"
"1" "appframework.vcxproj.filters"
}
}
}

3828
appframework/cocoamgr.mm Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,630 @@
//========= Copyright 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a group of app systems that all have the same lifetime
// that need to be connected/initialized, etc. in a well-defined order
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
//===============================================================================
GLMRendererInfo::GLMRendererInfo( void )
{
m_display = NULL;
Q_memset( &m_info, 0, sizeof( m_info ) );
}
GLMRendererInfo::~GLMRendererInfo( void )
{
SDLAPP_FUNC;
if (m_display)
{
delete m_display;
m_display = NULL;
}
}
// !!! FIXME: sync this function with the Mac version in case anything important has changed.
void GLMRendererInfo::Init( GLMRendererInfoFields *info )
{
SDLAPP_FUNC;
m_info = *info;
m_display = NULL;
m_info.m_fullscreen = 0;
m_info.m_accelerated = 1;
m_info.m_windowed = 1;
m_info.m_ati = true;
m_info.m_atiNewer = true;
m_info.m_hasGammaWrites = true;
// If you haven't created a GL context by now (and initialized gGL), you're about to crash.
m_info.m_hasMixedAttachmentSizes = gGL->m_bHave_GL_ARB_framebuffer_object;
m_info.m_hasBGRA = gGL->m_bHave_GL_EXT_vertex_array_bgra;
// !!! FIXME: what do these do on the Mac?
m_info.m_hasNewFullscreenMode = false;
m_info.m_hasNativeClipVertexMode = true;
// if user disabled them
if (CommandLine()->FindParm("-glmdisableclipplanes"))
{
m_info.m_hasNativeClipVertexMode = false;
}
// or maybe enabled them..
if (CommandLine()->FindParm("-glmenableclipplanes"))
{
m_info.m_hasNativeClipVertexMode = true;
}
m_info.m_hasOcclusionQuery = gGL->m_bHave_GL_ARB_occlusion_query;
m_info.m_hasFramebufferBlit = gGL->m_bHave_GL_EXT_framebuffer_blit || gGL->m_bHave_GL_ARB_framebuffer_object;
GLint nMaxAniso = 0;
gGL->glGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &nMaxAniso );
m_info.m_maxAniso = clamp<int>( nMaxAniso, 0, 16 );
// We don't currently used bindable uniforms, but I've been experimenting with them so I might as well check this in just in case they turn out to be useful.
m_info.m_hasBindableUniforms = gGL->m_bHave_GL_EXT_bindable_uniform;
m_info.m_hasBindableUniforms = false; // !!! FIXME hardwiring this path to false until we see how to accelerate it properly
m_info.m_maxVertexBindableUniforms = 0;
m_info.m_maxFragmentBindableUniforms = 0;
m_info.m_maxBindableUniformSize = 0;
if (m_info.m_hasBindableUniforms)
{
gGL->glGetIntegerv(GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT, &m_info.m_maxVertexBindableUniforms);
gGL->glGetIntegerv(GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT, &m_info.m_maxFragmentBindableUniforms);
gGL->glGetIntegerv(GL_MAX_BINDABLE_UNIFORM_SIZE_EXT, &m_info.m_maxBindableUniformSize);
if ( ( m_info.m_maxVertexBindableUniforms < 1 ) || ( m_info.m_maxFragmentBindableUniforms < 1 ) || ( m_info.m_maxBindableUniformSize < ( sizeof( float ) * 4 * 256 ) ) )
{
m_info.m_hasBindableUniforms = false;
}
}
m_info.m_hasUniformBuffers = gGL->m_bHave_GL_ARB_uniform_buffer;
m_info.m_hasPerfPackage1 = true; // this flag is Mac-specific. We do slower things if you don't have Mac OS X 10.x.y or later. Linux always does the fast path!
//-------------------------------------------------------------------
// runtime options that aren't negotiable once set
m_info.m_hasDualShaders = CommandLine()->FindParm("-glmdualshaders") != 0;
//-------------------------------------------------------------------
// "can'ts "
#if defined( OSX )
m_info.m_cantBlitReliably = m_info.m_intel; //FIXME X3100&10.6.3 has problems blitting.. adjust this if bug fixed in 10.6.4
#else
// m_cantBlitReliably path doesn't work right now, and the Intel path is different for us on Linux/Win7 anyway
m_info.m_cantBlitReliably = false;
#endif
if (CommandLine()->FindParm("-glmenabletrustblit"))
{
m_info.m_cantBlitReliably = false; // we trust the blit, so set the cant-blit cap to false
}
if (CommandLine()->FindParm("-glmdisabletrustblit"))
{
m_info.m_cantBlitReliably = true; // we do not trust the blit, so set the cant-blit cap to true
}
// MSAA resolve issues
m_info.m_cantResolveFlipped = false;
#if defined( OSX )
m_info.m_cantResolveScaled = true; // generally true until new extension ships
#else
// DON'T just slam this to false and run without first testing with -gl_debug enabled on NVidia/AMD/etc.
// This path needs the m_bHave_GL_EXT_framebuffer_multisample_blit_scaled extension.
m_info.m_cantResolveScaled = true;
if ( gGL->m_bHave_GL_EXT_framebuffer_multisample_blit_scaled )
{
m_info.m_cantResolveScaled = false;
}
#endif
// gamma decode impacting shader codegen
m_info.m_costlyGammaFlips = false;
}
void GLMRendererInfo::PopulateDisplays()
{
SDLAPP_FUNC;
Assert( !m_display );
m_display = new GLMDisplayInfo;
// Populate display mode table.
m_display->PopulateModes();
}
void GLMRendererInfo::Dump( int which )
{
SDLAPP_FUNC;
GLMPRINTF(("\n #%d: GLMRendererInfo @ %p, renderer-id=(%08x) display-mask=%08x vram=%dMB",
which, this,
m_info.m_rendererID,
m_info.m_displayMask,
m_info.m_vidMemory >> 20
));
GLMPRINTF(("\n VendorID=%04x DeviceID=%04x Model=%s",
m_info.m_pciVendorID,
m_info.m_pciDeviceID,
m_info.m_pciModelString
));
m_display->Dump( which );
}
GLMDisplayDB::GLMDisplayDB ()
{
SDLAPP_FUNC;
m_renderer.m_display = NULL;
}
GLMDisplayDB::~GLMDisplayDB ( void )
{
SDLAPP_FUNC;
if ( m_renderer.m_display )
{
delete m_renderer.m_display;
m_renderer.m_display = NULL;
}
}
#ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
#endif
#ifndef GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX
#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
#endif
#ifndef GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX
#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
#endif
#ifndef GL_VBO_FREE_MEMORY_ATI
#define GL_VBO_FREE_MEMORY_ATI 0x87FB
#endif
#ifndef GL_TEXTURE_FREE_MEMORY_ATI
#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
#endif
#ifndef GL_RENDERBUFFER_FREE_MEMORY_ATI
#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
#endif
void GLMDisplayDB::PopulateRenderers( void )
{
SDLAPP_FUNC;
Assert( !m_renderer.m_display );
GLMRendererInfoFields fields;
memset( &fields, 0, sizeof(fields) );
// Assume 512MB of available video memory
fields.m_vidMemory = 512 * 1024 * 1024;
DebugPrintf( "GL_NVX_gpu_memory_info: %s\n", gGL->m_bHave_GL_NVX_gpu_memory_info ? "AVAILABLE" : "UNAVAILABLE" );
DebugPrintf( "GL_ATI_meminfo: %s\n", gGL->m_bHave_GL_ATI_meminfo ? "AVAILABLE" : "UNAVAILABLE" );
if ( gGL->m_bHave_GL_NVX_gpu_memory_info )
{
gGL->glGetError();
GLint nTotalDedicated = 0, nTotalAvail = 0, nCurrentAvail = 0;
gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &nTotalDedicated );
gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &nTotalAvail );
gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &nCurrentAvail );
if ( gGL->glGetError() )
{
DebugPrintf( "GL_NVX_gpu_memory_info: Failed retrieving available GPU memory\n" );
}
else
{
DebugPrintf( "GL_NVX_gpu_memory_info: Total Dedicated: %u, Total Avail: %u, Current Avail: %u\n", nTotalDedicated, nTotalAvail, nCurrentAvail );
// Try to do something reasonable. Should we report dedicated or total available to the engine here?
// For now, just take the MAX of both.
uint64 nActualAvail = static_cast<uint64>( MAX( nTotalAvail, nTotalDedicated ) ) * 1024;
fields.m_vidMemory = static_cast< GLint >( MIN( nActualAvail, 0x7FFFFFFF ) );
}
}
else if ( gGL->m_bHave_GL_ATI_meminfo )
{
// As of 10/8/12 this extension is only available under Linux and Windows FireGL parts.
gGL->glGetError();
GLint nAvail[4] = { 0, 0, 0, 0 };
gGL->glGetIntegerv( GL_TEXTURE_FREE_MEMORY_ATI, nAvail );
if ( gGL->glGetError() )
{
DebugPrintf( "GL_ATI_meminfo: Failed retrieving available GPU memory\n" );
}
else
{
// param[0] - total memory free in the pool
// param[1] - largest available free block in the pool
// param[2] - total auxiliary memory free
// param[3] - largest auxiliary free block
DebugPrintf( "GL_ATI_meminfo: GL_TEXTURE_FREE_MEMORY_ATI: Total Free: %i, Largest Avail: %i, Total Aux: %i, Largest Aux Avail: %i\n",
nAvail[0], nAvail[1], nAvail[2], nAvail[3] );
uint64 nActualAvail = static_cast<uint64>( nAvail[0] ) * 1024;
fields.m_vidMemory = static_cast< GLint >( MIN( nActualAvail, 0x7FFFFFFF ) );
}
}
// Clamp the min amount of video memory to 256MB in case a query returned something bogus, or we interpreted it badly.
fields.m_vidMemory = MAX( fields.m_vidMemory, 128 * 1024 * 1024 );
fields.m_texMemory = fields.m_vidMemory;
fields.m_pciVendorID = GLM_OPENGL_VENDOR_ID;
fields.m_pciDeviceID = GLM_OPENGL_DEFAULT_DEVICE_ID;
if ( ( gGL->m_nDriverProvider == cGLDriverProviderIntel ) || ( gGL->m_nDriverProvider == cGLDriverProviderIntelOpenSource ) )
{
fields.m_pciDeviceID = GLM_OPENGL_LOW_PERF_DEVICE_ID;
}
/* fields.m_colorModes = (uint)-1;
fields.m_bufferModes = (uint)-1;
fields.m_depthModes = (uint)-1;
fields.m_stencilModes = (uint)-1;
fields.m_maxAuxBuffers = (uint)128;
fields.m_maxSampleBuffers = (uint)128;
fields.m_maxSamples = (uint)2048;
fields.m_sampleModes = (uint)128;
fields.m_sampleAlpha = (uint)32;
*/
GLint nMaxMultiSamples = 0;
gGL->glGetIntegerv( GL_MAX_SAMPLES_EXT, &nMaxMultiSamples );
fields.m_maxSamples = clamp<int>( nMaxMultiSamples, 0, 8 );
DebugPrintf( "GL_MAX_SAMPLES_EXT: %i\n", nMaxMultiSamples );
// We only have one GLMRendererInfo on Linux, unlike Mac OS X. Whatever libGL.so wants to do, we go with it.
m_renderer.Init( &fields );
// then go back and ask each renderer to populate its display info table.
m_renderer.PopulateDisplays();
}
void GLMDisplayDB::PopulateFakeAdapters( uint realRendererIndex ) // fake adapters = one real adapter times however many displays are on it
{
SDLAPP_FUNC;
Assert( realRendererIndex == 0 );
}
void GLMDisplayDB::Populate(void)
{
SDLAPP_FUNC;
this->PopulateRenderers();
this->PopulateFakeAdapters( 0 );
#if GLMDEBUG
this->Dump();
#endif
}
int GLMDisplayDB::GetFakeAdapterCount( void )
{
SDLAPP_FUNC;
return 1;
}
bool GLMDisplayDB::GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut )
{
SDLAPP_FUNC;
if (fakeAdapterIndex >= GetFakeAdapterCount() )
{
*rendererOut = 0;
*displayOut = 0;
return true; // fail
}
*rendererOut = 0;
*displayOut = 0;
bool rendResult = GetRendererInfo( *rendererOut, rendererInfoOut );
bool dispResult = GetDisplayInfo( *rendererOut, *displayOut, displayInfoOut );
return rendResult || dispResult;
}
int GLMDisplayDB::GetRendererCount( void )
{
SDLAPP_FUNC;
return 1;
}
bool GLMDisplayDB::GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut )
{
SDLAPP_FUNC;
memset( infoOut, 0, sizeof( GLMRendererInfoFields ) );
if (rendererIndex >= GetRendererCount())
return true; // fail
*infoOut = m_renderer.m_info;
return false;
}
int GLMDisplayDB::GetDisplayCount( int rendererIndex )
{
SDLAPP_FUNC;
if (rendererIndex >= GetRendererCount())
{
Assert( 0 );
return 0; // fail
}
return 1;
}
bool GLMDisplayDB::GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut )
{
SDLAPP_FUNC;
memset( infoOut, 0, sizeof( GLMDisplayInfoFields ) );
if (rendererIndex >= GetRendererCount())
return true; // fail
if (displayIndex >= GetDisplayCount(rendererIndex))
return true; // fail
*infoOut = m_renderer.m_display->m_info;
return false;
}
int GLMDisplayDB::GetModeCount( int rendererIndex, int displayIndex )
{
SDLAPP_FUNC;
if (rendererIndex >= GetRendererCount())
return 0; // fail
if (displayIndex >= GetDisplayCount(rendererIndex))
return 0; // fail
return m_renderer.m_display->m_modes->Count();
}
bool GLMDisplayDB::GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut )
{
SDLAPP_FUNC;
memset( infoOut, 0, sizeof( GLMDisplayModeInfoFields ) );
if ( rendererIndex >= GetRendererCount())
return true; // fail
if (displayIndex >= GetDisplayCount( rendererIndex ) )
return true; // fail
if ( modeIndex >= GetModeCount( rendererIndex, displayIndex ) )
return true; // fail
if ( modeIndex >= 0 )
{
GLMDisplayMode *displayModeInfo = m_renderer.m_display->m_modes->Element( modeIndex );
*infoOut = displayModeInfo->m_info;
}
else
{
const GLMDisplayInfoFields &info = m_renderer.m_display->m_info;
infoOut->m_modePixelWidth = info.m_displayPixelWidth;
infoOut->m_modePixelHeight = info.m_displayPixelHeight;
infoOut->m_modeRefreshHz = 0;
//return true; // fail
}
return false;
}
void GLMDisplayDB::Dump( void )
{
SDLAPP_FUNC;
GLMPRINTF(("\n GLMDisplayDB @ %p ",this ));
m_renderer.Dump( 0 );
}
//===============================================================================
GLMDisplayInfo::GLMDisplayInfo()
{
SDLAPP_FUNC;
m_modes = NULL;
int Width, Height;
GetLargestDisplaySize( Width, Height );
m_info.m_displayPixelWidth = ( uint )Width;
m_info.m_displayPixelHeight = ( uint )Height;
}
GLMDisplayInfo::~GLMDisplayInfo( void )
{
SDLAPP_FUNC;
}
extern "C" int DisplayModeSortFunction( GLMDisplayMode * const *A, GLMDisplayMode * const *B )
{
SDLAPP_FUNC;
int bigger = -1;
int smaller = 1; // adjust these for desired ordering
// check refreshrate - higher should win
if ( (*A)->m_info.m_modeRefreshHz > (*B)->m_info.m_modeRefreshHz )
{
return bigger;
}
else if ( (*A)->m_info.m_modeRefreshHz < (*B)->m_info.m_modeRefreshHz )
{
return smaller;
}
// check area - larger mode should win
int areaa = (*A)->m_info.m_modePixelWidth * (*A)->m_info.m_modePixelHeight;
int areab = (*B)->m_info.m_modePixelWidth * (*B)->m_info.m_modePixelHeight;
if ( areaa > areab )
{
return bigger;
}
else if ( areaa < areab )
{
return smaller;
}
return 0; // equal rank
}
void GLMDisplayInfo::PopulateModes( void )
{
SDLAPP_FUNC;
Assert( !m_modes );
m_modes = new CUtlVector< GLMDisplayMode* >;
int nummodes = SDL_GetNumVideoDisplays();
for ( int i = 0; i < nummodes; i++ )
{
SDL_Rect rect = { 0, 0, 0, 0 };
if ( !SDL_GetDisplayBounds( i, &rect ) && rect.w && rect.h )
{
m_modes->AddToTail( new GLMDisplayMode( rect.w, rect.h, 0 ) );
}
}
// Add a big pile of window resolutions.
static const struct
{
uint w;
uint h;
} s_Resolutions[] =
{
{ 640, 480 }, // 4x3
{ 800, 600 },
{ 1024, 768 },
{ 1152, 864 },
{ 1280, 960 },
{ 1600, 1200 },
{ 1920, 1440 },
{ 2048, 1536 },
{ 1280, 720 }, // 16x9
{ 1366, 768 },
{ 1600, 900 },
{ 1920, 1080 },
{ 720, 480 }, // 16x10
{ 1280, 800 },
{ 1680, 1050 },
{ 1920, 1200 },
{ 2560, 1600 },
};
for ( int i = 0; i < ARRAYSIZE( s_Resolutions ); i++ )
{
uint w = s_Resolutions[ i ].w;
uint h = s_Resolutions[ i ].h;
if ( ( w <= m_info.m_displayPixelWidth ) && ( h <= m_info.m_displayPixelHeight ) )
{
m_modes->AddToTail( new GLMDisplayMode( w, h, 0 ) );
if ( ( w * 2 <= m_info.m_displayPixelWidth ) && ( h * 2 < m_info.m_displayPixelHeight ) )
{
// Add double of everything also - Retina proofing hopefully.
m_modes->AddToTail( new GLMDisplayMode( w * 2, h * 2, 0 ) );
}
}
}
m_modes->Sort( DisplayModeSortFunction );
// remove dupes.
nummodes = m_modes->Count();
int i = 1; // not zero!
while (i < nummodes)
{
GLMDisplayModeInfoFields& info0 = m_modes->Element( i - 1 )->m_info;
GLMDisplayModeInfoFields& info1 = m_modes->Element( i )->m_info;
if ( ( info0.m_modePixelWidth == info1.m_modePixelWidth ) &&
( info0.m_modePixelHeight == info1.m_modePixelHeight ) &&
( info0.m_modeRefreshHz == info1.m_modeRefreshHz ) )
{
m_modes->Remove(i);
nummodes--;
}
else
{
i++;
}
}
}
void GLMDisplayInfo::Dump( int which )
{
SDLAPP_FUNC;
GLMPRINTF(("\n #%d: GLMDisplayInfo @ %08x, pixwidth=%d pixheight=%d",
which, (int)this, m_info.m_displayPixelWidth, m_info.m_displayPixelHeight ));
FOR_EACH_VEC( *m_modes, i )
{
( *m_modes )[i]->Dump(i);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,410 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/materialsystem2app.h"
#include "FileSystem.h"
#include "materialsystem2/IMaterialSystem2.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "filesystem_init.h"
#include "inputsystem/iinputsystem.h"
#include "tier2/tier2.h"
#include "rendersystem/irenderdevice.h"
#include "rendersystem/irenderhardwareconfig.h"
#include "vstdlib/jobthread.h"
//#include "videocfg/videocfg.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CMaterialSystem2App::CMaterialSystem2App()
{
m_RenderFactory = NULL;
m_hSwapChain = SWAP_CHAIN_HANDLE_INVALID;
}
//-----------------------------------------------------------------------------
// Creates render system
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::AddRenderSystem()
{
bool bIsVistaOrHigher = IsPlatformWindowsPC() && ( Plat_GetOSVersion() >= PLAT_OS_VERSION_VISTA );
const char *pShaderDLL = !IsPlatformX360() ? CommandLine()->ParmValue( "-rendersystemdll" ) : NULL;
if ( !pShaderDLL )
{
if ( IsPlatformWindowsPC() )
{
pShaderDLL = "rendersystemdx11.dll";
}
else if ( IsPlatformX360() )
{
pShaderDLL = "rendersystemdx9_360.dll";
}
else
{
pShaderDLL = "rendersystemgl.dll";
}
}
// Disallow dx11 on XP machines
if ( !bIsVistaOrHigher && !Q_stricmp( pShaderDLL, "rendersystemdx11.dll" ) )
{
pShaderDLL = "rendersystemdx9.dll";
}
AppModule_t module = LoadModule( pShaderDLL );
if ( module == APP_MODULE_INVALID )
{
if ( IsPlatformWindowsPC() )
{
pShaderDLL = "rendersystemdx9.dll";
module = LoadModule( pShaderDLL );
}
if ( module == APP_MODULE_INVALID )
{
pShaderDLL = "rendersystemempty.dll";
module = LoadModule( pShaderDLL );
if ( module == APP_MODULE_INVALID )
return false;
}
}
AddSystem( module, RENDER_DEVICE_MGR_INTERFACE_VERSION );
if ( IsPlatformX360() )
{
m_nRenderSystem = RENDER_SYSTEM_X360;
}
else if ( V_stristr( pShaderDLL, "rendersystemgl" ) != NULL )
{
m_nRenderSystem = RENDER_SYSTEM_GL;
}
else if ( V_stristr( pShaderDLL, "rendersystemdx11" ) != NULL )
{
m_nRenderSystem = RENDER_SYSTEM_DX11;
}
else
{
m_nRenderSystem = RENDER_SYSTEM_DX9;
}
return true;
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::Create()
{
if ( !AddRenderSystem() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
{ "materialsystem2.dll", MATERIAL_SYSTEM2_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
if ( !AddSystems( appSystems ) )
return false;
const char *pNumThreadsString = CommandLine()->ParmValue( "-threads" );
if ( pNumThreadsString )
{
m_nThreadCount = atoi( pNumThreadsString );
}
else
{
const CPUInformation &cpuInfo = GetCPUInformation();
m_nThreadCount = cpuInfo.m_nLogicalProcessors - 1; // one core for main thread
}
if ( m_nThreadCount > 0 )
{
ThreadPoolStartParams_t sparms( false, m_nThreadCount );
g_pThreadPool->Start( sparms );
}
return true;
}
void CMaterialSystem2App::Destroy()
{
}
//-----------------------------------------------------------------------------
// Pump messages
//-----------------------------------------------------------------------------
void CMaterialSystem2App::AppPumpMessages()
{
g_pInputSystem->PollInputState();
}
//-----------------------------------------------------------------------------
// Sets up the game path
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool )
{
if ( !BaseClass::SetupSearchPaths( pStartingDir, bOnlyUseStartingDir, bIsTool ) )
return false;
g_pFullFileSystem->AddSearchPath( GetGameInfoPath(), "SKIN", PATH_ADD_TO_HEAD );
return true;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
if ( !g_pFullFileSystem || !g_pMaterialSystem2 || !g_pRenderDeviceMgr || !g_pInputSystem )
{
Warning( "CMaterialSystem2App::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
// Needed to set up the device prior to Init() of other systems
g_pRenderDeviceMgr->InstallRenderDeviceSetup( this );
// Add paths...
// NOTE: Not sure if I should have this here or not. For now, my test
// is rendersystem test, which wants to do it itself.
// if ( !SetupSearchPaths( NULL, false, true ) )
// return false;
return true;
}
//-----------------------------------------------------------------------------
// Replace first underscore (if any) with \0 and return
// This handles special mods like tf_movies, l4d_movies, tf_comics
// As a result, such mods will use the gpu_level settings etc from the base mod
//-----------------------------------------------------------------------------
static void StripModSuffix( char *pModName )
{
int i = 0;
while ( pModName[i] != '\0' ) // Walk to the end of the string
{
if ( pModName[i] == '_') // If we hit an underscore
{
pModName[i] = '\0'; // Terminate the string here and bail out
return;
}
i++;
}
}
//-----------------------------------------------------------------------------
// Configures the application for the specific mod we're running
//-----------------------------------------------------------------------------
void CMaterialSystem2App::ApplyModSettings( )
{
/* PORTFIXME
char pModPath[MAX_PATH];
V_snprintf( pModPath, sizeof(pModPath), "" );
g_pFullFileSystem->GetSearchPath( "MOD", false, pModPath, sizeof( pModPath ) );
// Construct the mod name so we can use the mod-specific encrypted config files
char pModName[32];
V_StripTrailingSlash( pModPath );
V_FileBase( pModPath, pModName, sizeof( pModName ) );
StripModSuffix( pModName );
// Just use the highest levels in non-game apps
UpdateSystemLevel( CPU_LEVEL_HIGH, GPU_LEVEL_VERYHIGH, MEM_LEVEL_HIGH, GPU_MEM_LEVEL_HIGH, false, pModName );
*/
}
//-----------------------------------------------------------------------------
// Create our device + window
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::CreateRenderDevice()
{
// Create a device for this adapter
int nAdapterCount = g_pRenderDeviceMgr->GetAdapterCount();
int nAdapter = CommandLine()->ParmValue( "-adapter", 0 );
if ( nAdapter >= nAdapterCount )
{
Warning( "Specified too high an adapter number on the commandline (%d/%d)!\n", nAdapter, nAdapterCount );
return false;
}
int nFlags = 0;
bool bResizing = !IsConsoleApp() && ( CommandLine()->CheckParm( "-resizing" ) != NULL );
if ( bResizing )
{
nFlags |= RENDER_CREATE_DEVICE_RESIZE_WINDOWS;
}
m_RenderFactory = g_pRenderDeviceMgr->CreateDevice( nAdapter, nFlags );
if ( !m_RenderFactory )
{
Warning( "Unable to set mode!\n" );
return false;
}
// Let other systems see the render device
AddNonAppSystemFactory( m_RenderFactory );
ReconnectSystems( RENDER_DEVICE_INTERFACE_VERSION );
ReconnectSystems( RENDER_HARDWARECONFIG_INTERFACE_VERSION );
g_pRenderDevice = (IRenderDevice*)m_RenderFactory( RENDER_DEVICE_INTERFACE_VERSION, NULL );
g_pRenderHardwareConfig = (IRenderHardwareConfig*)m_RenderFactory( RENDER_HARDWARECONFIG_INTERFACE_VERSION, NULL );
// Fixup the platform level
if ( m_nRenderSystem == RENDER_SYSTEM_DX11 )
{
if ( g_pRenderHardwareConfig->GetDXSupportLevel() < 100 )
{
m_nRenderSystem = RENDER_SYSTEM_DX9;
}
}
if ( !IsConsoleApp() )
return CreateMainWindow( bResizing );
return CreateMainConsoleWindow();
}
//-----------------------------------------------------------------------------
// Create our window
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::PostInit( )
{
if ( !BaseClass::PostInit() )
return false;
// Set up mod settings
ApplyModSettings();
return true;
}
void CMaterialSystem2App::PreShutdown()
{
if ( g_pInputSystem )
{
g_pInputSystem->DetachFromWindow( );
}
if ( g_pRenderDevice )
{
g_pRenderDevice->DestroySwapChain( m_hSwapChain );
m_hSwapChain = SWAP_CHAIN_HANDLE_INVALID;
}
BaseClass::PreShutdown();
}
//-----------------------------------------------------------------------------
// Creates the main 3d window
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::CreateMainWindow( bool bResizing )
{
// NOTE: This could be placed into a separate function
// Create a main 3d-capable window
int nWidth = 1280;
int nHeight = IsPlatformX360() ? 720 : 960;
bool bFullscreen = ( CommandLine()->CheckParm( "-fullscreen" ) != NULL );
const char *pArg;
if ( CommandLine()->CheckParm( "-width", &pArg ) )
{
nWidth = atoi( pArg );
}
if ( CommandLine()->CheckParm( "-height", &pArg ) )
{
nHeight = atoi( pArg );
}
m_hSwapChain = Create3DWindow( GetAppName(), nWidth, nHeight, bResizing, bFullscreen, true );
return ( m_hSwapChain != SWAP_CHAIN_HANDLE_INVALID );
}
bool CMaterialSystem2App::CreateMainConsoleWindow()
{
RenderDeviceInfo_t mode;
mode.m_DisplayMode.m_nWidth = 512;
mode.m_DisplayMode.m_nHeight = 512;
mode.m_DisplayMode.m_Format = IMAGE_FORMAT_RGBA8888;
mode.m_DisplayMode.m_nRefreshRateNumerator = 60;
mode.m_DisplayMode.m_nRefreshRateDenominator = 1;
mode.m_bFullscreen = false;
mode.m_nBackBufferCount = 1;
mode.m_bWaitForVSync = false;
#ifdef PLATFORM_WINDOWS_PC
m_hSwapChain = g_pRenderDevice->CreateSwapChain( Plat_GetShellWindow(), mode );
return ( m_hSwapChain != SWAP_CHAIN_HANDLE_INVALID );
#endif
return true;
}
//-----------------------------------------------------------------------------
// Creates a 3d-capable window
//-----------------------------------------------------------------------------
SwapChainHandle_t CMaterialSystem2App::Create3DWindow( const char *pTitle, int nWidth, int nHeight, bool bResizing, bool bFullscreen, bool bAcceptsInput )
{
PlatWindow_t hWnd = (PlatWindow_t)CreateAppWindow( GetAppInstance(), pTitle, !bFullscreen, nWidth, nHeight, bResizing );
if ( !hWnd )
return SWAP_CHAIN_HANDLE_INVALID;
// By default, everything will just use this one swap chain.
RenderDeviceInfo_t mode;
mode.m_DisplayMode.m_nWidth = nWidth;
mode.m_DisplayMode.m_nHeight = nHeight;
mode.m_DisplayMode.m_Format = IMAGE_FORMAT_RGBA8888;
mode.m_DisplayMode.m_nRefreshRateNumerator = 60;
mode.m_DisplayMode.m_nRefreshRateDenominator = 1;
mode.m_bFullscreen = bFullscreen;
mode.m_nBackBufferCount = bFullscreen ? 2 : 1;
mode.m_bWaitForVSync = ( CommandLine()->CheckParm( "-vsync" ) != NULL );
SwapChainHandle_t hSwapChain = g_pRenderDevice->CreateSwapChain( hWnd, mode );
if ( bAcceptsInput )
{
g_pInputSystem->AttachToWindow( (void*)hWnd );
}
return hSwapChain;
}
//-----------------------------------------------------------------------------
// Returns the window associated with a swap chain
//-----------------------------------------------------------------------------
PlatWindow_t CMaterialSystem2App::GetAppWindow()
{
if ( !m_hSwapChain || !g_pRenderDevice )
return PLAT_WINDOW_INVALID;
return g_pRenderDevice->GetSwapChainWindow( m_hSwapChain );
}
#endif // _WIN32

267
appframework/matsysapp.cpp Normal file
View File

@ -0,0 +1,267 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/matsysapp.h"
#include "FileSystem.h"
#include "materialsystem/IMaterialSystem.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "materialsystem/MaterialSystem_Config.h"
#include "filesystem_init.h"
#include "inputsystem/iinputsystem.h"
#include "tier2/tier2.h"
#include "videocfg/videocfg.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CMatSysApp::CMatSysApp()
{
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CMatSysApp::Create()
{
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
{ "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
if ( !AddSystems( appSystems ) )
return false;
IMaterialSystem *pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
if ( !pMaterialSystem )
{
Warning( "CMatSysApp::Create: Unable to connect to necessary interface!\n" );
return false;
}
pMaterialSystem->SetShaderAPI( "shaderapidx9.dll" );
return true;
}
void CMatSysApp::Destroy()
{
}
//-----------------------------------------------------------------------------
// Pump messages
//-----------------------------------------------------------------------------
void CMatSysApp::AppPumpMessages()
{
g_pInputSystem->PollInputState();
}
//-----------------------------------------------------------------------------
// Sets up the game path
//-----------------------------------------------------------------------------
bool CMatSysApp::SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool )
{
if ( !BaseClass::SetupSearchPaths( pStartingDir, bOnlyUseStartingDir, bIsTool ) )
return false;
g_pFullFileSystem->AddSearchPath( GetGameInfoPath(), "SKIN", PATH_ADD_TO_HEAD );
return true;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CMatSysApp::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
if ( !g_pFullFileSystem || !g_pMaterialSystem || !g_pInputSystem )
{
Warning( "CMatSysApp::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
// Add paths...
if ( !SetupSearchPaths( NULL, false, true ) )
return false;
const char *pArg;
int iWidth = 1024;
int iHeight = 768;
bool bWindowed = (CommandLine()->CheckParm( "-fullscreen" ) == NULL);
if (CommandLine()->CheckParm( "-width", &pArg ))
{
iWidth = atoi( pArg );
}
if (CommandLine()->CheckParm( "-height", &pArg ))
{
iHeight = atoi( pArg );
}
m_nWidth = iWidth;
m_nHeight = iHeight;
m_HWnd = CreateAppWindow( GetAppInstance(), GetAppName(), bWindowed, iWidth, iHeight, false );
if ( !m_HWnd )
return false;
g_pInputSystem->AttachToWindow( m_HWnd );
// NOTE: If we specifically wanted to use a particular shader DLL, we set it here...
//m_pMaterialSystem->SetShaderAPI( "shaderapidx8" );
// Get the adapter from the command line....
const char *pAdapterString;
int adapter = 0;
if (CommandLine()->CheckParm( "-adapter", &pAdapterString ))
{
adapter = atoi( pAdapterString );
}
int adapterFlags = 0;
if ( CommandLine()->CheckParm( "-ref" ) )
{
adapterFlags |= MATERIAL_INIT_REFERENCE_RASTERIZER;
}
if ( AppUsesReadPixels() )
{
adapterFlags |= MATERIAL_INIT_ALLOCATE_FULLSCREEN_TEXTURE;
}
g_pMaterialSystem->SetAdapter( adapter, adapterFlags );
return true;
}
void CMatSysApp::PostShutdown()
{
if ( g_pInputSystem )
{
g_pInputSystem->DetachFromWindow( );
}
BaseClass::PostShutdown();
}
//-----------------------------------------------------------------------------
// Gets the window size
//-----------------------------------------------------------------------------
int CMatSysApp::GetWindowWidth() const
{
return m_nWidth;
}
int CMatSysApp::GetWindowHeight() const
{
return m_nHeight;
}
//-----------------------------------------------------------------------------
// Returns the window
//-----------------------------------------------------------------------------
void* CMatSysApp::GetAppWindow()
{
return m_HWnd;
}
// Replace first underscore (if any) with \0 and return
// This handles special mods like tf_movies, l4d_movies, tf_comics
// As a result, such mods will use the gpu_level settings etc from the base mod
void StripModSuffix( char *pModName )
{
int i = 0;
while ( pModName[i] != '\0' ) // Walk to the end of the string
{
if ( pModName[i] == '_') // If we hit an underscore
{
pModName[i] = '\0'; // Terminate the string here and bail out
return;
}
i++;
}
}
//-----------------------------------------------------------------------------
// Sets the video mode
//-----------------------------------------------------------------------------
bool CMatSysApp::SetVideoMode( )
{
MaterialSystem_Config_t config;
if ( CommandLine()->CheckParm( "-fullscreen" ) )
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, false );
}
else
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
}
if ( CommandLine()->CheckParm( "-resizing" ) )
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, true );
}
if ( CommandLine()->CheckParm( "-mat_vsync" ) )
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, false );
}
config.m_nAASamples = CommandLine()->ParmValue( "-mat_antialias", 1 );
config.m_nAAQuality = CommandLine()->ParmValue( "-mat_aaquality", 0 );
if ( CommandLine()->FindParm( "-csm_quality_level" ) )
{
int nCSMQuality = CommandLine()->ParmValue( "-csm_quality_level", CSMQUALITY_VERY_LOW );
config.m_nCSMQuality = (CSMQualityMode_t)clamp( nCSMQuality, CSMQUALITY_VERY_LOW, CSMQUALITY_TOTAL_MODES - 1 );
}
config.m_VideoMode.m_Width = config.m_VideoMode.m_Height = 0;
config.m_VideoMode.m_Format = IMAGE_FORMAT_BGRX8888;
config.m_VideoMode.m_RefreshRate = 0;
config.SetFlag( MATSYS_VIDCFG_FLAGS_STENCIL, true );
bool modeSet = g_pMaterialSystem->SetMode( m_HWnd, config );
if (!modeSet)
{
Error( "Unable to set mode\n" );
return false;
}
char pModPath[MAX_PATH];
V_snprintf( pModPath, sizeof(pModPath), "" );
g_pFullFileSystem->GetSearchPath( "MOD", false, pModPath, sizeof( pModPath ) );
// Construct the mod name so we can use the mod-specific encrypted config files
char pModName[32];
V_StripTrailingSlash( pModPath );
V_FileBase( pModPath, pModName, sizeof( pModName ) );
StripModSuffix( pModName );
// Just use the highest levels in non-game apps
UpdateSystemLevel( CPU_LEVEL_HIGH, GPU_LEVEL_VERYHIGH, MEM_LEVEL_HIGH, GPU_MEM_LEVEL_HIGH, false, pModName );
g_pMaterialSystem->OverrideConfig( config, false );
return true;
}
#endif // _WIN32

180
appframework/posixapp.cpp Normal file
View File

@ -0,0 +1,180 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======//
//
// Purpose: Pieces of the application framework, shared between POSIX systems (Mac OS X, Linux, etc)
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "appframework/AppFramework.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "interface.h"
#include "filesystem.h"
#include "appframework/IAppSystemGroup.h"
#include "filesystem_init.h"
#include "tier1/convar.h"
#include "vstdlib/cvar.h"
#include "togl/rendermechanism.h"
// NOTE: This has to be the last file included! (turned off below, since this is included like a header)
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Globals...
//-----------------------------------------------------------------------------
HINSTANCE s_HInstance;
static CSimpleLoggingListener s_SimpleLoggingListener;
ILoggingListener *g_pDefaultLoggingListener = &s_SimpleLoggingListener;
//-----------------------------------------------------------------------------
// HACK: Since I don't want to refit vgui yet...
//-----------------------------------------------------------------------------
void *GetAppInstance()
{
return s_HInstance;
}
//-----------------------------------------------------------------------------
// Sets the application instance, should only be used if you're not calling AppMain.
//-----------------------------------------------------------------------------
void SetAppInstance( void* hInstance )
{
s_HInstance = (HINSTANCE)hInstance;
}
//-----------------------------------------------------------------------------
// Version of AppMain used by windows applications
//-----------------------------------------------------------------------------
int AppMain( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup )
{
Assert( 0 );
return -1;
}
static CNonFatalLoggingResponsePolicy s_NonFatalLoggingResponsePolicy;
//-----------------------------------------------------------------------------
// Version of AppMain used by console applications
//-----------------------------------------------------------------------------
int AppMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
LoggingSystem_SetLoggingResponsePolicy( &s_NonFatalLoggingResponsePolicy );
s_HInstance = NULL;
CommandLine()->CreateCmdLine( argc, argv );
return pAppSystemGroup->Run( );
}
//-----------------------------------------------------------------------------
//
// Default implementation of an application meant to be run using Steam
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSteamApplication::CSteamApplication( CSteamAppSystemGroup *pAppSystemGroup )
{
m_pChildAppSystemGroup = pAppSystemGroup;
m_pFileSystem = NULL;
}
//-----------------------------------------------------------------------------
// Create necessary interfaces
//-----------------------------------------------------------------------------
bool CSteamApplication::Create( )
{
FileSystem_SetErrorMode( FS_ERRORMODE_NONE );
char pFileSystemDLL[MAX_PATH];
if ( FileSystem_GetFileSystemDLLName( pFileSystemDLL, MAX_PATH, m_bSteam ) != FS_OK )
return false;
// Add in the cvar factory
AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() );
AddSystem( cvarModule, CVAR_INTERFACE_VERSION );
AppModule_t fileSystemModule = LoadModule( pFileSystemDLL );
m_pFileSystem = (IFileSystem*)AddSystem( fileSystemModule, FILESYSTEM_INTERFACE_VERSION );
if ( !m_pFileSystem )
{
Error( "Unable to load %s", pFileSystemDLL );
return false;
}
return true;
}
bool CSteamApplication::GetFileSystemDLLName( char *pOut, int nMaxBytes, bool &bIsSteam )
{
return FileSystem_GetFileSystemDLLName( pOut, nMaxBytes, bIsSteam ) == FS_OK;
}
//-----------------------------------------------------------------------------
// The file system pointer is invalid at this point
//-----------------------------------------------------------------------------
void CSteamApplication::Destroy()
{
m_pFileSystem = NULL;
}
//-----------------------------------------------------------------------------
// Pre-init, shutdown
//-----------------------------------------------------------------------------
bool CSteamApplication::PreInit( )
{
return true;
}
void CSteamApplication::PostShutdown( )
{
}
//-----------------------------------------------------------------------------
// Run steam main loop
//-----------------------------------------------------------------------------
int CSteamApplication::Main( )
{
// Now that Steam is loaded, we can load up main libraries through steam
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Run( );
}
int CSteamApplication::Startup()
{
int nRetVal = BaseClass::Startup();
if ( GetCurrentStage() != NONE )
return nRetVal;
if ( FileSystem_SetBasePaths( m_pFileSystem ) != FS_OK )
return 0;
// Now that Steam is loaded, we can load up main libraries through steam
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Startup();
}
void CSteamApplication::Shutdown()
{
m_pChildAppSystemGroup->Shutdown();
BaseClass::Shutdown();
}
// Turn off memdbg macros (turned on up top) since this is included like a header
#include "tier0/memdbgoff.h"

2137
appframework/sdlmgr.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,120 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/vguimaterialsystem2app.h"
#include "vgui/IVGui.h"
#include "vgui/ISurface.h"
#include "vgui_controls/controls.h"
#include "vgui/IScheme.h"
#include "vgui/ILocalize.h"
#include "tier0/dbg.h"
#include "vguirendersurface/ivguirendersurface.h"
#include "tier3/tier3.h"
#include "interfaces/interfaces.h"
#include "inputsystem/iinputstacksystem.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CVGuiMaterialSystem2App::CVGuiMaterialSystem2App()
{
m_hAppInputContext = INPUT_CONTEXT_HANDLE_INVALID;
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CVGuiMaterialSystem2App::Create()
{
if ( !BaseClass::Create() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSTACKSYSTEM_INTERFACE_VERSION },
// NOTE: This has to occur before vgui2.dll so it replaces vgui2's surface implementation
{ "vguirendersurface.dll", VGUI_SURFACE_INTERFACE_VERSION },
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
return AddSystems( appSystems );
}
void CVGuiMaterialSystem2App::Destroy()
{
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CVGuiMaterialSystem2App::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
ConnectTier3Libraries( &factory, 1 );
if ( !vgui::VGui_InitInterfacesList( "CVGuiMaterialSystem2App", &factory, 1 ) )
return false;
if ( !g_pVGuiRenderSurface )
{
Warning( "CVGuiMaterialSystem2App::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
return true;
}
bool CVGuiMaterialSystem2App::PostInit()
{
if ( !BaseClass::PostInit() )
return false;
m_hAppInputContext = g_pInputStackSystem->PushInputContext();
InputContextHandle_t hVGuiInputContext = g_pInputStackSystem->PushInputContext();
g_pVGuiRenderSurface->SetInputContext( hVGuiInputContext );
g_pVGuiRenderSurface->EnableWindowsMessages( true );
return true;
}
void CVGuiMaterialSystem2App::PreShutdown()
{
g_pVGuiRenderSurface->EnableWindowsMessages( false );
g_pVGuiRenderSurface->SetInputContext( NULL );
if ( m_hAppInputContext != INPUT_CONTEXT_HANDLE_INVALID )
{
g_pInputStackSystem->PopInputContext(); // Vgui
g_pInputStackSystem->PopInputContext(); // App
}
BaseClass::PreShutdown();
}
void CVGuiMaterialSystem2App::PostShutdown()
{
DisconnectTier3Libraries();
BaseClass::PostShutdown();
}
InputContextHandle_t CVGuiMaterialSystem2App::GetAppInputContext()
{
return m_hAppInputContext;
}
#endif // _WIN32

1
appframework/vsi.nul Normal file
View File

@ -0,0 +1 @@
IMPORTANT: Do not remove the custom build step for this file

View File

@ -0,0 +1,28 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\avi\avi.cpp
Debug output file: F:\csgo_64\cstrike15_src\avi\avi.cpp
Release output file: F:\csgo_64\cstrike15_src\avi\avi.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\avi\bink.cpp
Debug output file: F:\csgo_64\cstrike15_src\avi\bink.cpp
Release output file: F:\csgo_64\cstrike15_src\avi\bink.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Release output file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Containing unity file:
PCH file:

1184
avi/avi.cpp Normal file

File diff suppressed because it is too large Load Diff

30
avi/avi.h Normal file
View File

@ -0,0 +1,30 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef AVI_H
#define AVI_H
#ifdef _WIN32
#pragma once
#endif
#include "tier2/tier2.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IFileSystem;
class IMaterialSystem;
//-----------------------------------------------------------------------------
// Global interfaces
//-----------------------------------------------------------------------------
extern IFileSystem *g_pFileSystem;
#endif // AVI_H

662
avi/avi_osx.cpp Normal file
View File

@ -0,0 +1,662 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "avi/iavi.h"
#include "avi.h"
#include "filesystem.h"
#include "tier1/strtools.h"
#include "tier1/utllinkedlist.h"
#include "tier1/keyvalues.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/materialsystemutil.h"
#include "materialsystem/itexture.h"
#include "vtf/vtf.h"
#include "pixelwriter.h"
#include "tier3/tier3.h"
//-----------------------------------------------------------------------------
//
// Class used to write out AVI files
//
//-----------------------------------------------------------------------------
class CAviFile
{
public:
CAviFile();
void Init( const AVIParams_t& params, void *hWnd );
void Shutdown();
void AppendMovieSound( short *buf, size_t bufsize );
void AppendMovieFrame( const BGR888_t *pRGBData );
private:
void Reset();
void CreateVideoStreams( const AVIParams_t& params, void *hWnd );
void CreateAudioStream();
bool m_bValid;
int m_nWidth;
int m_nHeight;
int m_nFrameRate;
int m_nFrameScale;
int m_nFrame;
int m_nSample;
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CAviFile::CAviFile()
{
Reset();
}
//-----------------------------------------------------------------------------
// Reset the avi file
//-----------------------------------------------------------------------------
void CAviFile::Reset()
{
m_bValid = false;
m_nWidth = 0;
m_nHeight = 0;
m_nFrameRate = 0;
m_nFrameScale = 1;
m_nFrame = 0;
m_nSample = 0;
}
//-----------------------------------------------------------------------------
// Start recording an AVI
//-----------------------------------------------------------------------------
void CAviFile::Init( const AVIParams_t& params, void *hWnd )
{
Reset();
char avifilename[ 512 ];
char fullavifilename[ 512 ];
Q_snprintf( avifilename, sizeof( avifilename ), "%s", params.m_pFileName );
Q_SetExtension( avifilename, ".avi", sizeof( avifilename ) );
g_pFullFileSystem->RelativePathToFullPath( avifilename, params.m_pPathID, fullavifilename, sizeof( fullavifilename ) );
if ( g_pFullFileSystem->FileExists( fullavifilename, params.m_pPathID ) )
{
g_pFullFileSystem->RemoveFile( fullavifilename, params.m_pPathID );
}
m_nFrameRate = params.m_nFrameRate;
m_nFrameScale = params.m_nFrameScale;
m_bValid = true;
m_nHeight = params.m_nHeight;
m_nWidth = params.m_nWidth;
CreateVideoStreams( params, hWnd );
CreateAudioStream();
}
void CAviFile::Shutdown()
{
Reset();
}
void CAviFile::CreateVideoStreams( const AVIParams_t& params, void *hWnd )
{
}
void CAviFile::CreateAudioStream()
{
}
void CAviFile::AppendMovieSound( short *buf, size_t bufsize )
{
if ( !m_bValid )
return;
unsigned long numsamps = bufsize / sizeof( short ); // numbytes*8 / au->wfx.wBitsPerSample;
m_nSample += numsamps;
}
//-----------------------------------------------------------------------------
// Adds a frame of the movie to the AVI
//-----------------------------------------------------------------------------
void CAviFile::AppendMovieFrame( const BGR888_t *pRGBData )
{
if ( !m_bValid )
return;
++m_nFrame;
}
//-----------------------------------------------------------------------------
//
// Class used to associated AVI files with IMaterials
//
//-----------------------------------------------------------------------------
class CAVIMaterial : public ITextureRegenerator
{
public:
CAVIMaterial();
// Initializes, shuts down the material
bool Init( const char *pMaterialName, const char *pFileName, const char *pPathID );
void Shutdown();
// Inherited from ITextureRegenerator
virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect );
virtual void Release();
// Returns the material
IMaterial *GetMaterial();
// Returns the texcoord range
void GetTexCoordRange( float *pMaxU, float *pMaxV );
// Returns the frame size of the AVI (stored in a subrect of the material itself)
void GetFrameSize( int *pWidth, int *pHeight );
// Sets the current time
void SetTime( float flTime );
// Returns the frame rate/count of the AVI
int GetFrameRate( );
int GetFrameCount( );
// Sets the frame for an AVI material (use instead of SetTime)
void SetFrame( float flFrame );
private:
// Initializes, shuts down the procedural texture
void CreateProceduralTexture( const char *pTextureName );
void DestroyProceduralTexture();
// Initializes, shuts down the procedural material
void CreateProceduralMaterial( const char *pMaterialName );
void DestroyProceduralMaterial();
// Initializes, shuts down the video stream
void CreateVideoStream( );
void DestroyVideoStream( );
CMaterialReference m_Material;
CTextureReference m_Texture;
int m_nAVIWidth;
int m_nAVIHeight;
int m_nFrameRate;
int m_nFrameCount;
int m_nCurrentSample;
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CAVIMaterial::CAVIMaterial()
{
}
//-----------------------------------------------------------------------------
// Initializes the material
//-----------------------------------------------------------------------------
bool CAVIMaterial::Init( const char *pMaterialName, const char *pFileName, const char *pPathID )
{
// Determine the full path name of the AVI
char pAVIFileName[ 512 ];
char pFullAVIFileName[ 512 ];
Q_snprintf( pAVIFileName, sizeof( pAVIFileName ), "%s", pFileName );
Q_DefaultExtension( pAVIFileName, ".avi", sizeof( pAVIFileName ) );
g_pFullFileSystem->RelativePathToFullPath( pAVIFileName, pPathID, pFullAVIFileName, sizeof( pFullAVIFileName ) );
CreateProceduralTexture( pMaterialName );
CreateProceduralMaterial( pMaterialName );
CreateVideoStream();
m_Texture->Download();
return true;
}
void CAVIMaterial::Shutdown()
{
DestroyVideoStream();
DestroyProceduralMaterial( );
DestroyProceduralTexture( );
}
//-----------------------------------------------------------------------------
// Returns the material
//-----------------------------------------------------------------------------
IMaterial *CAVIMaterial::GetMaterial()
{
return m_Material;
}
//-----------------------------------------------------------------------------
// Returns the texcoord range
//-----------------------------------------------------------------------------
void CAVIMaterial::GetTexCoordRange( float *pMaxU, float *pMaxV )
{
if ( !m_Texture )
{
*pMaxU = *pMaxV = 1.0f;
return;
}
int nTextureWidth = m_Texture->GetActualWidth();
int nTextureHeight = m_Texture->GetActualHeight();
*pMaxU = (float)m_nAVIWidth / (float)nTextureWidth;
*pMaxV = (float)m_nAVIHeight / (float)nTextureHeight;
}
//-----------------------------------------------------------------------------
// Returns the frame size of the AVI (stored in a subrect of the material itself)
//-----------------------------------------------------------------------------
void CAVIMaterial::GetFrameSize( int *pWidth, int *pHeight )
{
*pWidth = m_nAVIWidth;
*pHeight = m_nAVIHeight;
}
//-----------------------------------------------------------------------------
// Computes a power of two at least as big as the passed-in number
//-----------------------------------------------------------------------------
static inline int ComputeGreaterPowerOfTwo( int n )
{
int i = 1;
while ( i < n )
{
i <<= 1;
}
return i;
}
//-----------------------------------------------------------------------------
// Initializes, shuts down the procedural texture
//-----------------------------------------------------------------------------
void CAVIMaterial::CreateProceduralTexture( const char *pTextureName )
{
// Choose power-of-two textures which are at least as big as the AVI
int nWidth = ComputeGreaterPowerOfTwo( m_nAVIWidth );
int nHeight = ComputeGreaterPowerOfTwo( m_nAVIHeight );
m_Texture.InitProceduralTexture( pTextureName, "avi", nWidth, nHeight,
IMAGE_FORMAT_RGBA8888, TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_NOMIP |
TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
m_Texture->SetTextureRegenerator( this );
}
void CAVIMaterial::DestroyProceduralTexture()
{
if (m_Texture)
{
m_Texture->SetTextureRegenerator( NULL );
m_Texture.Shutdown();
}
}
//-----------------------------------------------------------------------------
// Initializes, shuts down the procedural material
//-----------------------------------------------------------------------------
void CAVIMaterial::CreateProceduralMaterial( const char *pMaterialName )
{
// FIXME: gak, this is backwards. Why doesn't the material just see that it has a funky basetexture?
char vmtfilename[ 512 ];
Q_strcpy( vmtfilename, pMaterialName );
Q_SetExtension( vmtfilename, ".vmt", sizeof( vmtfilename ) );
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
if (!pVMTKeyValues->LoadFromFile( g_pFullFileSystem , vmtfilename, "GAME" ))
{
pVMTKeyValues->SetString( "$basetexture", m_Texture->GetName() );
pVMTKeyValues->SetInt( "$nofog", 1 );
pVMTKeyValues->SetInt( "$spriteorientation", 3 );
pVMTKeyValues->SetInt( "$translucent", 1 );
}
m_Material.Init( pMaterialName, pVMTKeyValues );
m_Material->Refresh();
}
void CAVIMaterial::DestroyProceduralMaterial()
{
m_Material.Shutdown();
}
//-----------------------------------------------------------------------------
// Sets the current time
//-----------------------------------------------------------------------------
void CAVIMaterial::SetTime( float flTime )
{
}
//-----------------------------------------------------------------------------
// Returns the frame rate of the AVI
//-----------------------------------------------------------------------------
int CAVIMaterial::GetFrameRate( )
{
return m_nFrameRate;
}
int CAVIMaterial::GetFrameCount( )
{
return m_nFrameCount;
}
//-----------------------------------------------------------------------------
// Sets the frame for an AVI material (use instead of SetTime)
//-----------------------------------------------------------------------------
void CAVIMaterial::SetFrame( float flFrame )
{
}
//-----------------------------------------------------------------------------
// Initializes, shuts down the video stream
//-----------------------------------------------------------------------------
void CAVIMaterial::CreateVideoStream( )
{
}
void CAVIMaterial::DestroyVideoStream( )
{
}
//-----------------------------------------------------------------------------
// Inherited from ITextureRegenerator
//-----------------------------------------------------------------------------
void CAVIMaterial::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
{
}
void CAVIMaterial::Release()
{
}
//-----------------------------------------------------------------------------
//
// Implementation of IAvi
//
//-----------------------------------------------------------------------------
class CAvi : public CTier3AppSystem< IAvi >
{
typedef CTier3AppSystem< IAvi > BaseClass;
public:
CAvi();
// Inherited from IAppSystem
virtual bool Connect( CreateInterfaceFn factory );
virtual void *QueryInterface( const char *pInterfaceName );
virtual InitReturnVal_t Init();
virtual void Shutdown();
// Inherited from IAvi
virtual void SetMainWindow( void* hWnd );
virtual AVIHandle_t StartAVI( const AVIParams_t& params );
virtual void FinishAVI( AVIHandle_t h );
virtual void AppendMovieSound( AVIHandle_t h, short *buf, size_t bufsize );
virtual void AppendMovieFrame( AVIHandle_t h, const BGR888_t *pRGBData );
virtual AVIMaterial_t CreateAVIMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID );
virtual void DestroyAVIMaterial( AVIMaterial_t hMaterial );
virtual void SetTime( AVIMaterial_t hMaterial, float flTime );
virtual IMaterial* GetMaterial( AVIMaterial_t hMaterial );
virtual void GetTexCoordRange( AVIMaterial_t hMaterial, float *pMaxU, float *pMaxV );
virtual void GetFrameSize( AVIMaterial_t hMaterial, int *pWidth, int *pHeight );
virtual int GetFrameRate( AVIMaterial_t hMaterial );
virtual void SetFrame( AVIMaterial_t hMaterial, float flFrame );
virtual int GetFrameCount( AVIMaterial_t hMaterial );
private:
CUtlLinkedList< CAviFile, AVIHandle_t > m_AVIFiles;
// NOTE: Have to use pointers here since AVIMaterials inherit from ITextureRegenerator
// The realloc screws up the pointers held to ITextureRegenerators in the material system.
CUtlLinkedList< CAVIMaterial*, AVIMaterial_t > m_AVIMaterials;
};
//-----------------------------------------------------------------------------
// Singleton
//-----------------------------------------------------------------------------
static CAvi g_AVI;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CAvi, IAvi, AVI_INTERFACE_VERSION, g_AVI );
//-----------------------------------------------------------------------------
// Constructor/destructor
//-----------------------------------------------------------------------------
CAvi::CAvi()
{
}
//-----------------------------------------------------------------------------
// Connect/disconnect
//-----------------------------------------------------------------------------
bool CAvi::Connect( CreateInterfaceFn factory )
{
if ( !BaseClass::Connect( factory ) )
return false;
if ( !( g_pFullFileSystem && materials ) )
{
Msg( "Avi failed to connect to a required system\n" );
}
return ( g_pFullFileSystem && materials );
}
//-----------------------------------------------------------------------------
// Query Interface
//-----------------------------------------------------------------------------
void *CAvi::QueryInterface( const char *pInterfaceName )
{
if (!Q_strncmp( pInterfaceName, AVI_INTERFACE_VERSION, Q_strlen(AVI_INTERFACE_VERSION) + 1))
return (IAvi*)this;
return NULL;
}
//-----------------------------------------------------------------------------
// Init/shutdown
//-----------------------------------------------------------------------------
InitReturnVal_t CAvi::Init()
{
InitReturnVal_t nRetVal = BaseClass::Init();
if ( nRetVal != INIT_OK )
return nRetVal;
return INIT_OK;
}
void CAvi::Shutdown()
{
BaseClass::Shutdown();
}
//-----------------------------------------------------------------------------
// Sets the main window
//-----------------------------------------------------------------------------
void CAvi::SetMainWindow( void* hWnd )
{
Assert( false );
}
//-----------------------------------------------------------------------------
// Start, finish recording an AVI
//-----------------------------------------------------------------------------
AVIHandle_t CAvi::StartAVI( const AVIParams_t& params )
{
AVIHandle_t h = m_AVIFiles.AddToTail();
m_AVIFiles[h].Init( params, NULL /*hwnd*/ );
return h;
}
void CAvi::FinishAVI( AVIHandle_t h )
{
if ( h != AVIHANDLE_INVALID )
{
m_AVIFiles[h].Shutdown();
m_AVIFiles.Remove( h );
}
}
//-----------------------------------------------------------------------------
// Add sound buffer
//-----------------------------------------------------------------------------
void CAvi::AppendMovieSound( AVIHandle_t h, short *buf, size_t bufsize )
{
if ( h != AVIHANDLE_INVALID )
{
m_AVIFiles[h].AppendMovieSound( buf, bufsize );
}
}
//-----------------------------------------------------------------------------
// Add movie frame
//-----------------------------------------------------------------------------
void CAvi::AppendMovieFrame( AVIHandle_t h, const BGR888_t *pRGBData )
{
if ( h != AVIHANDLE_INVALID )
{
m_AVIFiles[h].AppendMovieFrame( pRGBData );
}
}
//-----------------------------------------------------------------------------
// Create/destroy an AVI material
//-----------------------------------------------------------------------------
AVIMaterial_t CAvi::CreateAVIMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID )
{
AVIMaterial_t h = m_AVIMaterials.AddToTail();
m_AVIMaterials[h] = new CAVIMaterial;
m_AVIMaterials[h]->Init( pMaterialName, pFileName, pPathID );
return h;
}
void CAvi::DestroyAVIMaterial( AVIMaterial_t h )
{
if ( h != AVIMATERIAL_INVALID )
{
m_AVIMaterials[h]->Shutdown();
delete m_AVIMaterials[h];
m_AVIMaterials.Remove( h );
}
}
//-----------------------------------------------------------------------------
// Sets the time for an AVI material
//-----------------------------------------------------------------------------
void CAvi::SetTime( AVIMaterial_t h, float flTime )
{
if ( h != AVIMATERIAL_INVALID )
{
m_AVIMaterials[h]->SetTime( flTime );
}
}
//-----------------------------------------------------------------------------
// Gets the IMaterial associated with an AVI material
//-----------------------------------------------------------------------------
IMaterial* CAvi::GetMaterial( AVIMaterial_t h )
{
if ( h != AVIMATERIAL_INVALID )
return m_AVIMaterials[h]->GetMaterial();
return NULL;
}
//-----------------------------------------------------------------------------
// Returns the max texture coordinate of the AVI
//-----------------------------------------------------------------------------
void CAvi::GetTexCoordRange( AVIMaterial_t h, float *pMaxU, float *pMaxV )
{
if ( h != AVIMATERIAL_INVALID )
{
m_AVIMaterials[h]->GetTexCoordRange( pMaxU, pMaxV );
}
else
{
*pMaxU = *pMaxV = 1.0f;
}
}
//-----------------------------------------------------------------------------
// Returns the frame size of the AVI (is a subrect of the material itself)
//-----------------------------------------------------------------------------
void CAvi::GetFrameSize( AVIMaterial_t h, int *pWidth, int *pHeight )
{
if ( h != AVIMATERIAL_INVALID )
{
m_AVIMaterials[h]->GetFrameSize( pWidth, pHeight );
}
else
{
*pWidth = *pHeight = 1;
}
}
//-----------------------------------------------------------------------------
// Returns the frame rate of the AVI
//-----------------------------------------------------------------------------
int CAvi::GetFrameRate( AVIMaterial_t h )
{
if ( h != AVIMATERIAL_INVALID )
return m_AVIMaterials[h]->GetFrameRate();
return 1;
}
int CAvi::GetFrameCount( AVIMaterial_t h )
{
if ( h != AVIMATERIAL_INVALID )
return m_AVIMaterials[h]->GetFrameCount();
return 1;
}
//-----------------------------------------------------------------------------
// Sets the frame for an AVI material (use instead of SetTime)
//-----------------------------------------------------------------------------
void CAvi::SetFrame( AVIMaterial_t h, float flFrame )
{
if ( h != AVIMATERIAL_INVALID )
{
m_AVIMaterials[h]->SetFrame( flFrame );
}
}

1938
avi/bink.cpp Normal file

File diff suppressed because it is too large Load Diff

1133
avi/quicktime.cpp Normal file

File diff suppressed because it is too large Load Diff

274
avi/quicktime.h Normal file
View File

@ -0,0 +1,274 @@
//===== Copyright (c) 2010, Valve Corporation, All rights reserved. ===========
//
// Purpose:
//
//=============================================================================
#ifndef QUICKTIME_H
#define QUICKTIME_H
#ifdef _WIN32
#pragma once
#endif
#include <avi/iquicktime.h>
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IFileSystem;
class IMaterialSystem;
class CQuickTimeMaterial;
//-----------------------------------------------------------------------------
// Global interfaces - you already did the needed includes, right?
//-----------------------------------------------------------------------------
extern IFileSystem *g_pFileSystem;
extern IMaterialSystem *materials;
//-----------------------------------------------------------------------------
// Quicktime includes - conditional compilation on #define QUICKTIME in VPC
// The intent is to have a default functionality fallback if not defined
// which provides a dynamically generated texture (moving line on background)
//-----------------------------------------------------------------------------
#if defined( QUICKTIME_VIDEO )
#if defined ( OSX )
#include <quicktime/QTML.h>
#include <quicktime/Movies.h>
#elif defined ( WIN32 )
#include <QTML.h>
#include <Movies.h>
#include <windows.h>
#endif
#else
typedef TimeValue long;
#endif
// -----------------------------------------------------------------------
// eVideoFrameFormat_t - bitformat for quicktime video frames
// -----------------------------------------------------------------------
enum eVideoFrameFormat_t
{
cVFF_Undefined = 0,
cVFF_R8G8B8A8_32Bit,
cVFF_R8G8B8_24Bit,
cVFF_Count, // Auto list counter
cVFF_ForceInt32 = 0x7FFFFFFF // Make sure eNum is (at least) an int32
};
//-----------------------------------------------------------------------------
// texture regenerator - callback to get new movie pixels into the texture
//-----------------------------------------------------------------------------
class CQuicktimeMaterialRGBTextureRegenerator : public ITextureRegenerator
{
public:
CQuicktimeMaterialRGBTextureRegenerator() :
m_pQTMaterial( NULL ),
m_nSourceWidth( 0 ),
m_nSourceHeight( 0 )
{
}
void SetParentMaterial( CQuickTimeMaterial *pQTMaterial, int nWidth, int nHeight )
{
m_pQTMaterial = pQTMaterial;
m_nSourceWidth = nWidth;
m_nSourceHeight = nHeight;
}
// Inherited from ITextureRegenerator
virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect );
virtual void Release();
private:
CQuickTimeMaterial *m_pQTMaterial;
int m_nSourceWidth;
int m_nSourceHeight;
};
//-----------------------------------------------------------------------------
//
// Class used to associated QuickTime video files with IMaterials
//
//-----------------------------------------------------------------------------
class CQuickTimeMaterial
{
public:
CQuickTimeMaterial();
~CQuickTimeMaterial();
// Initializes, shuts down the material
bool Init( const char *pMaterialName, const char *pFileName, const char *pPathID );
void Shutdown();
// Keeps the frames updated
bool Update( void );
// Check if a new frame is available
bool ReadyForSwap( void );
// Returns the material
IMaterial *GetMaterial();
// Returns the texcoord range
void GetTexCoordRange( float *pMaxU, float *pMaxV );
// Returns the frame size of the QuickTime Video (stored in a subrect of the material itself)
void GetFrameSize( int *pWidth, int *pHeight );
// Sets the current time
void SetTime( float flTime );
// Returns the frame rate/count of the QuickTime Material
int GetFrameRate( );
int GetFrameCount( );
// Sets the frame for an QuickTime material (use instead of SetTime) ??
void SetFrame( float flFrame );
void SetLooping( bool loop );
private:
friend class CQuicktimeMaterialRGBTextureRegenerator;
void Reset();
void OpenQTMovie( const char* theQTMovieFileName );
void SetQTFileName( const char *theQTMovieFileName );
void GetErrorFrame();
void CloseQTFile();
// Initializes, shuts down the procedural texture
void CreateProceduralTexture( const char *pTextureName );
void DestroyProceduralTexture();
// Initializes, shuts down the procedural material
void CreateProceduralMaterial( const char *pMaterialName );
void DestroyProceduralMaterial();
// Initializes, shuts down the video stream
CQuicktimeMaterialRGBTextureRegenerator m_TextureRegen;
CMaterialReference m_Material; // Ref to Material used for rendering the video frame
CTextureReference m_Texture; // Ref to the renderable texture which contains the most recent video frame (in a sub-rect)
float m_TexCordU; // Max U texture coordinate of the texture sub-rect which holds the video frame
float m_TexCordV; // Max V texture coordinate of the texture sub-rect which holds the video frame
int m_VideoFrameWidth;
int m_VideoFrameHeight;
char *m_pFileName;
char m_TextureName[128];
char m_MaterialName[128];
bool m_bActive;
bool m_bLoopMovie;
bool m_bMoviePlaying;
double m_MovieBeganPlayingTime;
double m_MovieCurrentTime;
#if defined( QUICKTIME_VIDEO )
// QuickTime Stuff
Movie m_QTMovie;
TimeValue m_QTMovieTimeScale; // Units per second
TimeValue m_QTMovieDuration; // movie duration is UPS
float m_QTMovieDurationinSec; // movie duration in seconds
long m_QTMoveFrameRate;
Rect m_QTMovieRect;
GWorldPtr m_MovieGWorld;
QTAudioContextRef m_AudioContext;
TimeValue m_LastInterestingTimePlayed;
TimeValue m_NextInterestingTimeToPlay;
// our Frame buffer stuff
#if defined ( WIN32 )
BITMAPINFO m_BitmapInfo;
#endif
#endif
void *m_BitMapData;
int m_BitMapDataSize;
bool m_bIsErrorFrame;
float m_nLastFrameTime;
static const int cMaxQTFileNameLen = 255;
static const int cMinVideoFrameWidth = 16;
static const int cMinVideoFrameHeight = 16;
static const int cMaxVideoFrameWidth = 2048;
static const int cMaxVideoFrameHeight = 2048;
};
//-----------------------------------------------------------------------------
//
// Implementation of IQuickTime
//
//-----------------------------------------------------------------------------
class CQuickTime : public CBaseAppSystem<IQuickTime>
{
public:
CQuickTime();
~CQuickTime();
// Inherited from IAppSystem
virtual bool Connect( CreateInterfaceFn factory );
virtual void Disconnect();
virtual void *QueryInterface( const char *pInterfaceName );
virtual InitReturnVal_t Init();
virtual void Shutdown();
// Inherited from IQuickTime
virtual QUICKTIMEMaterial_t CreateMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID, int flags = 0 );
virtual void DestroyMaterial( QUICKTIMEMaterial_t hMaterial );
virtual bool Update( QUICKTIMEMaterial_t hMaterial );
virtual bool ReadyForSwap( QUICKTIMEMaterial_t hMaterial );
virtual IMaterial *GetMaterial( QUICKTIMEMaterial_t hMaterial );
virtual void GetTexCoordRange( QUICKTIMEMaterial_t hMaterial, float *pMaxU, float *pMaxV );
virtual void GetFrameSize( QUICKTIMEMaterial_t hMaterial, int *pWidth, int *pHeight );
virtual int GetFrameRate( QUICKTIMEMaterial_t hMaterial );
virtual void SetFrame( QUICKTIMEMaterial_t hMaterial, float flFrame );
virtual int GetFrameCount( QUICKTIMEMaterial_t hMaterial );
virtual bool SetSoundDevice( void *pDevice );
private:
bool SetupQuicktime();
void ShutdownQuicktime();
// NOTE: Have to use pointers here since QuickTimeKMaterials inherit from ITextureRegenerator
// The realloc screws up the pointers held to ITextureRegenerators in the material system.
CUtlLinkedList< CQuickTimeMaterial*, QUICKTIMEMaterial_t > m_QTMaterials;
bool m_bQTInitialized;
};
#endif // QUICKTIME_H

74
avi/valve_avi.vpc Normal file
View File

@ -0,0 +1,74 @@
//-----------------------------------------------------------------------------
// VALVE_AVI.VPC
//
// Project Script
//
// MGP 4/010 Updated to support Quicktime on OSX. Win32 builds can optionally
// be enabled for cross platform work if quickTime is installed on the Win32
// PC.
//-----------------------------------------------------------------------------
$Macro SRCDIR ".."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$include "$SRCDIR\vpc_scripts\source_video_base.vpc"
$Configuration
{
$Compiler
{
// Win32 - need to point to Quicktime 7 for Win SDK directory so that dependant includes will work
$AdditionalIncludeDirectories "$BASE,..\common\quicktime_win32\" [$QUICKTIME_WINDOWS]
$AdditionalIncludeDirectories "$BASE;$SRCDIR\dx9sdk\include" [$WINDOWS]
$AdditionalIncludeDirectories "$BASE;$SRCDIR\thirdparty\sdl\include;$SRCDIR\thirdparty\sdl_mixer" [$LINUXALL]
}
$Linker
{
$IgnoreImportLibrary "Yes" [$WINDOWS]
$AdditionalDependencies "$BASE vfw32.lib" [$WINDOWS]
$SystemLibraries "iconv" [$OSXALL]
$SystemFrameworks "Quicktime;Carbon"
$AdditionalLibraryDirectories "$BASE;$SRCDIR\dx9sdk\lib" [$WINDOWS]
$GCC_ExtraLinkerFlags "-z muldefs -L$SRCDIR/thirdparty/sdl/build/.libs" [$LINUXALL]
$SystemLibraries "SDL2" [$LINUXALL]
}
}
$Project "valve_avi"
{
$Folder "Source Files"
{
$File "avi.cpp" [$WINDOWS]
$File "avi_osx.cpp" [$OSXALL]
$File "bink.cpp" [!$OSXALL]
$file "quicktime.cpp" [$QUICKTIME_VIDEO||$QUICKTIME_WINDOWS]
}
$Folder "Header Files"
{
$File "avi.h"
$file "quicktime.h"
// $File "$SRCDIR\BinkSDK\bink.h"
$File "$SRCDIR\public\pixelwriter.h"
}
$Folder "Interface"
{
$File "$SRCDIR\public\avi\iavi.h"
$File "$SRCDIR\public\avi\ibik.h"
$File "$SRCDIR\public\avi\iquicktime.h"
}
$Folder "Link Libraries" [$WINDOWS||$X360||$POSIX]
{
$Lib tier2
$lib tier3
$File "$SRCDIR\lib\common\quicktime\QTMLClient.lib" [$QUICKTIME_WINDOWS]
$File "$SRCDIR\DX9SDK\lib\dsound.lib" [$QUICKTIME_WINDOWS]
$File "$SRCDIR\DX9SDK\lib\dxguid.lib" [$QUICKTIME_WINDOWS]
$File "$SRCDIR\lib\common\libSDL2_mixer.a" [$LINUXALL]
}
}

View File

@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "valve_avi.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "valve_avi.vcxproj"
"1" "valve_avi.vcxproj.filters"
}
}
}

277
bitmap/ImageByteSwap.cpp Normal file
View File

@ -0,0 +1,277 @@
//======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Image Byte Swapping. Isolate routines to own module to allow librarian
// to ignore xbox 360 dependenices in non-applicable win32 projects.
//
//=============================================================================//
#if defined( _WIN32 ) && !defined( _X360 ) && !defined( DX_TO_GL_ABSTRACTION )
#include <windows.h>
#endif
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "bitmap/imageformat.h"
// Should be last include
#include "tier0/memdbgon.h"
#if defined( _WIN32 ) && !defined( _X360 ) && !defined( NO_X360_XDK ) && !defined( DX_TO_GL_ABSTRACTION )
#if defined( XDK_INSTALLED )
// the x86 version of the 360 (used by win32 tools)
// It would have been nice to use the 360 D3DFORMAT bit encodings, but the codes
// are different for WIN32, and this routine is used by a WIN32 library to
// manipulate 360 data, so there can be no reliance on WIN32 D3DFORMAT bits
#include "d3d9.h"
#include "XGraphics.h"
#endif
#endif
namespace ImageLoader
{
//-----------------------------------------------------------------------------
// Known formats that can be converted. Used as a trap for 360 formats
// that may occur but have not been validated yet.
//-----------------------------------------------------------------------------
bool IsFormatValidForConversion( ImageFormat fmt )
{
switch ( fmt )
{
case IMAGE_FORMAT_RGBA8888:
case IMAGE_FORMAT_ABGR8888:
case IMAGE_FORMAT_RGB888:
case IMAGE_FORMAT_BGR888:
case IMAGE_FORMAT_ARGB8888:
case IMAGE_FORMAT_BGRA8888:
case IMAGE_FORMAT_BGRX8888:
case IMAGE_FORMAT_UVWQ8888:
case IMAGE_FORMAT_RGBA16161616F:
case IMAGE_FORMAT_RGBA16161616:
case IMAGE_FORMAT_UVLX8888:
case IMAGE_FORMAT_DXT1:
case IMAGE_FORMAT_DXT1_ONEBITALPHA:
case IMAGE_FORMAT_DXT3:
case IMAGE_FORMAT_DXT5:
case IMAGE_FORMAT_UV88:
return true;
// untested formats
default:
case IMAGE_FORMAT_RGB565:
case IMAGE_FORMAT_I8:
case IMAGE_FORMAT_IA88:
case IMAGE_FORMAT_A8:
case IMAGE_FORMAT_RGB888_BLUESCREEN:
case IMAGE_FORMAT_BGR888_BLUESCREEN:
case IMAGE_FORMAT_BGR565:
case IMAGE_FORMAT_BGRX5551:
case IMAGE_FORMAT_BGRA4444:
case IMAGE_FORMAT_BGRA5551:
case IMAGE_FORMAT_ATI1N:
case IMAGE_FORMAT_ATI2N:
break;
}
return false;
}
//-----------------------------------------------------------------------------
// Swaps the image element type within the format.
// This is to ensure that >8 bit channels are in the correct endian format
// as expected by the conversion process, which varies according to format,
// input, and output.
//-----------------------------------------------------------------------------
void PreConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, VtfConsoleFormatType_t targetConsole, int width, int stride )
{
Assert( IsFormatValidForConversion( imageFormat ) );
#ifndef DX_TO_GL_ABSTRACTION
if ( IsPC() )
{
// running as a win32 tool, data is in expected order
// for conversion code
return;
}
// If licensees don't have the XDK installed they are not going to be able to do image conversion and shouldn't need to
#if defined (XDK_INSTALLED)
// running on 360 and converting, input data must be x86 order
// swap to ensure conversion code gets valid data
XGENDIANTYPE xEndian;
switch ( imageFormat )
{
default:
return;
case IMAGE_FORMAT_RGBA16161616F:
case IMAGE_FORMAT_RGBA16161616:
xEndian = XGENDIAN_8IN16;
break;
}
int count;
if ( !stride )
{
stride = XGENDIANTYPE_GET_DATA_SIZE( xEndian );
count = nImageSize / stride;
XGEndianSwapMemory( pImageData, pImageData, xEndian, stride, count );
}
else
{
int nRows = nImageSize/stride;
for ( int i=0; i<nRows; i++ )
{
XGEndianSwapMemory( pImageData, pImageData, xEndian, XGENDIANTYPE_GET_DATA_SIZE( xEndian ), width );
pImageData += stride;
}
}
#endif // XDK_INSTALLED
#endif // COMPILER_MSVC32
}
//-----------------------------------------------------------------------------
// Swaps image bytes for use on a big endian platform. This is used after the conversion
// process to match the 360 d3dformats.
//-----------------------------------------------------------------------------
void PostConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, VtfConsoleFormatType_t targetConsole, int width, int stride )
{
Assert( IsFormatValidForConversion( imageFormat ) );
#ifndef DX_TO_GL_ABSTRACTION
// If licensees don't have the XDK installed they are not going to be able to do image conversion and shouldn't need to
#if defined (XDK_INSTALLED)
// It would have been nice to use the 360 D3DFORMAT bit encodings, but the codes
// are different for win32, and this routine is used by a win32 library to
// manipulate 360 data, so there can be no reliance on D3DFORMAT bits
XGENDIANTYPE xEndian;
switch ( imageFormat )
{
default:
return;
case IMAGE_FORMAT_RGBA16161616F:
case IMAGE_FORMAT_RGBA16161616:
if ( IsGameConsole() )
{
// running on 360 the conversion output is correct
return;
}
// running on the pc, the output needs to be in 360 order
xEndian = XGENDIAN_8IN16;
break;
case IMAGE_FORMAT_DXT1:
case IMAGE_FORMAT_DXT1_ONEBITALPHA:
case IMAGE_FORMAT_DXT3:
case IMAGE_FORMAT_DXT5:
case IMAGE_FORMAT_UV88:
case IMAGE_FORMAT_ATI1N:
case IMAGE_FORMAT_ATI2N:
// Don't endian swap compressed textures for PS3, but swap everything else just like Xbox360
if ( targetConsole == VTF_CONSOLE_PS3 )
return;
xEndian = XGENDIAN_8IN16;
break;
case IMAGE_FORMAT_BGRA8888:
case IMAGE_FORMAT_BGRX8888:
case IMAGE_FORMAT_UVWQ8888:
case IMAGE_FORMAT_UVLX8888:
xEndian = XGENDIAN_8IN32;
break;
}
int count;
if ( !stride )
{
stride = XGENDIANTYPE_GET_DATA_SIZE( xEndian );
count = nImageSize / stride;
XGEndianSwapMemory( pImageData, pImageData, xEndian, stride, count );
}
else
{
int nRows = nImageSize/stride;
for ( int i=0; i<nRows; i++ )
{
XGEndianSwapMemory( pImageData, pImageData, xEndian, XGENDIANTYPE_GET_DATA_SIZE( xEndian ), width );
pImageData += stride;
}
}
#endif // XDK_INSTALLED
#endif // COMPILER_MSVC32
}
//-----------------------------------------------------------------------------
// Swaps image bytes.
//-----------------------------------------------------------------------------
void ByteSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width, int stride )
{
Assert( IsFormatValidForConversion( imageFormat ) );
#ifndef DX_TO_GL_ABSTRACTION
// If licensees don't have the XDK installed they are not going to be able to do image conversion and shouldn't need to
#if defined (XDK_INSTALLED)
XGENDIANTYPE xEndian;
switch ( imageFormat )
{
case IMAGE_FORMAT_BGR888:
case IMAGE_FORMAT_I8:
case IMAGE_FORMAT_A8:
default:
return;
case IMAGE_FORMAT_BGRA8888:
case IMAGE_FORMAT_BGRX8888:
case IMAGE_FORMAT_UVWQ8888:
case IMAGE_FORMAT_UVLX8888:
case IMAGE_FORMAT_R32F:
case IMAGE_FORMAT_RGBA32323232F:
xEndian = XGENDIAN_8IN32;
break;
case IMAGE_FORMAT_BGR565:
case IMAGE_FORMAT_BGRX5551:
case IMAGE_FORMAT_BGRA5551:
case IMAGE_FORMAT_BGRA4444:
case IMAGE_FORMAT_IA88:
case IMAGE_FORMAT_DXT1:
case IMAGE_FORMAT_DXT1_ONEBITALPHA:
case IMAGE_FORMAT_DXT3:
case IMAGE_FORMAT_DXT5:
case IMAGE_FORMAT_ATI1N:
case IMAGE_FORMAT_ATI2N:
case IMAGE_FORMAT_UV88:
case IMAGE_FORMAT_RGBA16161616F:
case IMAGE_FORMAT_RGBA16161616:
xEndian = XGENDIAN_8IN16;
break;
}
int count;
if ( !stride )
{
stride = XGENDIANTYPE_GET_DATA_SIZE( xEndian );
count = nImageSize / stride;
XGEndianSwapMemory( pImageData, pImageData, xEndian, stride, count );
}
else
{
int nRows = nImageSize/stride;
for ( int i=0; i<nRows; i++ )
{
XGEndianSwapMemory( pImageData, pImageData, xEndian, XGENDIANTYPE_GET_DATA_SIZE( xEndian ), width );
pImageData += stride;
}
}
#endif // XDK_INSTALLED
#endif // COMPILER_MSVC32
}
}

View File

@ -0,0 +1,100 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\bitmap\bitmap.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\bitmap.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\bitmap.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\colorconversion.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\colorconversion.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\colorconversion.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap2.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap2.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap2.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap3.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap3.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap3.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap4.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap4.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap4.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap_bilateralfilter.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap_bilateralfilter.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\floatbitmap_bilateralfilter.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\floatcubemap.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\floatcubemap.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\floatcubemap.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\imageformat.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\imageformat.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\imageformat.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\psd.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\psd.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\psd.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\psheet.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\psheet.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\psheet.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\resample.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\resample.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\resample.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\texturepacker.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\texturepacker.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\texturepacker.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\tgaloader.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\tgaloader.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\tgaloader.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\tgawriter.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\tgawriter.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\tgawriter.cpp
Containing unity file:
PCH file:

View File

@ -0,0 +1,16 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bitmap\ImageByteSwap.cpp
Debug output file: F:\csgo_64\cstrike15_src\bitmap\ImageByteSwap.cpp
Release output file: F:\csgo_64\cstrike15_src\bitmap\ImageByteSwap.cpp
Containing unity file:
PCH file:

778
bitmap/bitmap.cpp Normal file
View File

@ -0,0 +1,778 @@
//======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//=============================================================================//
#include "bitmap/bitmap.h"
#include "dbg.h"
#include "utlbuffer.h"
#include "bitmap/psd.h"
#include "bitmap/tgaloader.h"
// Should be last include
#include "tier0/memdbgon.h"
bool Bitmap_t::IsValid() const
{
if ( m_nWidth <= 0 || m_nHeight <= 0 || m_pBits == NULL )
{
Assert( m_nWidth == 0 );
Assert( m_nHeight == 0 );
Assert( m_pBits == NULL );
return false;
}
return true;
}
void Bitmap_t::Clear()
{
if ( m_pBits && m_bOwnsBuffer )
{
free( m_pBits );
}
Reset();
}
void Bitmap_t::Init( int xs, int ys, ImageFormat imageFormat, int nStride )
{
// Check for bogus allocation sizes
if (xs <= 0 || ys <= 0 )
{
Assert( xs == 0 );
Assert( ys == 0 );
Clear();
return;
}
int nPixSize = ImageLoader::SizeInBytes( imageFormat );
// Auto detect stride
if ( nStride == 0 )
{
nStride = nPixSize * xs;
}
// Check for NOP
if (
m_pBits
&& m_bOwnsBuffer
&& m_nWidth == xs
&& m_nHeight == ys
&& nStride == m_nStride
&& nPixSize == m_nPixelSize )
{
// We're already got a buffer of the right size.
// The only thing that might be wrong is the pixel format.
m_ImageFormat = imageFormat;
return;
}
// Free up anything already allocated
Clear();
// Remember dimensions and pixel format
m_nWidth = xs;
m_nHeight = ys;
m_ImageFormat = imageFormat;
m_nPixelSize = nPixSize;
m_nStride = nStride;
// Allocate buffer. Because this is a PC game,
// failure is impossible....right?
m_pBits = (byte *)malloc( ys * m_nStride );
// Assume ownership
m_bOwnsBuffer = true;
}
void Bitmap_t::SetBuffer( int nWidth, int nHeight, ImageFormat imageFormat, unsigned char *pBits, bool bAssumeOwnership, int nStride )
{
Assert( pBits );
Assert( nWidth > 0 );
Assert( nHeight > 0 );
// Free up anything already allocated
Clear();
// Remember dimensions and pixel format
m_nWidth = nWidth;
m_nHeight = nHeight;
m_ImageFormat = imageFormat;
m_nPixelSize = ImageLoader::SizeInBytes( imageFormat );
if ( nStride == 0 )
{
m_nStride = m_nPixelSize * nWidth;
}
else
{
m_nStride = nStride;
}
// Set our buffer pointer
m_pBits = pBits;
// Assume ownership of the buffer, if requested
m_bOwnsBuffer = bAssumeOwnership;
// We should be good to go
Assert( IsValid() );
}
Color Bitmap_t::GetColor( int x, int y ) const
{
Assert( x >= 0 && x < m_nWidth );
Assert( y >= 0 && y < m_nHeight );
Assert( m_pBits );
// Get pointer to pixel data
byte *ptr = m_pBits + (y*m_nStride) + x* m_nPixelSize;
// Check supported image formats
switch ( m_ImageFormat )
{
case IMAGE_FORMAT_RGBA8888:
return Color( ptr[0], ptr[1], ptr[2], ptr[3] );
case IMAGE_FORMAT_ABGR8888:
return Color( ptr[3], ptr[2], ptr[1], ptr[0] );
default:
Assert( !"Unsupport image format!");
return Color( 255,0,255,255 );
}
}
void Bitmap_t::SetColor( int x, int y, Color c )
{
Assert( x >= 0 && x < m_nWidth );
Assert( y >= 0 && y < m_nHeight );
Assert( m_pBits );
// Get pointer to pixel data
byte *ptr = m_pBits + (y*m_nStride) + x* m_nPixelSize;
// Check supported image formats
switch ( m_ImageFormat )
{
case IMAGE_FORMAT_RGBA8888:
ptr[0] = c.r();
ptr[1] = c.g();
ptr[2] = c.b();
ptr[3] = c.a();
break;
case IMAGE_FORMAT_ABGR8888:
ptr[0] = c.a();
ptr[1] = c.b();
ptr[2] = c.g();
ptr[3] = c.r();
break;
default:
Assert( !"Unsupport image format!");
break;
}
}
//bool LoadVTF( const char *pszFilename )
//{
//
// // Load the raw file data
// CUtlBuffer fileData;
// if ( !filesystem->ReadFile( pszFilename, "game", fileData ) )
// {
// Warning( "Failed to load %s\n", pszFilename);
// return false;
// }
//
// return LoadVTFFromBuffer( fileData, pszFilename );
//}
//
//bool LoadVTFFromBuffer( CUtlBuffer fileData, const char *pszDebugName = "buffer" )
//{
//
// // Parse it into VTF object
// IVTFTexture *pVTFTexture( CreateVTFTexture() );
// if ( !pVTFTexture->Unserialize( fileData ) )
// {
// DestroyVTFTexture( pVTFTexture );
// Warning( "Failed to deserialize VTF %s\n", pszDebugName);
// return false;
// }
//
// // We are re-reading our own files, so they should be 8888's
// if ( pVTFTexture->Format() != IMAGE_FORMAT_RGBA8888 )
// {
// DestroyVTFTexture( pVTFTexture );
// Warning( "%s isn't RGBA8888\n", pszDebugName);
// return false;
// }
//
// // Copy the image data
// Allocate( pVTFTexture->Width(), pVTFTexture->Height() );
// for ( int y = 0 ; y < m_nHeight ; ++y )
// {
// memcpy( PixPtr(0, y), pVTFTexture->ImageData(0, 0, 0, 0, y), m_nWidth*4 );
// }
//
// // Clean up
// DestroyVTFTexture( pVTFTexture );
// return true;
//}
//
//bool SaveVTF( CUtlBuffer &outBuffer )
//{
// // Create the VTF to write into
// IVTFTexture *pVTFTexture( CreateVTFTexture() );
// const int nFlags = TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_SRGB;
// if ( !pVTFTexture->Init( m_nWidth, m_nHeight, 1, IMAGE_FORMAT_RGBA8888, nFlags, 1, 1 ) )
// {
// DestroyVTFTexture( pVTFTexture );
// return false;
// }
//
// // write the rgba image to the vtf texture using the pixel writer
// CPixelWriter pixelWriter;
// pixelWriter.SetPixelMemory( pVTFTexture->Format(), pVTFTexture->ImageData(), pVTFTexture->RowSizeInBytes( 0 ) );
//
// for (int y = 0; y < m_nHeight; ++y)
// {
// pixelWriter.Seek( 0, y );
// for (int x = 0; x < m_nWidth; ++x)
// {
// Color c = GetPix( x, y );
// pixelWriter.WritePixel( c.r(), c.g(), c.b(), c.a() );
// }
// }
//
// // Serialize to the buffer
// if ( !pVTFTexture->Serialize( outBuffer ) )
// {
// DestroyVTFTexture( pVTFTexture );
// return false;
// }
// DestroyVTFTexture( pVTFTexture );
// return true;
//}
//void Resize( int nNewSizeX, int nNewSizeY, const Image *pImgSrc = NULL )
//{
// if ( pImgSrc == NULL )
// {
// pImgSrc = this;
// }
//
// if ( nNewSizeX == m_nWidth && nNewSizeY == m_nHeight && pImgSrc == this )
// {
// return;
// }
//
// byte *pNewData = (byte *)malloc( nNewSizeX * nNewSizeY * 4 );
// ImgUtl_StretchRGBAImage( pImgSrc->m_pBits, pImgSrc->m_nWidth, pImgSrc->m_nHeight, pNewData, nNewSizeX, nNewSizeY );
// Clear();
// m_pBits = pNewData;
// m_nWidth = nNewSizeX;
// m_nHeight = nNewSizeY;
//}
//
//void Crop( int x0, int y0, int nNewSizeX, int nNewSizeY, const Image *pImgSrc )
//{
// if ( pImgSrc == NULL )
// {
// pImgSrc = this;
// }
//
// if ( nNewSizeX == m_nWidth && nNewSizeY == m_nHeight && pImgSrc == this )
// {
// return;
// }
//
//
// Assert( x0 >= 0 );
// Assert( y0 >= 0 );
// Assert( x0 + nNewSizeX <= pImgSrc->m_nWidth );
// Assert( y0 + nNewSizeY <= pImgSrc->m_nHeight );
//
// // Allocate new buffer
// int nRowSize = nNewSizeX * 4;
// byte *pNewData = (byte *)malloc( nNewSizeY * nRowSize );
//
// // Copy data, one row at a time
// for ( int y = 0 ; y < nNewSizeY ; ++y )
// {
// memcpy( pNewData + y*nRowSize, pImgSrc->PixPtr(x0, y0+y), nRowSize );
// }
//
// // Replace current buffer with the new one
// Clear();
// m_pBits = pNewData;
// m_nWidth = nNewSizeX;
// m_nHeight = nNewSizeY;
//}
void Bitmap_t::MakeLogicalCopyOf( Bitmap_t &src, bool bTransferBufferOwnership )
{
// What does it mean to make a logical copy of an
// invalid bitmap? I'll tell you what it means: you have a bug.
Assert( src.IsValid() );
// Free up anything we already own
Clear();
// Copy all of the member variables so we are
// a logical copy of the source bitmap
m_nWidth = src.m_nWidth;
m_nHeight = src.m_nHeight;
m_nPixelSize = src.m_nPixelSize;
m_nStride = src.m_nStride;
m_ImageFormat = src.m_ImageFormat;
m_pBits = src.m_pBits;
Assert( !m_bOwnsBuffer );
// Check for assuming ownership of the buffer
if ( bTransferBufferOwnership )
{
if ( src.m_bOwnsBuffer )
{
m_bOwnsBuffer = true;
src.m_bOwnsBuffer = false;
}
else
{
// They don't own the buffer? Then who does?
// Maybe nobody, and it would safe to assume
// ownership. But more than likely, this is a
// bug.
Assert( src.m_bOwnsBuffer );
// And a leak is better than a double-free.
// Don't assume ownership of the buffer.
}
}
}
void Bitmap_t::Crop( int x0, int y0, int nWidth, int nHeight, const Bitmap_t *pImgSource )
{
// Check for cropping in place, then save off our data to a temp
Bitmap_t temp;
if ( pImgSource == this || !pImgSource )
{
temp.MakeLogicalCopyOf( *this, m_bOwnsBuffer );
pImgSource = &temp;
}
// No source image?
if ( !pImgSource->IsValid() )
{
Assert( pImgSource->IsValid() );
return;
}
// Sanity check crop rectangle
Assert( x0 >= 0 );
Assert( y0 >= 0 );
Assert( x0 + nWidth <= pImgSource->Width() );
Assert( y0 + nHeight <= pImgSource->Height() );
// Allocate buffer
Init( nWidth, nHeight, pImgSource->Format() );
// Something wrong?
if ( !IsValid() )
{
Assert( IsValid() );
return;
}
// Copy the data a row at a time
int nRowSize = m_nWidth * m_nPixelSize;
for ( int y = 0 ; y < m_nHeight ; ++y )
{
memcpy( GetPixel(y,0), pImgSource->GetPixel( x0, y + y0 ), nRowSize );
}
}
void Bitmap_t::SetPixelData( const Bitmap_t &src, int nSrcX1, int nSrcY1, int nCopySizeX, int nCopySizeY, int nDestX1, int nDestY1 )
{
// Safety
if ( !src.IsValid() )
{
Assert( src.IsValid() );
return;
}
if ( !IsValid() )
{
Assert( IsValid() );
return;
}
// You need to specify a valid source rectangle, we cannot clip that for you
if ( nSrcX1 < 0 || nSrcY1 < 0 || nSrcX1 + nCopySizeX > src.Width() || nSrcY1 + nCopySizeY > src.Height() )
{
Assert( nSrcX1 >= 0 );
Assert( nSrcY1 >= 0 );
Assert( nSrcX1 + nCopySizeX <= src.Width() );
Assert( nSrcY1 + nCopySizeY <= src.Height() );
return;
}
// But we can clip the rectangle if it extends outside the destination image in a perfectly
// reasonable way
if ( nDestX1 < 0 )
{
nCopySizeX += nDestX1;
nDestX1 = 0;
}
if ( nDestX1 + nCopySizeX > Width() )
{
nCopySizeX = Width() - nDestX1;
}
if ( nDestY1 < 0 )
{
nCopySizeY += nDestY1;
nDestY1 = 0;
}
if ( nDestY1 + nCopySizeY > Height() )
{
nCopySizeY = Height() - nDestY1;
}
if ( nCopySizeX <= 0 || nCopySizeY <= 0 )
{
return;
}
// Copy the pixel data
for ( int y = 0 ; y < nCopySizeY ; ++y )
{
// Wow, this could be a lot faster in the common case
// that the pixe formats are the same. But...this code
// is simple and works, and is NOT the root of all evil.
for ( int x = 0 ; x < nCopySizeX ; ++x )
{
Color c = src.GetColor( nSrcX1 + x, nSrcY1 + y );
SetColor( nDestX1 + x, nDestY1 + y, c );
}
}
}
void Bitmap_t::SetPixelData( const Bitmap_t &src, int nDestX1, int nDestY1 )
{
SetPixelData( src, 0, 0, src.Width(), src.Height(), nDestX1, nDestY1 );
}
//-----------------------------------------------------------------------------
// Returns true if it's a PFM file
//-----------------------------------------------------------------------------
bool IsPFMFile( CUtlBuffer &buf )
{
int nGet = buf.TellGet();
char c0 = buf.GetChar();
char c1 = buf.GetChar();
char c2 = buf.GetChar();
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
return ( c0 == 'P' && ( c1 == 'F' || c1 == 'f' ) && c2 == 0xA );
}
//-----------------------------------------------------------------------------
// This reads an integer from a binary CUtlBuffer.
//-----------------------------------------------------------------------------
static int ReadIntFromUtlBuffer( CUtlBuffer &buf )
{
int val = 0;
int c;
while( buf.IsValid() )
{
c = buf.GetChar();
if( c >= '0' && c <= '9' )
{
val = val * 10 + ( c - '0' );
}
else
{
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, -1 );
break;
}
}
return val;
}
static inline bool IsWhitespace( char c )
{
return c == ' ' || c == '\t' || c == 10;
}
static void EatWhiteSpace( CUtlBuffer &buf )
{
while( buf.IsValid() )
{
int c = buf.GetChar();
if( !IsWhitespace( c ) )
{
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, -1 );
return;
}
}
return;
}
//-----------------------------------------------------------------------------
// Reads PFM info + advances to the texture bits
//-----------------------------------------------------------------------------
bool PFMGetInfo_AndAdvanceToTextureBits( CUtlBuffer &pfmBuffer, int &nWidth, int &nHeight, ImageFormat &imageFormat )
{
pfmBuffer.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
if( pfmBuffer.GetChar() != 'P' )
{
Assert( 0 );
return false;
}
char c = pfmBuffer.GetChar();
if ( c == 'F' )
{
imageFormat = IMAGE_FORMAT_RGB323232F;
}
else if ( c == 'f' )
{
imageFormat = IMAGE_FORMAT_R32F;
}
else
{
Assert( 0 );
return false;
}
if( pfmBuffer.GetChar() != 0xa )
{
Assert( 0 );
return false;
}
nWidth = ReadIntFromUtlBuffer( pfmBuffer );
EatWhiteSpace( pfmBuffer );
nHeight = ReadIntFromUtlBuffer( pfmBuffer );
// eat crap until the next newline
while( pfmBuffer.IsValid() && pfmBuffer.GetChar() != 0xa )
{
}
int nScale = ReadIntFromUtlBuffer( pfmBuffer );
// eat crap until the next newline
while( pfmBuffer.IsValid() && pfmBuffer.GetChar() != 0xa )
{
}
if ( nScale > 0 )
{
pfmBuffer.SetBigEndian( true );
}
// Here, the buffer should be at the start of the texture data
return true;
}
//-----------------------------------------------------------------------------
// Loads a PFM file into a Bitmap_t as RGBA32323232F data
// PFM source data doesn't have alpha, so we put 1.0f into alpha
//-----------------------------------------------------------------------------
bool PFMReadFileRGBA32323232F( CUtlBuffer &fileBuffer, Bitmap_t &bitmap, float pfmScale )
{
int nWidth = 0, nHeight = 0;
ImageFormat imageFormat = IMAGE_FORMAT_UNKNOWN;
PFMGetInfo_AndAdvanceToTextureBits( fileBuffer, nWidth, nHeight, imageFormat ); // Read the header (advances us to the texture bits)
Assert( imageFormat == IMAGE_FORMAT_RGB323232F );
bitmap.Init( nWidth, nHeight, IMAGE_FORMAT_RGBA32323232F ); // Init the bitmap
// NOTE: PFMs are displayed *UPSIDE-DOWN* in Photoshop! (as of CS2... HDRShop gets it right)
// Reading rows in reverse order here is the correct thing to do:
for( int y = ( nHeight - 1 ); y >= 0; y-- )
{
Assert( fileBuffer.IsValid() );
if ( !fileBuffer.IsValid() )
return false;
float *pOut = ( (float *)bitmap.GetBits() ) + y*nWidth*4; // Point to output row
for ( int x = 0; x < nWidth; x++ ) // For every RGB input color
{
fileBuffer.Get( pOut, sizeof( float ) ); // Get red
*pOut *= pfmScale; // Scale into output
pOut++;
fileBuffer.Get( pOut, sizeof( float ) ); // Get green
*pOut *= pfmScale; // Scale into output
pOut++;
fileBuffer.Get( pOut, sizeof( float ) ); // Get blue
*pOut *= pfmScale; // Scale into output
pOut++;
*pOut = 1.0f; // 1.0f into alpha
pOut++;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Loads a PFM file into a Bitmap_t as RGB323232F data
//-----------------------------------------------------------------------------
bool PFMReadFileRGB323232F( CUtlBuffer &fileBuffer, Bitmap_t &bitmap, float pfmScale )
{
// Read the header (advances us to the texture bits)
int nWidth = 0, nHeight = 0;
ImageFormat imageFormat = IMAGE_FORMAT_UNKNOWN;
PFMGetInfo_AndAdvanceToTextureBits( fileBuffer, nWidth, nHeight, imageFormat );
Assert( imageFormat == IMAGE_FORMAT_RGB323232F );
// Init the bitmap
bitmap.Init( nWidth, nHeight, IMAGE_FORMAT_RGB323232F );
// Read the texels
for( int y = ( nHeight - 1 ); y >= 0; y-- )
{
Assert( fileBuffer.IsValid() );
if ( !fileBuffer.IsValid() )
return false;
// NOTE: PFMs are displayed *UPSIDE-DOWN* in Photoshop! (as of CS2... HDRShop gets it right)
// Reading rows in reverse order here is the correct thing to do:
float *pRow = ( (float *)bitmap.GetBits() ) + y*nWidth*3;
fileBuffer.Get( pRow, nWidth*3*sizeof( float ) );
for ( int x = 0; x < nWidth*3; x++ )
{
pRow[ x ] *= pfmScale;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Loads the x channel of a PFM file into a Bitmap_t as R32F data
//-----------------------------------------------------------------------------
bool PFMReadFileR32F( CUtlBuffer &fileBuffer, Bitmap_t &bitmap, float pfmScale )
{
// Read the header (advances us to the texture bits)
int nWidth, nHeight;
ImageFormat fileImageFormat; // Format of data in file
PFMGetInfo_AndAdvanceToTextureBits( fileBuffer, nWidth, nHeight, fileImageFormat );
Assert( fileImageFormat == IMAGE_FORMAT_RGB323232F );
// Init the bitmap
bitmap.Init( nWidth, nHeight, IMAGE_FORMAT_R32F );
float flMin = FLOAT32_MAX;
float flMax = FLOAT32_MIN;
// Read the texels, snarfing out just the x component
for( int y = ( nHeight - 1 ); y >= 0; y-- )
{
Assert( fileBuffer.IsValid() );
if ( !fileBuffer.IsValid() )
return false;
// NOTE: PFMs are displayed *UPSIDE-DOWN* in Photoshop! (as of CS2... HDRShop gets it right)
// Reading rows in reverse order here is the correct thing to do:
float *pRow = ( (float *)bitmap.GetBits() ) + y*nWidth;
for ( int x = 0; x < nWidth; x++ )
{
fileBuffer.Get( pRow+x, sizeof( float ) ); // Grab x component and scale
pRow[x] *= pfmScale;
flMin = MIN( pRow[x], flMin );
flMax = MAX( pRow[x], flMax );
float flDummy[2];
fileBuffer.Get( &flDummy, 2*sizeof( float ) ); // Jump past y and z components in file
}
}
printf( "Displacement Range: (%g, %g)\n", flMin, flMax );
return true;
}
//-----------------------------------------------------------------------------
// Loads a PFM file into a Bitmap_t
//-----------------------------------------------------------------------------
bool PFMReadFile( CUtlBuffer &buf, Bitmap_t *pBitmap )
{
// Read the header (advances us to the texture bits)
int nWidth = 0, nHeight = 0;
ImageFormat fmt = IMAGE_FORMAT_UNKNOWN;
PFMGetInfo_AndAdvanceToTextureBits( buf, nWidth, nHeight, fmt );
// Init the bitmap
pBitmap->Init( nWidth, nHeight, fmt );
int nRowBytes = ImageLoader::GetMemRequired( nWidth, 1, 1, 1, fmt );
// Read the texels
for( int y = ( nHeight - 1 ); y >= 0; y-- )
{
Assert( buf.IsValid() );
if ( !buf.IsValid() )
return false;
// NOTE: PFMs are displayed *UPSIDE-DOWN* in Photoshop! (as of CS2... HDRShop gets it right)
// Reading rows in reverse order here is the correct thing to do:
void *pDest = pBitmap->GetBits() + y * nRowBytes;
buf.Get( pDest, nRowBytes );
}
return true;
}
//-----------------------------------------------------------------------------
// Loads a bitmap from an arbitrary file: could be a TGA, PSD, or PFM.
// LoadBitmap autodetects which type
//-----------------------------------------------------------------------------
BitmapFileType_t LoadBitmapFile( CUtlBuffer &buf, Bitmap_t *pBitmap )
{
if ( IsPSDFile( buf ) )
{
// FIXME: Make it actually load the true format
if ( !PSDReadFileRGBA8888( buf, *pBitmap ) )
return BITMAP_FILE_TYPE_UNKNOWN;
return BITMAP_FILE_TYPE_PSD;
}
if ( IsPFMFile( buf ) )
{
if ( !PFMReadFile( buf, pBitmap ) )
return BITMAP_FILE_TYPE_UNKNOWN;
return BITMAP_FILE_TYPE_PFM;
}
// It's not really possible to detect TGAness.. there's no identifier
// Assume TGA file here
int nWidth, nHeight;
ImageFormat fmt;
float flGamma;
int nGet = buf.TellGet();
bool bOk = TGALoader::GetInfo( buf, &nWidth, &nHeight, &fmt, &flGamma );
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
if ( !bOk )
return BITMAP_FILE_TYPE_UNKNOWN;
// FIXME: TGALoader is incredibly inefficient when trying to just get
// the bits as-is as it loads into RGBA8888 and then color converts out
pBitmap->Init( nWidth, nHeight, fmt );
if ( !TGALoader::Load( pBitmap->GetBits(), buf, nWidth, nHeight, fmt, flGamma, false ) )
return BITMAP_FILE_TYPE_UNKNOWN;
return BITMAP_FILE_TYPE_TGA;
}

63
bitmap/bitmap.vpc Normal file
View File

@ -0,0 +1,63 @@
//-----------------------------------------------------------------------------
// BITMAP.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$SRCDIR\dx9sdk\include" [$WINDOWS]
$AdditionalIncludeDirectories "$BASE;$(XEDK)\include\win32" [$WINDOWS && $XDKINSTALLED]
$AdditionalIncludeDirectories "$BASE;$(XEDK)\include\xbox" [$X360]
}
}
$Project "bitmap"
{
$Folder "Source Files"
{
$File "bitmap.cpp"
$File "ImageByteSwap.cpp" [$X360 || $PS3]
$File "colorconversion.cpp"
$File "floatbitmap.cpp"
$File "floatbitmap2.cpp"
$File "floatbitmap3.cpp"
$File "floatbitmap4.cpp" [$WINDOWS]
$File "floatbitmap_bilateralfilter.cpp"
$File "floatcubemap.cpp"
$File "imageformat.cpp"
$File "psd.cpp"
$File "psheet.cpp"
$File "resample.cpp"
$File "tgaloader.cpp"
$File "texturepacker.cpp"
$File "tgawriter.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\bitmap\bitmap.h"
$File "$SRCDIR\public\bitmap\floatbitmap.h"
$File "$SRCDIR\public\bitmap\imageformat.h"
$File "$SRCDIR\public\bitmap\imageformat_declarations.h"
$File "$SRCDIR\public\bitmap\psd.h"
$File "$SRCDIR\public\bitmap\psheet.h"
$File "$SRCDIR\public\bitmap\texturepacker.h"
$File "$SRCDIR\public\bitmap\tgaloader.h"
$File "$SRCDIR\public\bitmap\tgawriter.h"
$File "$SRCDIR\public\bitmap\stb_dxt.h"
}
$Folder "Link Libraries" [$WINDOWS]
{
$Lib "$SRCDIR\lib\public\nvtc" [!$WIN64]
$Lib "$SRCDIR\lib\public\nvtc64" [$WIN64]
$Lib "bitmap_byteswap"
}
}

View File

@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "bitmap.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "bitmap.vcxproj"
"1" "bitmap.vcxproj.filters"
}
}
}

View File

@ -0,0 +1,47 @@
//-----------------------------------------------------------------------------
// BITMAP_BYTESWAP.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR ".."
$Macro OUTLIBDIR "$LIBPUBLIC"
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$(XEDK)\include\win32" [$WINDOWS]
}
}
$Configuration "Debug"
{
$General
{
$IntermediateDirectory ".\Debug_BitmapByteswap$PLATSUBDIR" [$WINDOWS]
}
}
$Configuration "Release"
{
$General
{
$IntermediateDirectory ".\Debug_BitmapByteswap$PLATSUBDIR" [$WINDOWS]
}
}
$Project "bitmap_byteswap"
{
$Folder "Source Files"
{
$File "ImageByteSwap.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\bitmap\imageformat.h"
}
}

View File

@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "bitmap_byteswap.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "bitmap_byteswap.vcxproj"
"1" "bitmap_byteswap.vcxproj.filters"
}
}
}

2495
bitmap/colorconversion.cpp Normal file

File diff suppressed because it is too large Load Diff

1618
bitmap/floatbitmap.cpp Normal file

File diff suppressed because it is too large Load Diff

151
bitmap/floatbitmap2.cpp Normal file
View File

@ -0,0 +1,151 @@
//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include <tier0/platform.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "bitmap/floatbitmap.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
static float ScaleValue( float f, float overbright )
{
// map a value between 0..255 to the scale factor
int ival = ( int )f;
return ival * ( overbright / 255.0 );
}
static float IScaleValue( float f, float overbright )
{
f *= ( 1.0 / overbright );
int ival = ( int )MIN( 255, ceil( f * 255.0 ));
return ival;
}
void MaybeSetScaleVaue( FloatBitMap_t const & orig, FloatBitMap_t & newbm, int x, int y,
float newscale, float overbright )
{
// clamp the given scale value to the legal range for that pixel and regnerate the rgb
// components.
float maxc = MAX( MAX( orig.Pixel( x, y, 0, 0 ), orig.Pixel( x, y, 0, 1 )), orig.Pixel( x, y, 0, 2 ));
if ( maxc == 0.0 )
{
// pixel is black. any scale value is fine.
newbm.Pixel( x, y, 0, 3 ) = newscale;
for( int c = 0;c < 3;c++ )
newbm.Pixel( x, y, 0, c ) = 0;
}
else
{
// float desired_floatscale=maxc;
float scale_we_will_get = ScaleValue( newscale, overbright );
// if (scale_we_will_get >= desired_floatscale )
{
newbm.Pixel( x, y, 0, 3 ) = newscale;
for( int c = 0;c < 3;c++ )
newbm.Pixel( x, y, 0, c ) = orig.Pixel( x, y, 0, c ) / ( scale_we_will_get );
}
}
}
void FloatBitMap_t::Uncompress( float overbright )
{
for( int y = 0;y < NumRows();y++ )
for( int x = 0;x < NumCols();x++ )
{
int iactual_alpha_value = ( int )( 255.0 * Pixel( x, y, 0, 3 ) );
float actual_alpha_value = iactual_alpha_value * ( 1.0 / 255.0 );
for( int c = 0;c < 3;c++ )
{
int iactual_color_value = ( int )( 255.0 * Pixel( x, y, 0, c ) );
float actual_color_value = iactual_color_value * ( 1.0 / 255.0 );
Pixel( x, y, 0, c ) = actual_alpha_value * actual_color_value * overbright;
}
}
}
#define GAUSSIAN_WIDTH 5
#define SQ(x) ((x)*(x))
void FloatBitMap_t::CompressTo8Bits( float overbright )
{
FloatBitMap_t TmpFBM( NumCols(), NumRows() );
// first, saturate to max overbright
for( int y = 0;y < NumRows();y++ )
for( int x = 0;x < NumCols();x++ )
for( int c = 0;c < 3;c++ )
Pixel( x, y, 0, c ) = MIN( overbright, Pixel( x, y, 0, c ));
// first pass - choose nominal scale values to convert to rgb,scale
for( int y = 0;y < NumRows();y++ )
for( int x = 0;x < NumCols();x++ )
{
// determine maximum component
float maxc = MAX( MAX( Pixel( x, y, 0, 0 ), Pixel( x, y, 0, 1 )), Pixel( x, y, 0, 2 ));
if ( maxc == 0 )
{
for( int c = 0;c < 4;c++ )
TmpFBM.Pixel( x, y, 0, c ) = 0;
}
else
{
float desired_floatscale = maxc;
float closest_iscale = IScaleValue( desired_floatscale, overbright );
float scale_value_we_got = ScaleValue( closest_iscale, overbright );
TmpFBM.Pixel( x, y, 0, 3 ) = closest_iscale;
for( int c = 0;c < 3;c++ )
TmpFBM.Pixel( x, y, 0, c ) = Pixel( x, y, 0, c ) / scale_value_we_got;
}
}
// now, refine scale values
#ifdef FILTER_TO_REDUCE_LERP_ARTIFACTS
// I haven't been able to come up with a filter which eleiminates objectionable artifacts on all
// source textures. So, I've gone to doing the lerping in the shader.
int pass = 0;
while( pass < 1 )
{
FloatBitMap_t temp_filtered( & TmpFBM );
for( int y = 0;y < NumRows();y++ )
{
for( int x = 0;x < NumCols();x++ )
{
float sum_scales = 0.0;
float sum_weights = 0.0;
for( int yofs =- GAUSSIAN_WIDTH;yofs <= GAUSSIAN_WIDTH;yofs++ )
for( int xofs =- GAUSSIAN_WIDTH;xofs <= GAUSSIAN_WIDTH;xofs++ )
{
float r = 0.456 * GAUSSIAN_WIDTH;
r = 0.26 * GAUSSIAN_WIDTH;
float x1 = xofs / r;
float y1 = yofs / r;
float a = ( SQ( x1 ) + SQ( y1 )) / ( 2.0 * SQ( r ));
float w = exp( - a );
sum_scales += w * TmpFBM.PixelClamped( x + xofs, y + yofs, 3 );
sum_weights += w;
}
int new_trial_scale = sum_scales * ( 1.0 / sum_weights );
MaybeSetScaleVaue( * this, temp_filtered, x, y, new_trial_scale, overbright );
}
}
pass++;
memcpy( TmpFBM.RGBAData, temp_filtered.RGBAData, NumCols() * NumRows() * 4 * sizeof( float ));
}
#endif
CopyAttrFrom( TmpFBM, FBM_ATTR_RED );
CopyAttrFrom( TmpFBM, FBM_ATTR_GREEN );
CopyAttrFrom( TmpFBM, FBM_ATTR_BLUE );
CopyAttrFrom( TmpFBM, FBM_ATTR_ALPHA );
// now, map scale to real value
for( int y = 0; y < NumRows(); y++ )
for( int x = 0; x < NumCols(); x++ )
Pixel( x, y, 0, 3 ) *= ( 1.0 / 255.0 );
}

118
bitmap/floatbitmap3.cpp Normal file
View File

@ -0,0 +1,118 @@
//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include <tier0/platform.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "bitmap/floatbitmap.h"
#include "vstdlib/vstdlib.h"
#include "vstdlib/random.h"
#include "tier1/strtools.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
void FloatBitMap_t::InitializeWithRandomPixelsFromAnotherFloatBM( FloatBitMap_t const & other )
{
for( int z = 0; z < NumSlices(); z++ )
{
for( int y = 0;y < NumRows();y++ )
{
for( int x = 0;x < NumCols();x++ )
{
int x1 = RandomInt( 0, other.NumCols() - 1 );
int y1 = RandomInt( 0, other.NumRows() - 1 );
int z1 = RandomInt( 0, other.NumSlices() - 1 );
for( int c = 0; c < 4; c++ )
{
Pixel( x, y, z, c ) = other.Pixel( x1, y1, z1, c );
}
}
}
}
}
void FloatBitMap_t::QuarterSizeWithGaussian( FloatBitMap_t *pBitmap )
{
// generate a new bitmap half on each axis, using a separable gaussian.
static float kernel[]={.05, .25, .4, .25, .05};
pBitmap->Init( NumCols() / 2, NumRows() / 2 );
for( int y = 0;y < NumRows() / 2;y++ )
for( int x = 0;x < NumCols() / 2;x++ )
{
for( int c = 0;c < 4;c++ )
{
float sum = 0;
float sumweights = 0; // for versatility in handling the
// offscreen case
for( int xofs =- 2;xofs <= 2;xofs++ )
{
int orig_x = MAX( 0, MIN( NumCols() - 1, x * 2 + xofs ));
for( int yofs =- 2;yofs <= 2;yofs++ )
{
int orig_y = MAX( 0, MIN( NumRows() - 1, y * 2 + yofs ));
float coeff = kernel[xofs + 2]* kernel[yofs + 2];
sum += Pixel( orig_x, orig_y, 0, c ) * coeff;
sumweights += coeff;
}
}
pBitmap->Pixel( x, y, 0, c ) = sum / sumweights;
}
}
}
FloatImagePyramid_t::FloatImagePyramid_t( FloatBitMap_t const & src, ImagePyramidMode_t mode )
{
memset( m_pLevels, 0, sizeof( m_pLevels ));
m_nLevels = 1;
m_pLevels[0]= new FloatBitMap_t( & src );
ReconstructLowerResolutionLevels( 0 );
}
void FloatImagePyramid_t::ReconstructLowerResolutionLevels( int start_level )
{
while( ( m_pLevels[start_level]-> NumCols() > 1 ) && ( m_pLevels[start_level]-> NumRows() > 1 ) )
{
if ( m_pLevels[start_level + 1] )
delete m_pLevels[start_level + 1];
m_pLevels[start_level + 1] = new FloatBitMap_t;
m_pLevels[start_level]->QuarterSizeWithGaussian( m_pLevels[start_level + 1] );
start_level++;
}
m_nLevels = start_level + 1;
}
float & FloatImagePyramid_t::Pixel( int x, int y, int component, int level ) const
{
Assert( level < m_nLevels );
x <<= level;
y <<= level;
return m_pLevels[level]-> Pixel( x, y, 0, component );
}
void FloatImagePyramid_t::WriteTGAs( char const * basename ) const
{
for( int l = 0;l < m_nLevels;l++ )
{
char bname_out[1024];
Q_snprintf(bname_out,sizeof(bname_out),"%s_%02d.tga",basename,l);
m_pLevels[l]-> WriteTGAFile( bname_out );
}
}
FloatImagePyramid_t::~FloatImagePyramid_t( void )
{
for( int l = 0;l < m_nLevels;l++ )
if ( m_pLevels[l] )
delete m_pLevels[l];
}

354
bitmap/floatbitmap4.cpp Normal file
View File

@ -0,0 +1,354 @@
//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include <tier0/platform.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "bitmap/floatbitmap.h"
#include "vstdlib/vstdlib.h"
#include "raytrace.h"
#include "mathlib/bumpvects.h"
#include "mathlib/halton.h"
#include "tier0/threadtools.h"
#include "tier0/progressbar.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
// In order to handle intersections with wrapped copies, we repeat the bitmap triangles this many
// times
#define NREPS_TILE 1
extern int n_intersection_calculations;
struct SSBumpCalculationContext // what each thread needs to see
{
RayTracingEnvironment * m_pRtEnv;
FloatBitMap_t * ret_bm; // the bitmnap we are building
FloatBitMap_t const * src_bm;
int nrays_to_trace_per_pixel;
float bump_scale;
Vector *trace_directions; // light source directions to trace
Vector *normals;
int min_y; // range of scanlines to computer for
int max_y;
uint32 m_nOptionFlags;
int thread_number;
};
static uintp SSBumpCalculationThreadFN( void * ctx1 )
{
SSBumpCalculationContext * ctx = ( SSBumpCalculationContext * ) ctx1;
RayStream ray_trace_stream_ctx;
RayTracingSingleResult * rslts = new
RayTracingSingleResult[ctx->ret_bm->NumCols() * ctx->nrays_to_trace_per_pixel];
for( int y = ctx->min_y; y <= ctx->max_y; y++ )
{
if ( ctx->thread_number == 0 )
ReportProgress("Computing output",(1+ctx->max_y-ctx->min_y),y-ctx->min_y);
for( int r = 0; r < ctx->nrays_to_trace_per_pixel; r++ )
{
for( int x = 0; x < ctx->ret_bm->NumCols(); x++ )
{
Vector surf_pnt( x, y, ctx->bump_scale * ctx->src_bm->Pixel( x, y, 0, 3 ) );
// move the ray origin up a hair
surf_pnt.z += 0.55;
Vector trace_end = surf_pnt;
Vector trace_dir = ctx->trace_directions[ r ];
trace_dir *= ( 1 + NREPS_TILE * 2 ) * MAX( ctx->src_bm->NumCols(), ctx->src_bm->NumRows() );
trace_end += trace_dir;
ctx->m_pRtEnv->AddToRayStream( ray_trace_stream_ctx, surf_pnt, trace_end,
& ( rslts[ r + ctx->nrays_to_trace_per_pixel * ( x )] ) );
}
}
if ( ctx->nrays_to_trace_per_pixel )
ctx->m_pRtEnv->FinishRayStream( ray_trace_stream_ctx );
// now, all ray tracing results are in the results buffer. Determine the visible self-shadowed
// bump map lighting at each vertex in each basis direction
for( int x = 0; x < ctx->src_bm->NumCols(); x++ )
{
int nNumChannels = ( ctx->m_nOptionFlags & SSBUMP_OPTION_NONDIRECTIONAL ) ? 1 : 3;
for( int c = 0; c < nNumChannels; c++ )
{
float sum_dots = 0;
float sum_possible_dots = 0;
Vector ldir = g_localBumpBasis[c];
float ndotl = DotProduct( ldir, ctx->normals[x + y * ctx->src_bm->NumCols()] );
if ( ndotl < 0 )
ctx->ret_bm->Pixel( x, y, 0, c ) = 0;
else
{
if ( ctx->nrays_to_trace_per_pixel )
{
RayTracingSingleResult * this_rslt =
rslts + ctx->nrays_to_trace_per_pixel * ( x );
for( int r = 0; r < ctx->nrays_to_trace_per_pixel; r++ )
{
float dot;
if ( ctx->m_nOptionFlags & SSBUMP_OPTION_NONDIRECTIONAL )
dot = ctx->trace_directions[r].z;
else
dot = DotProduct( ldir, ctx->trace_directions[r] );
if ( dot > 0 )
{
sum_possible_dots += dot;
if ( this_rslt[r].HitID == - 1 )
sum_dots += dot;
}
}
}
else
{
sum_dots = sum_possible_dots = 1.0;
}
ctx->ret_bm->Pixel( x, y, 0, c ) = ( ndotl * sum_dots ) / sum_possible_dots;
}
}
if ( ctx->m_nOptionFlags & SSBUMP_OPTION_NONDIRECTIONAL )
{
ctx->ret_bm->Pixel( x, y, 0, 1 ) = ctx->ret_bm->Pixel( x, y, 0, 0 ); // copy height
ctx->ret_bm->Pixel( x, y, 0, 2 ) = ctx->ret_bm->Pixel( x, y, 0, 0 ); // copy height
ctx->ret_bm->Pixel( x, y, 0, 3 ) = ctx->ret_bm->Pixel( x, y, 0, 0 ); // copy height
}
else
{
ctx->ret_bm->Pixel( x, y, 0, 3 ) = ctx->src_bm->Pixel( x, y, 0, 3 ); // copy height
}
}
}
delete[] rslts;
return 0;
}
void FloatBitMap_t::ComputeVertexPositionsAndNormals( float flHeightScale, Vector ** ppPosOut, Vector ** ppNormalOut ) const
{
Vector * verts = new Vector[NumCols() * NumRows()];
// first, calculate vertex positions
for( int y = 0; y < NumRows(); y++ )
for( int x = 0; x < NumCols(); x++ )
{
Vector * out = verts + x + y * NumCols();
out->x = x;
out->y = y;
out->z = flHeightScale * Pixel( x, y, 0, 3 );
}
Vector * normals = new Vector[NumCols() * NumRows()];
// now, calculate normals, smoothed
for( int y = 0; y < NumRows(); y++ )
for( int x = 0; x < NumCols(); x++ )
{
// now, calculcate average normal
Vector avg_normal( 0, 0, 0 );
for( int xofs =- 1;xofs <= 1;xofs++ )
for( int yofs =- 1;yofs <= 1;yofs++ )
{
int x0 = ( x + xofs );
if ( x0 < 0 )
x0 += NumCols();
int y0 = ( y + yofs );
if ( y0 < 0 )
y0 += NumRows();
x0 = x0 % NumCols();
y0 = y0 % NumRows();
int x1 = ( x0 + 1 ) % NumCols();
int y1 = ( y0 + 1 ) % NumRows();
// now, form the two triangles from this vertex
Vector p0 = verts[x0 + y0 * NumCols()];
Vector e1 = verts[x1 + y0 * NumCols()];
e1 -= p0;
Vector e2 = verts[x0 + y1 * NumCols()];
e2 -= p0;
Vector n1;
CrossProduct( e1, e2, n1 );
if ( n1.z < 0 )
n1.Negate();
e1 = verts[x + y1 * NumCols()];
e1 -= p0;
e2 = verts[x1 + y1 * NumCols()];
e2 -= p0;
Vector n2;
CrossProduct( e1, e2, n2 );
if ( n2.z < 0 )
n2.Negate();
n1.NormalizeInPlace();
n2.NormalizeInPlace();
avg_normal += n1;
avg_normal += n2;
}
avg_normal.NormalizeInPlace();
normals[x + y * NumCols()]= avg_normal;
}
* ppPosOut = verts;
* ppNormalOut = normals;
}
FloatBitMap_t * FloatBitMap_t::ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
float bump_scale, int nrays_to_trace_per_pixel,
uint32 nOptionFlags ) const
{
// first, add all the triangles from the height map to the "world".
// we will make multiple copies to handle wrapping
int tcnt = 1;
Vector * verts;
Vector * normals;
ComputeVertexPositionsAndNormals( bump_scale, & verts, & normals );
RayTracingEnvironment rtEnv;
rtEnv.Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS; // save some ram
if ( nrays_to_trace_per_pixel )
{
rtEnv.MakeRoomForTriangles( ( 1 + 2 * NREPS_TILE ) * ( 1 + 2 * NREPS_TILE ) * 2 * NumRows() * NumCols() );
// now, add a whole mess of triangles to trace against
for( int tilex =- NREPS_TILE; tilex <= NREPS_TILE; tilex++ )
for( int tiley =- NREPS_TILE; tiley <= NREPS_TILE; tiley++ )
{
int min_x = 0;
int max_x = NumCols() - 1;
int min_y = 0;
int max_y = NumRows() - 1;
if ( tilex < 0 )
min_x = NumCols() / 2;
if ( tilex > 0 )
max_x = NumCols() / 2;
if ( tiley < 0 )
min_y = NumRows() / 2;
if ( tiley > 0 )
max_y = NumRows() / 2;
for( int y = min_y; y <= max_y; y++ )
for( int x = min_x; x <= max_x; x++ )
{
Vector ofs( tilex * NumCols(), tiley * NumRows(), 0 );
int x1 = ( x + 1 ) % NumCols();
int y1 = ( y + 1 ) % NumRows();
Vector v0 = verts[x + y * NumCols()];
Vector v1 = verts[x1 + y * NumCols()];
Vector v2 = verts[x1 + y1 * NumCols()];
Vector v3 = verts[x + y1 * NumCols()];
v0.x = x; v0.y = y;
v1.x = x + 1; v1.y = y;
v2.x = x + 1; v2.y = y + 1;
v3.x = x; v3.y = y + 1;
v0 += ofs; v1 += ofs; v2 += ofs; v3 += ofs;
rtEnv.AddTriangle( tcnt++, v0, v1, v2, Vector( 1, 1, 1 ) );
rtEnv.AddTriangle( tcnt++, v0, v3, v2, Vector( 1, 1, 1 ) );
}
}
//printf("added %d triangles\n",tcnt-1);
ReportProgress("Creating kd-tree",0,0);
rtEnv.SetupAccelerationStructure();
// ok, now we have built a structure for ray intersection. we will take advantage
// of the SSE ray tracing code by intersecting rays as a batch.
}
// We need to calculate for each vertex (i.e. pixel) of the heightmap, how "much" of the world
// it can see in each basis direction. we will do this by sampling a sphere of rays around the
// vertex, and using dot-product weighting to measure the lighting contribution in each basis
// direction. note that the surface normal is not used here. The surface normal will end up
// being reflected in the result because of rays being blocked when they try to pass through
// the planes of the triangles touching the vertex.
// note that there is no reason inter-bounced lighting could not be folded into this
// calculation.
FloatBitMap_t * ret = new FloatBitMap_t( NumCols(), NumRows() );
Vector * trace_directions = new Vector[nrays_to_trace_per_pixel];
DirectionalSampler_t my_sphere_sampler;
for( int r = 0; r < nrays_to_trace_per_pixel; r++ )
{
Vector trace_dir = my_sphere_sampler.NextValue();
// trace_dir=Vector(1,0,0);
trace_dir.z = fabs( trace_dir.z ); // upwards facing only
trace_directions[ r ]= trace_dir;
}
volatile SSBumpCalculationContext ctxs[32];
ctxs[0].m_pRtEnv =& rtEnv;
ctxs[0].ret_bm = ret;
ctxs[0].src_bm = this;
ctxs[0].nrays_to_trace_per_pixel = nrays_to_trace_per_pixel;
ctxs[0].bump_scale = bump_scale;
ctxs[0].trace_directions = trace_directions;
ctxs[0].normals = normals;
ctxs[0].min_y = 0;
ctxs[0].max_y = NumRows() - 1;
ctxs[0].m_nOptionFlags = nOptionFlags;
int nthreads = MIN( 32, GetCPUInformation().m_nPhysicalProcessors );
ThreadHandle_t waithandles[32];
int starty = 0;
int ystep = NumRows() / nthreads;
for( int t = 0;t < nthreads; t++ )
{
if ( t )
memcpy( ( void * ) ( & ctxs[t] ), ( void * ) & ctxs[0], sizeof( ctxs[0] ) );
ctxs[t].thread_number = t;
ctxs[t].min_y = starty;
if ( t != nthreads - 1 )
ctxs[t].max_y = MIN( NumRows() - 1, starty + ystep - 1 );
else
ctxs[t].max_y = NumRows() - 1;
waithandles[t]= CreateSimpleThread( SSBumpCalculationThreadFN, ( SSBumpCalculationContext * ) & ctxs[t] );
starty += ystep;
}
for( int t = 0;t < nthreads;t++ )
{
ThreadJoin( waithandles[t] );
}
if ( nOptionFlags & SSBUMP_MOD2X_DETAIL_TEXTURE )
{
const float flOutputScale = 0.5 * ( 1.0 / .57735026 ); // normalize so that a flat normal yields 0.5
// scale output weights by color channel
for( int nY = 0; nY < NumRows(); nY++ )
for( int nX = 0; nX < NumCols(); nX++ )
{
float flScale = flOutputScale * ( 2.0 / 3.0 ) * ( Pixel( nX, nY, 0, 0 ) + Pixel( nX, nY, 0, 1 ) + Pixel( nX, nY, 0, 2 ) );
ret->Pixel( nX, nY, 0, 0 ) *= flScale;
ret->Pixel( nX, nY, 0, 1 ) *= flScale;
ret->Pixel( nX, nY, 0, 2 ) *= flScale;
}
}
delete[] verts;
delete[] trace_directions;
delete[] normals;
return ret; // destructor will clean up rtenv
}
// generate a conventional normal map from a source with height stored in alpha.
FloatBitMap_t * FloatBitMap_t::ComputeBumpmapFromHeightInAlphaChannel( float flBumpScale ) const
{
Vector * verts;
Vector * normals;
ComputeVertexPositionsAndNormals( flBumpScale, & verts, & normals );
FloatBitMap_t * ret = new FloatBitMap_t( NumCols(), NumRows() );
for( int y = 0; y < NumRows(); y++ )
for( int x = 0; x < NumCols(); x++ )
{
Vector const & N = normals[ x + y * NumCols() ];
ret->Pixel( x, y, 0, 0 ) = 0.5 + 0.5 * N.x;
ret->Pixel( x, y, 0, 1 ) = 0.5 + 0.5 * N.y;
ret->Pixel( x, y, 0, 2 ) = 0.5 + 0.5 * N.z;
ret->Pixel( x, y, 0, 3 ) = Pixel( x, y, 0, 3 );
}
return ret;
}

View File

@ -0,0 +1,105 @@
//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include <tier0/platform.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "bitmap/floatbitmap.h"
#include <tier2/tier2.h>
#include "tier0/threadtools.h"
#include "tier0/progressbar.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
struct TBFCalculationContext
{
int min_y, max_y; // range to calculate in this thread
int thread_number;
int radius_in_pixels;
float edge_threshold_value;
FloatBitMap_t const * orig_bm;
FloatBitMap_t * dest_bm;
};
static uintp TBFCalculationThreadFN( void *ctx1 )
{
TBFCalculationContext * ctx = ( TBFCalculationContext * ) ctx1;
for( int y = ctx->min_y; y <= ctx->max_y; y++ )
{
if ( ctx->thread_number == 0 )
{
ReportProgress("Performing bilateral filter",(1+ctx->max_y-ctx->min_y), y - ctx->min_y );
}
for( int x = 0; x < ctx->dest_bm->NumCols(); x++ )
{
for( int c = 0;c < 4;c++ )
{
float sum_weights = 0;
float filter_sum = 0;
float centerp = ctx->orig_bm->Pixel( x, y, 0, c );
for( int iy =- ctx->radius_in_pixels; iy <= ctx->radius_in_pixels; iy++ )
{
for( int ix =- ctx->radius_in_pixels; ix <= ctx->radius_in_pixels; ix++ )
{
float this_p = ctx->orig_bm->PixelWrapped( x + ix, y + iy, 0, c );
// caluclate the g() term. We use a gaussian
float exp1 = ( ix * ix + iy * iy ) * ( 1.0 / ( 2.0 * ctx->radius_in_pixels *.033 ));
float g = exp( - exp1 );
// calculate the "similarity" term. We use a triangle filter
float s = 1.0;
float cdiff = fabs( centerp - this_p );
s = ( cdiff > ctx->edge_threshold_value )?0:
FLerp( 1, 0, 0, ctx->edge_threshold_value, cdiff );
sum_weights += s * g;
filter_sum += s * g * this_p;
}
}
ctx->dest_bm->Pixel( x, y, 0, c ) = filter_sum / sum_weights;
}
}
}
return 0;
}
void FloatBitMap_t::TileableBilateralFilter( int radius_in_pixels,
float edge_threshold_value )
{
FloatBitMap_t orig( this ); // need a copy for the source
TBFCalculationContext ctxs[32];
ctxs[0].radius_in_pixels = radius_in_pixels;
ctxs[0].edge_threshold_value = edge_threshold_value;
ctxs[0].orig_bm = & orig;
ctxs[0].dest_bm = this;
int nthreads = MIN( 32, GetCPUInformation().m_nPhysicalProcessors );
ThreadHandle_t waithandles[32];
int starty = 0;
int ystep = NumRows() / nthreads;
for( int t = 0;t < nthreads;t++ )
{
if ( t )
ctxs[t]= ctxs[0];
ctxs[t].thread_number = t;
ctxs[t].min_y = starty;
if ( t != nthreads - 1 )
ctxs[t].max_y = MIN( NumRows() - 1, starty + ystep - 1 );
else
ctxs[t].max_y = NumRows() - 1;
waithandles[t]= CreateSimpleThread( TBFCalculationThreadFN, & ctxs[t] );
starty += ystep;
}
for( int t = 0;t < nthreads;t++ )
{
ThreadJoin( waithandles[t] );
}
}

179
bitmap/floatcubemap.cpp Normal file
View File

@ -0,0 +1,179 @@
#include <tier0/platform.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "bitmap/floatbitmap.h"
#include <filesystem.h>
#include <mathlib/vector.h>
#include "mathlib/spherical_geometry.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
static Vector face_xvector[6]={ // direction of x pixels on face
Vector( - 1, 0, 0 ), // back
Vector( 1, 0, 0 ), // down
Vector( 1, 0, 0 ), // front
Vector( 0, 1, 0 ), // left
Vector( 0, - 1, 0 ), // right
Vector( 1, 0, 0 ) // up
};
static Vector face_yvector[6]={ // direction of y pixels on face
Vector( 0, 0, - 1 ), // back
Vector( 0, 1, 0 ), // down
Vector( 0, 0, - 1 ), // front
Vector( 0, 0, - 1 ), // left
Vector( 0, 0, - 1 ), // right
Vector( 0, - 1, 0 ) // up
};
static Vector face_zvector[6]={
Vector( 1, 1, 1 ), // back
Vector( - 1, - 1, - 1 ), // down
Vector( - 1, - 1, 1 ), // front
Vector( 1, - 1, 1 ), // left
Vector( - 1, 1, 1 ), // right
Vector( - 1, 1, 1 ) // up
};
static char const *namepts[6]={"%sbk.pfm","%sdn.pfm","%sft.pfm","%slf.pfm","%srt.pfm","%sup.pfm"};
FloatCubeMap_t::FloatCubeMap_t( char const *basename )
{
for( int f = 0;f < 6;f++ )
{
char fnamebuf[512];
sprintf( fnamebuf, namepts[f], basename );
face_maps[f].LoadFromPFM( fnamebuf );
}
}
void FloatCubeMap_t::WritePFMs( char const *basename )
{
for( int f = 0;f < 6;f++ )
{
char fnamebuf[512];
sprintf( fnamebuf, namepts[f], basename );
face_maps[f].WritePFM( fnamebuf );
}
}
Vector FloatCubeMap_t::PixelDirection( int face, int x, int y )
{
FloatBitMap_t const & bm = face_maps[face];
float xc = x * 1.0 / ( bm.NumCols() - 1 );
float yc = y * 1.0 / ( bm.NumRows() - 1 );
Vector dir = 2 * xc * face_xvector[face]+
2 * yc * face_yvector[face]+ face_zvector[face];
VectorNormalize( dir );
return dir;
}
Vector FloatCubeMap_t::FaceNormal( int face )
{
float xc = 0.5;
float yc = 0.5;
Vector dir = 2 * xc * face_xvector[face]+
2 * yc * face_yvector[face]+ face_zvector[face];
VectorNormalize( dir );
return dir;
}
void FloatCubeMap_t::Resample( FloatCubeMap_t & out, float flPhongExponent )
{
// terribly slow brute force algorithm just so I can try it out
for( int dface = 0;dface < 6;dface++ )
{
for( int dy = 0;dy < out.face_maps[dface].NumRows();dy++ )
for( int dx = 0;dx < out.face_maps[dface].NumCols();dx++ )
{
float sum_weights = 0;
float sum_rgb[3]={0, 0, 0};
for( int sface = 0;sface < 6;sface++ )
{
// easy 15% optimization - check if faces point away from each other
if ( DotProduct( FaceNormal( sface ), FaceNormal( sface ) ) >- 0.9 )
{
Vector ddir = out.PixelDirection( dface, dx, dy );
for( int sy = 0;sy < face_maps[sface].NumRows();sy++ )
for( int sx = 0;sx < face_maps[sface].NumCols();sx++ )
{
float dp = DotProduct( ddir, PixelDirection( sface, sx, sy ) );
if ( dp > 0.0 )
{
dp = pow( dp, flPhongExponent );
sum_weights += dp;
for( int c = 0;c < 3;c++ )
sum_rgb[c] += dp * face_maps[sface].Pixel( sx, sy, 0, c );
}
}
}
}
for( int c = 0;c < 3;c++ )
out.face_maps[dface].Pixel( dx, dy, 0, c ) = sum_rgb[c] * ( 1.0 / sum_weights );
}
}
}
void FloatCubeMap_t::CalculateSphericalHarmonicApproximation( int nOrder, Vector *flCoeffs )
{
for( int nL = 0; nL <= nOrder; nL++ )
{
for( int nM = - nL ; nM <= nL; nM++ )
{
Vector vecSum( 0, 0, 0 );
float flSumWeights = 0.;
for( int nFace = 0; nFace < 6; nFace++ )
for( int nY = 0; nY < face_maps[nFace].NumRows(); nY++ )
for( int nX = 0; nX < face_maps[nFace].NumCols(); nX++ )
{
// determine direction and area of sample. !!speed!! this could be incremental
Vector dir00 = PixelDirection( nFace, nX, nY );
Vector dir01 = PixelDirection( nFace, nX, nY + 1 );
Vector dir10 = PixelDirection( nFace, nX + 1 , nY );
Vector dir11 = PixelDirection( nFace, nX + 1, nY + 1 );
float flArea = UnitSphereTriangleArea( dir00, dir10, dir11 ) +
UnitSphereTriangleArea( dir00, dir01, dir11 );
float flHarmonic = SphericalHarmonic( nL, nM, dir00 );
flSumWeights += flArea;
for( int c = 0; c < 3; c++ )
vecSum[c] += flHarmonic * face_maps[nFace].Pixel( nX, nY, 0, c ) * flArea;
}
vecSum *= ( ( 4 * M_PI ) / flSumWeights );
*( flCoeffs++ ) = vecSum;
}
}
}
void FloatCubeMap_t::GenerateFromSphericalHarmonics( int nOrder, Vector const *flCoeffs )
{
for( int nFace = 0; nFace < 6; nFace++ )
face_maps[nFace].Clear( 0, 0, 0, 1 );
for( int nL = 0; nL <= nOrder; nL++ )
{
for( int nM = - nL ; nM <= nL; nM++ )
{
for( int nFace = 0; nFace < 6; nFace++ )
for( int nY = 0; nY < face_maps[nFace].NumRows(); nY++ )
for( int nX = 0; nX < face_maps[nFace].NumCols(); nX++ )
{
// determine direction and area of sample. !!speed!! this could be incremental
Vector dir00 = PixelDirection( nFace, nX, nY );
float flHarmonic = SphericalHarmonic( nL, nM, dir00 );
for( int c = 0; c < 3; c++ )
face_maps[nFace].Pixel( nX, nY, 0, c ) += ( *flCoeffs )[c] * flHarmonic;
}
flCoeffs++;
}
}
}

651
bitmap/imageformat.cpp Normal file
View File

@ -0,0 +1,651 @@
//======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//=============================================================================//
#if defined( _WIN32 ) && !defined( _X360 ) && !defined( DX_TO_GL_ABSTRACTION )
#include <windows.h>
#include "../dx9sdk/include/d3d9types.h"
#include "dx11sdk/d3d11.h"
#endif
#include "bitmap/imageformat.h"
#include "basetypes.h"
#include "tier0/dbg.h"
#ifndef _PS3
#include <malloc.h>
#include <memory.h>
#else
#include <stdlib.h>
#endif
#include "nvtc.h"
#include "mathlib/mathlib.h"
#include "mathlib/vector.h"
#include "tier1/utlmemory.h"
#include "tier1/strtools.h"
#include "mathlib/compressed_vector.h"
// Should be last include
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Various important function types for each color format
//-----------------------------------------------------------------------------
static ImageFormatInfo_t g_ImageFormatInfo[] =
{
{ "UNKNOWN", 0, 0, 0, 0, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_UNKNOWN,
{ "RGBA8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_RGBA8888,
{ "ABGR8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_ABGR8888,
{ "RGB888", 3, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_RGB888,
{ "BGR888", 3, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_BGR888,
{ "RGB565", 2, 5, 6, 5, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_RGB565,
{ "I8", 1, 0, 0, 0, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_I8,
{ "IA88", 2, 0, 0, 0, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_IA88
{ "P8", 1, 0, 0, 0, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_P8
{ "A8", 1, 0, 0, 0, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_A8
{ "RGB888_BLUESCREEN", 3, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_RGB888_BLUESCREEN
{ "BGR888_BLUESCREEN", 3, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_BGR888_BLUESCREEN
{ "ARGB8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_ARGB8888
{ "BGRA8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_BGRA8888
{ "DXT1", 0, 0, 0, 0, 0, 0, 0, true, false, false }, // IMAGE_FORMAT_DXT1
{ "DXT3", 0, 0, 0, 0, 8, 0, 0, true, false, false }, // IMAGE_FORMAT_DXT3
{ "DXT5", 0, 0, 0, 0, 8, 0, 0, true, false, false }, // IMAGE_FORMAT_DXT5
{ "BGRX8888", 4, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_BGRX8888
{ "BGR565", 2, 5, 6, 5, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_BGR565
{ "BGRX5551", 2, 5, 5, 5, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_BGRX5551
{ "BGRA4444", 2, 4, 4, 4, 4, 0, 0, false, false, false }, // IMAGE_FORMAT_BGRA4444
{ "DXT1_ONEBITALPHA", 0, 0, 0, 0, 0, 0, 0, true, false, false }, // IMAGE_FORMAT_DXT1_ONEBITALPHA
{ "BGRA5551", 2, 5, 5, 5, 1, 0, 0, false, false, false }, // IMAGE_FORMAT_BGRA5551
{ "UV88", 2, 8, 8, 0, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_UV88
{ "UVWQ8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_UVWQ8888
{ "RGBA16161616F", 8, 16, 16, 16, 16, 0, 0, false, true, false }, // IMAGE_FORMAT_RGBA16161616F
{ "RGBA16161616", 8, 16, 16, 16, 16, 0, 0, false, false, false }, // IMAGE_FORMAT_RGBA16161616
{ "UVLX8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_UVLX8888
{ "R32F", 4, 32, 0, 0, 0, 0, 0, false, true, false }, // IMAGE_FORMAT_R32F
{ "RGB323232F", 12, 32, 32, 32, 0, 0, 0, false, true, false }, // IMAGE_FORMAT_RGB323232F
{ "RGBA32323232F", 16, 32, 32, 32, 32, 0, 0, false, true, false }, // IMAGE_FORMAT_RGBA32323232F
{ "RG1616F", 4, 16, 16, 0, 0, 0, 0, false, true, false }, // IMAGE_FORMAT_RG1616F
{ "RG3232F", 8, 32, 32, 0, 0, 0, 0, false, true, false }, // IMAGE_FORMAT_RG3232F
{ "RGBX8888", 4, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_RGBX8888
{ "NV_NULL", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_NV_NULL
// Vendor-dependent compressed formats typically used for normal map compression
{ "ATI1N", 0, 0, 0, 0, 0, 0, 0, true, false, false }, // IMAGE_FORMAT_ATI1N
{ "ATI2N", 0, 0, 0, 0, 0, 0, 0, true, false, false }, // IMAGE_FORMAT_ATI2N
{ "RGBA1010102", 4, 10, 10, 10, 2, 0, 0, false, false, false }, // IMAGE_FORMAT_RGBA1010102
{ "BGRA1010102", 4, 10, 10, 10, 2, 0, 0, false, false, false }, // IMAGE_FORMAT_BGRA1010102
{ "R16F", 2, 16, 0, 0, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_R16F
// Vendor-dependent depth formats used for shadow depth mapping
{ "D16", 2, 0, 0, 0, 0, 16, 0, false, false, true }, // IMAGE_FORMAT_D16
{ "D15S1", 2, 0, 0, 0, 0, 15, 1, false, false, true }, // IMAGE_FORMAT_D15S1
{ "D32", 4, 0, 0, 0, 0, 32, 0, false, false, true }, // IMAGE_FORMAT_D32
{ "D24S8", 4, 0, 0, 0, 0, 24, 8, false, false, true }, // IMAGE_FORMAT_D24S8
{ "LINEAR_D24S8", 4, 0, 0, 0, 0, 24, 8, false, false, true }, // IMAGE_FORMAT_LINEAR_D24S8
{ "D24X8", 4, 0, 0, 0, 0, 24, 0, false, false, true }, // IMAGE_FORMAT_D24X8
{ "D24X4S4", 4, 0, 0, 0, 0, 24, 4, false, false, true }, // IMAGE_FORMAT_D24X4S4
{ "D24FS8", 4, 0, 0, 0, 0, 24, 8, false, false, true }, // IMAGE_FORMAT_D24FS8
{ "D16_SHADOW", 2, 0, 0, 0, 0, 16, 0, false, false, true }, // IMAGE_FORMAT_D16_SHADOW
{ "D24X8_SHADOW", 4, 0, 0, 0, 0, 24, 0, false, false, true }, // IMAGE_FORMAT_D24X8_SHADOW
{ "LINEAR_BGRX8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_BGRX8888
{ "LINEAR_RGBA8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_RGBA8888
{ "LINEAR_ABGR8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_ABGR8888
{ "LINEAR_ARGB8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_ARGB8888
{ "LINEAR_BGRA8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_BGRA8888
{ "LINEAR_RGB888", 3, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_RGB888
{ "LINEAR_BGR888", 3, 8, 8, 8, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_BGR888
{ "LINEAR_BGRX5551", 2, 5, 5, 5, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_BGRX5551
{ "LINEAR_I8", 1, 0, 0, 0, 0, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_I8
{ "LINEAR_RGBA16161616", 8, 16, 16, 16, 16, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_RGBA16161616
{ "LINEAR_A8", 1, 0, 0, 0, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LINEAR_A8
{ "LINEAR_DXT1", 0, 0, 0, 0, 0, 0, 0, true, false, false }, // IMAGE_FORMAT_LINEAR_DXT1
{ "LINEAR_DXT3", 0, 0, 0, 0, 8, 0, 0, true, false, false }, // IMAGE_FORMAT_LINEAR_DXT3
{ "LINEAR_DXT5", 0, 0, 0, 0, 8, 0, 0, true, false, false }, // IMAGE_FORMAT_LINEAR_DXT5
{ "LE_BGRX8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LE_BGRX8888
{ "LE_BGRA8888", 4, 8, 8, 8, 8, 0, 0, false, false, false }, // IMAGE_FORMAT_LE_BGRA8888
{ "DXT1_RUNTIME", 0, 0, 0, 0, 0, 0, 0, true, false, false }, // IMAGE_FORMAT_DXT1_RUNTIME
{ "DXT5_RUNTIME", 0, 0, 0, 0, 8, 0, 0, true, false, false }, // IMAGE_FORMAT_DXT5_RUNTIME
// Vendor-dependent depth formats used for resolving
{ "INTZ", 4, 0, 0, 0, 0, 24, 8, false, false, true}, // IMAGE_FORMAT_INTZ
};
namespace ImageLoader
{
//-----------------------------------------------------------------------------
// Returns info about each image format
//-----------------------------------------------------------------------------
const ImageFormatInfo_t& ImageFormatInfo( ImageFormat fmt )
{
COMPILE_TIME_ASSERT( ( NUM_IMAGE_FORMATS + 1 ) == ARRAYSIZE( g_ImageFormatInfo ) );
Assert( unsigned( fmt + 1 ) <= ( NUM_IMAGE_FORMATS ) );
return g_ImageFormatInfo[ fmt + 1 ];
}
int GetMemRequired( int width, int height, int depth, int nMipmapCount, ImageFormat imageFormat, int *pAdjustedHeight )
{
depth = MAX( 1, depth );
int nRet = 0;
if ( nMipmapCount == 1 )
{
// Block compressed formats
const ImageFormatInfo_t &fmt = ImageFormatInfo( imageFormat );
if ( fmt.m_bIsCompressed )
{
Assert( ( width < 4 ) || !( width % 4 ) );
Assert( ( height < 4 ) || !( height % 4 ) );
Assert( ( depth < 4 ) || !( depth % 4 ) );
if ( width < 4 && width > 0 )
{
width = 4;
}
if ( height < 4 && height > 0 )
{
height = 4;
}
if ( depth < 4 && depth > 1 )
{
depth = 4;
}
width >>= 2;
height >>= 2;
int numBlocks = width * height * depth;
switch ( imageFormat )
{
case IMAGE_FORMAT_DXT1:
case IMAGE_FORMAT_DXT1_RUNTIME:
case IMAGE_FORMAT_LINEAR_DXT1:
case IMAGE_FORMAT_ATI1N:
nRet = numBlocks * 8;
break;
case IMAGE_FORMAT_DXT3:
case IMAGE_FORMAT_DXT5:
case IMAGE_FORMAT_DXT5_RUNTIME:
case IMAGE_FORMAT_LINEAR_DXT3:
case IMAGE_FORMAT_LINEAR_DXT5:
case IMAGE_FORMAT_ATI2N:
nRet = numBlocks * 16;
break;
}
}
else
{
nRet = width * height * depth * fmt.m_nNumBytes;
}
if ( pAdjustedHeight )
{
*pAdjustedHeight = height;
}
return nRet;
}
// Mipmap version
int memSize = 0;
// Not sensical for mip chains
if ( pAdjustedHeight )
{
*pAdjustedHeight = 0;
}
while ( true )
{
memSize += GetMemRequired( width, height, depth, imageFormat, false );
if ( width == 1 && height == 1 && depth == 1 )
break;
width >>= 1;
height >>= 1;
depth >>= 1;
if ( width < 1 )
{
width = 1;
}
if ( height < 1 )
{
height = 1;
}
if ( depth < 1 )
{
depth = 1;
}
if ( nMipmapCount )
{
if ( --nMipmapCount == 0 )
break;
}
}
return memSize;
}
int GetMemRequired( int width, int height, int depth, ImageFormat imageFormat, bool mipmap, int *pAdjustedHeight )
{
return GetMemRequired( width, height, depth, mipmap ? 0 : 1, imageFormat, pAdjustedHeight );
}
int GetMipMapLevelByteOffset( int width, int height, ImageFormat imageFormat, int skipMipLevels, int nDepth )
{
int offset = 0;
while( skipMipLevels > 0 )
{
offset += GetMemRequired( width, height, nDepth, 1, imageFormat );
if( width == 1 && height == 1 && nDepth == 1 )
{
break;
}
width = MAX( 1, width >> 1 );
height = MAX( 1, height >> 1 );
nDepth = MAX( 1, nDepth >> 1 );
skipMipLevels--;
}
return offset;
}
//-----------------------------------------------------------------------------
// This version is for mipmaps which are stored smallest level to largest level in memory
//-----------------------------------------------------------------------------
int GetMipMapLevelByteOffsetReverse( int nWidth, int nHeight, int nDepth, int nTotalMipCount, ImageFormat imageFormat, int nMipLevel )
{
if ( nTotalMipCount == 1 )
return 0;
int nSkipSize = 0;
for ( int i = 0; i < nTotalMipCount; ++i )
{
int nMipSize = GetMemRequired( nWidth, nHeight, nDepth, 1, imageFormat );
if ( i > nMipLevel )
{
nSkipSize += nMipSize;
}
if( nWidth == 1 && nHeight == 1 && nDepth == 1 )
break;
nWidth = MAX( 1, nWidth >> 1 );
nHeight = MAX( 1, nHeight >> 1 );
nDepth = MAX( 1, nDepth >> 1 );
}
return nSkipSize;
}
void GetMipMapLevelDimensions( int *width, int *height, int skipMipLevels )
{
while( skipMipLevels > 0 )
{
if( *width == 1 && *height == 1 )
{
break;
}
*width >>= 1;
*height >>= 1;
if( *width < 1 )
{
*width = 1;
}
if( *height < 1 )
{
*height = 1;
}
skipMipLevels--;
}
}
void GetMipMapLevelDimensions( int &nWidth, int &nHeight, int &nDepth, int nMipLevel )
{
for( ; nMipLevel > 0; --nMipLevel )
{
if( nWidth <= 1 && nHeight <= 1 && nDepth <= 1 )
break;
nWidth >>= 1;
nHeight >>= 1;
nDepth >>= 1;
}
nWidth = MAX( nWidth, 1 );
nHeight = MAX( nHeight, 1 );
nDepth = MAX( nDepth, 1 );
}
int GetNumMipMapLevels( int width, int height, int depth )
{
if ( depth <= 0 )
{
depth = 1;
}
if( width < 1 || height < 1 || depth < 1 )
return 0;
int numMipLevels = 1;
while( 1 )
{
if( width == 1 && height == 1 && depth == 1 )
break;
width >>= 1;
height >>= 1;
depth >>= 1;
if( width < 1 )
{
width = 1;
}
if( height < 1 )
{
height = 1;
}
if( depth < 1 )
{
depth = 1;
}
numMipLevels++;
}
return numMipLevels;
}
// Turn off warning about FOURCC formats below...
#pragma warning (disable:4063)
#ifdef POSIX
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)
#endif
//-----------------------------------------------------------------------------
// convert back and forth from D3D format to ImageFormat, regardless of
// whether it's supported or not
//-----------------------------------------------------------------------------
ImageFormat D3DFormatToImageFormat( D3DFORMAT format )
{
#if defined( PLATFORM_X360 )
if ( IS_D3DFORMAT_SRGB( format ) )
{
// sanitize the format from possible sRGB state for comparison purposes
format = MAKE_NON_SRGB_FMT( format );
}
#endif
switch ( format )
{
#if !defined( PLATFORM_X360 )
case D3DFMT_R8G8B8:
return IMAGE_FORMAT_BGR888;
#endif
#ifndef POSIX
case D3DFMT_A8B8G8R8:
return IMAGE_FORMAT_RGBA8888;
case D3DFMT_X8B8G8R8:
return IMAGE_FORMAT_RGBX8888;
#endif // !POSIX
case D3DFMT_A8R8G8B8:
return IMAGE_FORMAT_BGRA8888;
case D3DFMT_X8R8G8B8:
return IMAGE_FORMAT_BGRX8888;
case D3DFMT_R5G6B5:
return IMAGE_FORMAT_BGR565;
case D3DFMT_X1R5G5B5:
return IMAGE_FORMAT_BGRX5551;
case D3DFMT_A1R5G5B5:
return IMAGE_FORMAT_BGRA5551;
case D3DFMT_A4R4G4B4:
return IMAGE_FORMAT_BGRA4444;
#if !defined( PLATFORM_X360 ) && !defined( POSIX )
case D3DFMT_P8:
return IMAGE_FORMAT_P8;
#endif
case D3DFMT_L8:
return IMAGE_FORMAT_I8;
case D3DFMT_A8L8:
return IMAGE_FORMAT_IA88;
case D3DFMT_A8:
return IMAGE_FORMAT_A8;
case D3DFMT_DXT1:
return IMAGE_FORMAT_DXT1;
case D3DFMT_DXT3:
return IMAGE_FORMAT_DXT3;
case D3DFMT_DXT5:
return IMAGE_FORMAT_DXT5;
case D3DFMT_V8U8:
return IMAGE_FORMAT_UV88;
case D3DFMT_Q8W8V8U8:
return IMAGE_FORMAT_UVWQ8888;
case D3DFMT_X8L8V8U8:
return IMAGE_FORMAT_UVLX8888;
case D3DFMT_A16B16G16R16F:
return IMAGE_FORMAT_RGBA16161616F;
case D3DFMT_A16B16G16R16:
return IMAGE_FORMAT_RGBA16161616;
case D3DFMT_R32F:
return IMAGE_FORMAT_R32F;
case D3DFMT_A32B32G32R32F:
return IMAGE_FORMAT_RGBA32323232F;
case (D3DFORMAT)(MAKEFOURCC('N','U','L','L')):
return IMAGE_FORMAT_NULL;
case D3DFMT_D16:
return IMAGE_FORMAT_D16;
#ifndef POSIX
case D3DFMT_G16R16F:
return IMAGE_FORMAT_RG1616F;
case D3DFMT_G32R32F:
return IMAGE_FORMAT_RG3232F;
#endif // !POSIX
case D3DFMT_D24S8:
return IMAGE_FORMAT_D24S8;
case (D3DFORMAT)(MAKEFOURCC('A','T','I','1')):
return IMAGE_FORMAT_ATI1N;
case (D3DFORMAT)(MAKEFOURCC('A','T','I','2')):
return IMAGE_FORMAT_ATI2N;
#ifndef POSIX
case D3DFMT_A2B10G10R10:
return IMAGE_FORMAT_RGBA1010102;
case D3DFMT_A2R10G10B10:
return IMAGE_FORMAT_BGRA1010102;
case D3DFMT_R16F:
return IMAGE_FORMAT_R16F;
case D3DFMT_D32:
return IMAGE_FORMAT_D32;
#endif // !POSIX
case D3DFMT_D24X8:
return IMAGE_FORMAT_D24X8;
#ifndef PLATFORM_X360
case D3DFMT_D15S1:
return IMAGE_FORMAT_D15S1;
case D3DFMT_D24X4S4:
return IMAGE_FORMAT_D24X4S4;
#endif
case D3DFMT_UNKNOWN:
return IMAGE_FORMAT_UNKNOWN;
#ifdef PLATFORM_X360
case D3DFMT_LIN_A8R8G8B8:
return IMAGE_FORMAT_LINEAR_BGRA8888;
case D3DFMT_LIN_A8B8G8R8:
return IMAGE_FORMAT_LINEAR_RGBA8888;
case D3DFMT_LIN_X8R8G8B8:
return IMAGE_FORMAT_LINEAR_BGRX8888;
case D3DFMT_LIN_X1R5G5B5:
return IMAGE_FORMAT_LINEAR_BGRX5551;
case D3DFMT_LIN_L8:
return IMAGE_FORMAT_LINEAR_I8;
case D3DFMT_LIN_A16B16G16R16:
return IMAGE_FORMAT_LINEAR_RGBA16161616;
case D3DFMT_LE_X8R8G8B8:
return IMAGE_FORMAT_LE_BGRX8888;
case D3DFMT_LE_A8R8G8B8:
return IMAGE_FORMAT_LE_BGRA8888;
case D3DFMT_LIN_D24S8:
return IMAGE_FORMAT_LINEAR_D24S8;
case D3DFMT_LIN_A8:
return IMAGE_FORMAT_LINEAR_A8;
case D3DFMT_LIN_DXT1:
return IMAGE_FORMAT_LINEAR_DXT1;
case D3DFMT_LIN_DXT3:
return IMAGE_FORMAT_LINEAR_DXT3;
case D3DFMT_LIN_DXT5:
return IMAGE_FORMAT_LINEAR_DXT5;
#endif
#if !defined( _PS3 )
case D3DFMT_D24FS8:
return IMAGE_FORMAT_D24FS8;
#endif // !_PS3
}
return IMAGE_FORMAT_UNKNOWN;
}
#ifdef _PS3
// Stub out some formats that don't have direct analgoues on PS3 or that we haven't yet mapped
#define D3DFMT_A8B8G8R8 D3DFMT_UNKNOWN
#define D3DFMT_P8 D3DFMT_UNKNOWN
#define D3DFMT_G16R16F D3DFMT_UNKNOWN
#define D3DFMT_G32R32F D3DFMT_UNKNOWN
#define D3DFMT_X8B8G8R8 D3DFMT_UNKNOWN
#define D3DFMT_A2B10G10R10 D3DFMT_UNKNOWN
#define D3DFMT_A2R10G10B10 D3DFMT_UNKNOWN
#define D3DFMT_R16F D3DFMT_UNKNOWN
#define D3DFMT_D32 D3DFMT_UNKNOWN
#define D3DFMT_D24FS8 D3DFMT_UNKNOWN
#endif // _PS3
// A format exists in here only if there is a direct mapping
static D3DFORMAT s_pD3DFormats[] =
{
D3DFMT_UNKNOWN, // IMAGE_FORMAT_UNKNOWN,
D3DFMT_A8B8G8R8, // IMAGE_FORMAT_RGBA8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_ABGR8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_RGB888,
#if !defined( PLATFORM_X360 )
D3DFMT_R8G8B8, // IMAGE_FORMAT_BGR888
#else
D3DFMT_UNKNOWN, // IMAGE_FORMAT_BGR888
#endif
D3DFMT_UNKNOWN, // IMAGE_FORMAT_RGB565,
D3DFMT_L8, // IMAGE_FORMAT_I8,
D3DFMT_A8L8, // IMAGE_FORMAT_IA88,
#ifndef PLATFORM_X360
D3DFMT_P8, // IMAGE_FORMAT_P8,
#else
D3DFMT_UNKNOWN, // IMAGE_FORMAT_P8,
#endif
D3DFMT_A8, // IMAGE_FORMAT_A8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_RGB888_BLUESCREEN,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_BGR888_BLUESCREEN,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_ARGB8888,
D3DFMT_A8R8G8B8, // IMAGE_FORMAT_BGRA8888,
D3DFMT_DXT1, // IMAGE_FORMAT_DXT1,
D3DFMT_DXT3, // IMAGE_FORMAT_DXT3,
D3DFMT_DXT5, // IMAGE_FORMAT_DXT5,
D3DFMT_X8R8G8B8, // IMAGE_FORMAT_BGRX8888,
D3DFMT_R5G6B5, // IMAGE_FORMAT_BGR565,
D3DFMT_X1R5G5B5, // IMAGE_FORMAT_BGRX5551,
D3DFMT_A4R4G4B4, // IMAGE_FORMAT_BGRA4444,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_DXT1_ONEBITALPHA,
D3DFMT_A1R5G5B5, // IMAGE_FORMAT_BGRA5551,
D3DFMT_V8U8, // IMAGE_FORMAT_UV88,
D3DFMT_Q8W8V8U8, // IMAGE_FORMAT_UVWQ8888,
D3DFMT_A16B16G16R16F, // IMAGE_FORMAT_RGBA16161616F,
D3DFMT_A16B16G16R16, // IMAGE_FORMAT_RGBA16161616,
D3DFMT_X8L8V8U8, // IMAGE_FORMAT_UVLX8888,
D3DFMT_R32F, // IMAGE_FORMAT_R32F,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_RGB323232F,
D3DFMT_A32B32G32R32F, // IMAGE_FORMAT_RGBA32323232F,
D3DFMT_G16R16F, // IMAGE_FORMAT_RG1616F,
D3DFMT_G32R32F, // IMAGE_FORMAT_RG3232F,
D3DFMT_X8B8G8R8, // IMAGE_FORMAT_RGBX8888,
(D3DFORMAT)(MAKEFOURCC('N','U','L','L')), // IMAGE_FORMAT_NULL,
(D3DFORMAT)(MAKEFOURCC('A','T','I','2')), // IMAGE_FORMAT_ATI2N,
(D3DFORMAT)(MAKEFOURCC('A','T','I','1')), // IMAGE_FORMAT_ATI1N,
D3DFMT_A2B10G10R10, // IMAGE_FORMAT_RGBA1010102,
D3DFMT_A2R10G10B10, // IMAGE_FORMAT_BGRA1010102,
D3DFMT_R16F, // IMAGE_FORMAT_R16F,
D3DFMT_D16, // IMAGE_FORMAT_D16,
#ifndef PLATFORM_X360
D3DFMT_D15S1, // IMAGE_FORMAT_D15S1,
D3DFMT_D32, // IMAGE_FORMAT_D32,
D3DFMT_D24S8, // IMAGE_FORMAT_D24S8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_D24S8,
D3DFMT_D24X8, // IMAGE_FORMAT_D24X8,
D3DFMT_D24X4S4, // IMAGE_FORMAT_D24X4S4,
D3DFMT_D24FS8, // IMAGE_FORMAT_D24FS8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_D16_SHADOW,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_D24S8_SHADOW,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_BGRX8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_RGBA8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_ABGR8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_ARGB8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_BGRA8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_RGB888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_BGR888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_BGRX5551,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_I8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_RGBA16161616,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_A8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_DXT1,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_DXT3,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_DXT5,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LE_BGRX8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LE_BGRA8888,
D3DFMT_DXT1, // IMAGE_FORMAT_DXT5_RUNTIME,
D3DFMT_DXT5, // IMAGE_FORMAT_DXT5_RUNTIME,
(D3DFORMAT)(MAKEFOURCC('I','N','T','Z')), // IMAGE_FORMAT_INTZ,
#else
D3DFMT_UNKNOWN, // IMAGE_FORMAT_D15S1,
D3DFMT_D32, // IMAGE_FORMAT_D32,
D3DFMT_D24S8, // IMAGE_FORMAT_D24S8,
D3DFMT_LIN_D24S8, // IMAGE_FORMAT_LINEAR_D24S8,
D3DFMT_D24X8, // IMAGE_FORMAT_D24X8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_D24X4S4,
D3DFMT_D24FS8, // IMAGE_FORMAT_D24FS8,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_D16_SHADOW,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_D24S8_SHADOW,
D3DFMT_LIN_X8R8G8B8, // IMAGE_FORMAT_LINEAR_BGRX8888,
D3DFMT_LIN_A8B8G8R8, // IMAGE_FORMAT_LINEAR_RGBA8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_ABGR8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_ARGB8888,
D3DFMT_LIN_A8R8G8B8, // IMAGE_FORMAT_LINEAR_BGRA8888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_RGB888,
D3DFMT_UNKNOWN, // IMAGE_FORMAT_LINEAR_BGR888,
D3DFMT_LIN_X1R5G5B5, // IMAGE_FORMAT_LINEAR_BGRX5551,
D3DFMT_LIN_L8, // IMAGE_FORMAT_LINEAR_I8,
D3DFMT_LIN_A16B16G16R16, // IMAGE_FORMAT_LINEAR_RGBA16161616,
D3DFMT_LIN_A8, // IMAGE_FORMAT_LINEAR_A8
D3DFMT_LIN_DXT1, // IMAGE_FORMAT_LINEAR_DXT1,
D3DFMT_LIN_DXT3, // IMAGE_FORMAT_LINEAR_DXT3,
D3DFMT_LIN_DXT5, // IMAGE_FORMAT_LINEAR_DXT5,
D3DFMT_LE_X8R8G8B8, // IMAGE_FORMAT_LE_BGRX8888,
D3DFMT_LE_A8R8G8B8, // IMAGE_FORMAT_LE_BGRA8888,
D3DFMT_DXT1, // IMAGE_FORMAT_DXT5_RUNTIME,
D3DFMT_DXT5, // IMAGE_FORMAT_DXT5_RUNTIME,
#endif
};
D3DFORMAT ImageFormatToD3DFormat( ImageFormat format )
{
COMPILE_TIME_ASSERT( ARRAYSIZE( s_pD3DFormats ) == NUM_IMAGE_FORMATS + 1 );
return s_pD3DFormats[ format + 1 ];
}
#pragma warning (default:4063)
} // ImageLoader namespace ends

571
bitmap/psd.cpp Normal file
View File

@ -0,0 +1,571 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "bitmap/psd.h"
#include "tier0/dbg.h"
#include "tier1/utlbuffer.h"
#include "filesystem.h"
#include "tier2/tier2.h"
#include "tier2/utlstreambuffer.h"
#include "bitmap/imageformat.h"
#include "bitmap/bitmap.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// The PSD signature bytes
//-----------------------------------------------------------------------------
#define PSD_SIGNATURE 0x38425053
#define PSD_IMGRES_SIGNATURE 0x3842494D
//-----------------------------------------------------------------------------
// Format of the PSD header on disk
// NOTE: PSD file header, everything is bigendian
//-----------------------------------------------------------------------------
#pragma pack (1)
enum PSDMode_t
{
MODE_GREYSCALE = 1,
MODE_PALETTIZED = 2,
MODE_RGBA = 3,
MODE_CMYK = 4,
MODE_MULTICHANNEL = 7,
MODE_LAB = 9,
MODE_COUNT = 10,
};
//////////////////////////////////////////////////////////////////////////
//
// BEGIN PSD FILE:
//
// PSDHeader_t
// unsigned int numBytesPalette;
// byte palette[ numBytesPalette ]; = { (all red palette entries), (all green palette entries), (all blue palette entries) }, where numEntries = numBytesPalette/3;
// unsigned int numBytesImgResources;
// byte imgresources[ numBytesImgResources ]; = { sequence of PSDImgResEntry_t }
// unsigned int numBytesLayers;
// byte layers[ numBytesLayers ];
// unsigned short uCompressionInfo;
// < ~ image data ~ >
//
// END PSD FILE
//
//////////////////////////////////////////////////////////////////////////
struct PSDHeader_t
{
unsigned int m_nSignature;
unsigned short m_nVersion;
unsigned char m_pReserved[6];
unsigned short m_nChannels;
unsigned int m_nRows;
unsigned int m_nColumns;
unsigned short m_nDepth;
unsigned short m_nMode;
};
struct PSDPalette_t
{
unsigned char *m_pRed;
unsigned char *m_pGreen;
unsigned char *m_pBlue;
};
//-----------------------------------------------------------------------------
// NOTE: This is how we could load files using file mapping
//-----------------------------------------------------------------------------
//HANDLE File = CreateFile(FileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
//Assert(File != INVALID_HANDLE_VALUE);
//HANDLE FileMap = CreateFileMapping(File,0,PAGE_READONLY,0,0,0);
//Assert(FileMap != INVALID_HANDLE_VALUE);
//void *FileData = MapViewOfFile(FileMap,FILE_MAP_READ,0,0,0);
//-----------------------------------------------------------------------------
// Is it a PSD file?
//-----------------------------------------------------------------------------
bool IsPSDFile( CUtlBuffer &buf )
{
int nGet = buf.TellGet();
PSDHeader_t header;
buf.Get( &header, sizeof(header) );
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
if ( BigLong( header.m_nSignature ) != PSD_SIGNATURE )
return false;
if ( BigShort( header.m_nVersion ) != 1 )
return false;
return ( BigShort( header.m_nDepth ) == 8 );
}
bool IsPSDFile( const char *pFileName, const char *pPathID )
{
CUtlBuffer buf;
if ( !g_pFullFileSystem->ReadFile( pFileName, pPathID, buf, sizeof(PSDHeader_t) ) )
{
Warning( "Unable to read file %s\n", pFileName );
return false;
}
return IsPSDFile( buf );
}
//-----------------------------------------------------------------------------
// Returns information about the PSD file
//-----------------------------------------------------------------------------
bool PSDGetInfo( CUtlBuffer &buf, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma )
{
int nGet = buf.TellGet();
PSDHeader_t header;
buf.Get( &header, sizeof(header) );
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
if ( BigLong( header.m_nSignature ) != PSD_SIGNATURE )
return false;
if ( BigShort( header.m_nVersion ) != 1 )
return false;
if ( BigShort( header.m_nDepth ) != 8 )
return false;
*pWidth = BigLong( header.m_nColumns );
*pHeight = BigLong( header.m_nRows );
*pImageFormat = BigShort( header.m_nChannels ) == 3 ? IMAGE_FORMAT_RGB888 : IMAGE_FORMAT_RGBA8888;
*pSourceGamma = ARTWORK_GAMMA;
return true;
}
bool PSDGetInfo( const char *pFileName, const char *pPathID, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma )
{
CUtlBuffer buf;
if ( !g_pFullFileSystem->ReadFile( pFileName, pPathID, buf, sizeof(PSDHeader_t) ) )
{
Warning( "Unable to read file %s\n", pFileName );
return false;
}
return PSDGetInfo( buf, pWidth, pHeight, pImageFormat, pSourceGamma );
}
//-----------------------------------------------------------------------------
// Get PSD file image resources
//-----------------------------------------------------------------------------
PSDImageResources PSDGetImageResources( CUtlBuffer &buf )
{
int nGet = buf.TellGet();
// Header
PSDHeader_t header;
buf.Get( &header, sizeof( header ) );
// Then palette
unsigned int numBytesPalette = BigLong( buf.GetUnsignedInt() );
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, numBytesPalette );
// Then image resources
unsigned int numBytesImgResources = BigLong( buf.GetUnsignedInt() );
PSDImageResources imgres( numBytesImgResources, ( unsigned char * ) buf.PeekGet() );
// Restore the seek
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
return imgres;
}
//-----------------------------------------------------------------------------
// Converts from CMYK to RGB
//-----------------------------------------------------------------------------
static inline void CMYKToRGB( RGBA8888_t &color )
{
unsigned char nCyan = 255 - color.r;
unsigned char nMagenta = 255 - color.g;
unsigned char nYellow = 255 - color.b;
unsigned char nBlack = 255 - color.a;
int nCyanBlack = (int)nCyan + (int)nBlack;
int nMagentaBlack = (int)nMagenta + (int)nBlack;
int nYellowBlack = (int)nYellow + (int)nBlack;
color.r = ( nCyanBlack < 255 ) ? 255 - nCyanBlack : 0;
color.g = ( nMagentaBlack < 255 ) ? 255 - nMagentaBlack : 0;
color.b = ( nYellowBlack < 255 ) ? 255 - nYellowBlack : 0;
color.a = 255;
}
//-----------------------------------------------------------------------------
// Deals with uncompressed channels
//-----------------------------------------------------------------------------
static void PSDConvertToRGBA8888( int nChannelsCount, PSDMode_t mode, PSDPalette_t &palette, Bitmap_t &bitmap )
{
bool bShouldFillInAlpha = false;
unsigned char *pDest = bitmap.GetBits();
switch( mode )
{
case MODE_RGBA:
bShouldFillInAlpha = ( nChannelsCount == 3 );
break;
case MODE_PALETTIZED:
{
// Convert from palette
bShouldFillInAlpha = ( nChannelsCount == 1 );
for( int j=0; j < bitmap.Height(); ++j )
{
for ( int k = 0; k < bitmap.Width(); ++k, pDest += 4 )
{
unsigned char nPaletteIndex = pDest[0];
pDest[0] = palette.m_pRed[nPaletteIndex];
pDest[1] = palette.m_pGreen[nPaletteIndex];
pDest[2] = palette.m_pBlue[nPaletteIndex];
}
}
}
break;
case MODE_GREYSCALE:
{
// Monochrome
bShouldFillInAlpha = ( nChannelsCount == 1 );
for( int j=0; j < bitmap.Height(); ++j )
{
for ( int k = 0; k < bitmap.Width(); ++k, pDest += 4 )
{
pDest[1] = pDest[0];
pDest[2] = pDest[0];
}
}
}
break;
case MODE_CMYK:
{
// NOTE: The conversion will fill in alpha by default
bShouldFillInAlpha = false;
for( int j=0; j < bitmap.Height(); ++j )
{
for ( int k = 0; k < bitmap.Width(); ++k, pDest += 4 )
{
CMYKToRGB( *((RGBA8888_t*)pDest) );
}
}
}
break;
}
if ( bShouldFillInAlpha )
{
// No alpha channel, fill in white
unsigned char *pDest = bitmap.GetBits();
for( int j=0; j < bitmap.Height(); ++j )
{
for ( int k = 0; k < bitmap.Width(); ++k, pDest += 4 )
{
pDest[3] = 0xFF;
}
}
}
}
//-----------------------------------------------------------------------------
// Deals with uncompressed channels
//-----------------------------------------------------------------------------
static int s_pChannelIndex[MODE_COUNT+1][4] =
{
{ -1, -1, -1, -1 },
{ 0, 3, -1, -1 }, // MODE_GREYSCALE
{ 0, 3, -1, -1 }, // MODE_PALETTIZED
{ 0, 1, 2, 3 }, // MODE_RGBA
{ 0, 1, 2, 3 }, // MODE_CMYK
{ -1, -1, -1, -1 },
{ -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, // MODE_MULTICHANNEL
{ -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, // MODE_LAB
{ 3, -1, -1, -1 }, // Secret second pass mode for CMYK
};
static void PSDReadUncompressedChannels( CUtlBuffer &buf, int nChannelsCount, PSDMode_t mode, PSDPalette_t &palette, Bitmap_t &bitmap )
{
unsigned char *pChannelRow = (unsigned char*)stackalloc( bitmap.Width() );
for ( int i=0; i<nChannelsCount; ++i )
{
int nIndex = s_pChannelIndex[mode][i];
Assert( nIndex != -1 );
unsigned char *pDest = bitmap.GetBits();
for( int j=0; j < bitmap.Height(); ++j )
{
buf.Get( pChannelRow, bitmap.Width() );
// Collate the channels together
for ( int k = 0; k < bitmap.Width(); ++k, pDest += 4 )
{
pDest[nIndex] = pChannelRow[k];
}
}
}
PSDConvertToRGBA8888( nChannelsCount, mode, palette, bitmap );
}
//-----------------------------------------------------------------------------
// Deals with compressed channels
//-----------------------------------------------------------------------------
static void PSDReadCompressedChannels( CUtlBuffer &buf, int nChannelsCount, PSDMode_t mode, PSDPalette_t &palette, Bitmap_t &bitmap )
{
unsigned char *pChannelRow = (unsigned char*)stackalloc( bitmap.Width() );
for ( int i=0; i<nChannelsCount; ++i )
{
int nIndex = s_pChannelIndex[mode][i];
Assert( nIndex != -1 );
unsigned char *pDest = bitmap.GetBits();
for( int j=0; j < bitmap.Height(); ++j )
{
unsigned char *pSrc = pChannelRow;
unsigned int nPixelsRemaining = bitmap.Width();
while ( nPixelsRemaining > 0 )
{
int nCount = buf.GetChar();
if ( nCount >= 0 )
{
// If nCount is between 0 + 7F, it means copy the next nCount+1 bytes directly
++nCount;
Assert( (unsigned int)nCount <= nPixelsRemaining );
buf.Get( pSrc, nCount );
}
else
{
// If nCount is between 80 and FF, it means replicate the next byte -Count+1 times
nCount = -nCount + 1;
Assert( (unsigned int)nCount <= nPixelsRemaining );
unsigned char nPattern = buf.GetUnsignedChar();
memset( pSrc, nPattern, nCount );
}
pSrc += nCount;
nPixelsRemaining -= nCount;
}
Assert( nPixelsRemaining == 0 );
// Collate the channels together
for ( int k = 0; k < bitmap.Width(); ++k, pDest += 4 )
{
pDest[nIndex] = pChannelRow[k];
}
}
}
PSDConvertToRGBA8888( nChannelsCount, mode, palette, bitmap );
}
//-----------------------------------------------------------------------------
// Reads the PSD file into the specified buffer
//-----------------------------------------------------------------------------
bool PSDReadFileRGBA8888( CUtlBuffer &buf, Bitmap_t &bitmap )
{
PSDHeader_t header;
buf.Get( &header, sizeof(header) );
if ( BigLong( header.m_nSignature ) != PSD_SIGNATURE )
return false;
if ( BigShort( header.m_nVersion ) != 1 )
return false;
if ( BigShort( header.m_nDepth ) != 8 )
return false;
PSDMode_t mode = (PSDMode_t)BigShort( header.m_nMode );
int nChannelsCount = BigShort( header.m_nChannels );
if ( mode == MODE_MULTICHANNEL || mode == MODE_LAB )
return false;
switch ( mode )
{
case MODE_RGBA:
if ( nChannelsCount < 3 )
return false;
break;
case MODE_GREYSCALE:
case MODE_PALETTIZED:
if ( nChannelsCount != 1 && nChannelsCount != 2 )
return false;
break;
case MODE_CMYK:
if ( nChannelsCount < 4 )
return false;
break;
default:
Warning( "Unsupported PSD color mode!\n" );
return false;
}
int nWidth = BigLong( header.m_nColumns );
int nHeight = BigLong( header.m_nRows );
// Skip parts of memory we don't care about
int nColorModeSize = BigLong( buf.GetUnsignedInt() );
Assert( nColorModeSize % 3 == 0 );
unsigned char *pPaletteBits = (unsigned char*)stackalloc( nColorModeSize );
PSDPalette_t palette;
palette.m_pRed = palette.m_pGreen = palette.m_pBlue = 0;
if ( nColorModeSize )
{
int nPaletteSize = nColorModeSize / 3;
buf.Get( pPaletteBits, nColorModeSize );
palette.m_pRed = pPaletteBits;
palette.m_pGreen = palette.m_pRed + nPaletteSize;
palette.m_pBlue = palette.m_pGreen + nPaletteSize;
}
int nImageResourcesSize = BigLong( buf.GetUnsignedInt() );
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nImageResourcesSize );
int nLayersSize = BigLong( buf.GetUnsignedInt() );
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nLayersSize );
unsigned short nCompressionType = BigShort( buf.GetShort() );
bitmap.Init( nWidth, nHeight, IMAGE_FORMAT_RGBA8888 );
bool bSecondPassCMYKA = ( nChannelsCount > 4 && mode == MODE_CMYK );
if ( nCompressionType == 0 )
{
PSDReadUncompressedChannels( buf, ( nChannelsCount > 4 ) ? 4 : nChannelsCount, mode, palette, bitmap );
}
else
{
// Skip the data that indicates the length of each compressed row in bytes
// NOTE: There are two bytes per row per channel
unsigned int nLineLengthData = sizeof(unsigned short) * bitmap.Height() * nChannelsCount;
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nLineLengthData );
PSDReadCompressedChannels( buf, ( nChannelsCount > 4 ) ? 4 : nChannelsCount, mode, palette, bitmap );
}
// Read the alpha in a second pass for CMYKA
if ( bSecondPassCMYKA )
{
if ( nCompressionType == 0 )
{
PSDReadUncompressedChannels( buf, 1, MODE_COUNT, palette, bitmap );
}
else
{
PSDReadCompressedChannels( buf, 1, MODE_COUNT, palette, bitmap );
}
}
return true;
}
//-----------------------------------------------------------------------------
// Loads the heightfield from a file
//-----------------------------------------------------------------------------
bool PSDReadFileRGBA8888( const char *pFileName, const char *pPathID, Bitmap_t &bitmap )
{
CUtlStreamBuffer buf( pFileName, pPathID, CUtlBuffer::READ_ONLY );
if ( !g_pFullFileSystem->ReadFile( pFileName, pPathID, buf, sizeof(PSDHeader_t) ) )
{
Warning( "Unable to read file %s\n", pFileName );
return false;
}
return PSDReadFileRGBA8888( buf, bitmap );
}
//////////////////////////////////////////////////////////////////////////
//
// PSD Helper structs implementation
//
//////////////////////////////////////////////////////////////////////////
PSDImageResources::ResElement PSDImageResources::FindElement( Resource eType ) const
{
ResElement res;
memset( &res, 0, sizeof( res ) );
unsigned char const *pvBuffer = m_pvBuffer, * const pvBufferEnd = m_pvBuffer + m_numBytes;
while ( pvBuffer < pvBufferEnd )
{
// 4 : signature
// 2 : type
// 4 : reserved
// 2 : length
// bytes[ length ]
uint32 uSignature = BigLong( *( uint32* )( pvBuffer ) );
pvBuffer += 4;
if ( uSignature != PSD_IMGRES_SIGNATURE )
break;
unsigned short uType = BigShort( *( unsigned short * )( pvBuffer ) );
pvBuffer += 6;
unsigned short uLength = BigShort( *( unsigned short * )( pvBuffer ) );
pvBuffer += 2;
if ( uType == eType )
{
res.m_eType = eType;
res.m_numBytes = uLength;
res.m_pvData = pvBuffer;
break;
}
else
{
pvBuffer += ( ( uLength + 1 ) &~1 );
}
}
return res;
}
PSDResFileInfo::ResFileInfoElement PSDResFileInfo::FindElement( ResFileInfo eType ) const
{
ResFileInfoElement res;
memset( &res, 0, sizeof( res ) );
unsigned char const *pvBuffer = m_res.m_pvData, * const pvBufferEnd = pvBuffer + m_res.m_numBytes;
while ( pvBuffer < pvBufferEnd )
{
// 2 : = 0x1C02
// 1 : type
// 2 : length
// bytes[ length ]
unsigned short uResLabel = BigShort( *( unsigned short * )( pvBuffer ) );
pvBuffer += 2;
unsigned char uType = *pvBuffer;
pvBuffer += 1;
unsigned short uLength = BigShort( *( unsigned short * )( pvBuffer ) );
pvBuffer += 2;
if ( uType == eType && uResLabel == 0x1C02 )
{
res.m_eType = eType;
res.m_numBytes = uLength;
res.m_pvData = pvBuffer;
break;
}
else
{
pvBuffer += uLength;
}
}
return res;
}

477
bitmap/psheet.cpp Normal file
View File

@ -0,0 +1,477 @@
//===== Copyright <20> 1996-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose: sheet code for particles and other sprite functions
//
//===========================================================================//
#include "bitmap/psheet.h"
#include "tier1/UtlStringMap.h"
#include "tier1/utlbuffer.h"
#include "tier2/fileutils.h"
// MOC_TODO: These probably shouldn't be here - maybe we should put CSheetExtended somewhere else, like materialsystem?
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/itexture.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CSheet::CSheet( void )
{
}
CSheet::CSheet( CUtlBuffer &buf )
{
// lets read a sheet
buf.ActivateByteSwappingIfBigEndian();
int nVersion = buf.GetInt(); // version#
int nNumCoordsPerFrame = (nVersion)?MAX_IMAGES_PER_FRAME_ON_DISK:1;
int nNumSequences = buf.GetInt();
int nNumToAllocate = nNumSequences;
// The old hardcoded arrays were 64.
// We will allocate 64 for now to handle content issues with
// rendering system trying to get at empty sequences.
if ( nNumToAllocate < 64 )
nNumToAllocate = 64;
m_SheetInfo.EnsureCapacity( nNumSequences );
for ( int i = 0; i < nNumToAllocate; ++i )
{
m_SheetInfo.AddToTail();
m_SheetInfo[i].m_pSamples = NULL;
m_SheetInfo[i].m_SeqFlags = 0;
m_SheetInfo[i].m_bSequenceIsCopyOfAnotherSequence = 0;
m_SheetInfo[i].m_nNumFrames = 0;
m_SheetInfo[i].m_flFrameSpan = 0.0f;
}
while ( nNumSequences-- )
{
int nSequenceIndex = buf.GetInt();
if ( nSequenceIndex < 0 )
{
Warning( "Invalid sequence number (%d)!!!\n", nSequenceIndex );
return;
}
else if ( nSequenceIndex >= m_SheetInfo.Count() )
{
// This can happen if users delete intermediate sequences.
// For example you can wind up with n sequences if you delete a sequence between 0 and n
// In this case we will pad out the vector.
int i = -1;
while ( i < nSequenceIndex )
{
i = m_SheetInfo.AddToTail();
m_SheetInfo[i].m_pSamples = NULL;
m_SheetInfo[i].m_SeqFlags = 0;
m_SheetInfo[i].m_bSequenceIsCopyOfAnotherSequence = 0;
m_SheetInfo[i].m_nNumFrames = 0;
m_SheetInfo[i].m_flFrameSpan = 0.0f;
}
}
m_SheetInfo[nSequenceIndex].m_SeqFlags = (uint8)(0xFF & buf.GetInt()); // reading an int, but not worth storing it all
int nFrameCount = buf.GetInt();
// Save off how many frames we have for this sequence
m_SheetInfo[nSequenceIndex].m_nNumFrames = nFrameCount;
Assert( nFrameCount >= 0 );
bool bSingleFrameSequence = ( nFrameCount == 1 );
int nTimeSamples = bSingleFrameSequence ? 1 : SEQUENCE_SAMPLE_COUNT;
if ( m_SheetInfo[nSequenceIndex].m_pSamples )
{
Warning( "Invalid particle sheet sequence index. There are more than one items with a sequence index of %d. We are only using the last one we found..\n", nSequenceIndex );
delete[] m_SheetInfo[nSequenceIndex].m_pSamples;
}
m_SheetInfo[nSequenceIndex].m_pSamples = new SheetSequenceSample_t[ nTimeSamples ];
int fTotalSequenceTime = ( int )buf.GetFloat();
float InterpKnot[SEQUENCE_SAMPLE_COUNT];
float InterpValue[SEQUENCE_SAMPLE_COUNT];
SheetSequenceSample_t Samples[SEQUENCE_SAMPLE_COUNT];
float fCurTime = 0.;
for( int nFrm = 0 ; nFrm < nFrameCount; nFrm++ )
{
float fThisDuration = buf.GetFloat();
InterpValue[ nFrm ] = nFrm;
InterpKnot [ nFrm ] = SEQUENCE_SAMPLE_COUNT*( fCurTime/ fTotalSequenceTime );
SheetSequenceSample_t &seq = Samples[ nFrm ];
seq.m_fBlendFactor = 0.0f;
for(int nImage = 0 ; nImage< nNumCoordsPerFrame; nImage++ )
{
SequenceSampleTextureCoords_t &s=seq.m_TextureCoordData[nImage];
s.m_fLeft_U0 = buf.GetFloat();
s.m_fTop_V0 = buf.GetFloat();
s.m_fRight_U0 = buf.GetFloat();
s.m_fBottom_V0 = buf.GetFloat();
}
if ( nNumCoordsPerFrame == 1 )
seq.CopyFirstFrameToOthers();
fCurTime += fThisDuration;
m_SheetInfo[nSequenceIndex].m_flFrameSpan = fCurTime;
}
// now, fill in the whole table
for( int nIdx = 0; nIdx < nTimeSamples; nIdx++ )
{
float flIdxA, flIdxB, flInterp;
GetInterpolationData( InterpKnot, InterpValue, nFrameCount,
SEQUENCE_SAMPLE_COUNT,
nIdx,
! ( m_SheetInfo[nSequenceIndex].m_SeqFlags & SEQ_FLAG_CLAMP ),
&flIdxA, &flIdxB, &flInterp );
SheetSequenceSample_t sA = Samples[(int) flIdxA];
SheetSequenceSample_t sB = Samples[(int) flIdxB];
SheetSequenceSample_t &oseq = m_SheetInfo[nSequenceIndex].m_pSamples[nIdx];
oseq.m_fBlendFactor = flInterp;
for(int nImage = 0 ; nImage< MAX_IMAGES_PER_FRAME_IN_MEMORY; nImage++ )
{
SequenceSampleTextureCoords_t &src0=sA.m_TextureCoordData[nImage];
SequenceSampleTextureCoords_t &src1=sB.m_TextureCoordData[nImage];
SequenceSampleTextureCoords_t &o=oseq.m_TextureCoordData[nImage];
o.m_fLeft_U0 = src0.m_fLeft_U0;
o.m_fTop_V0 = src0.m_fTop_V0;
o.m_fRight_U0 = src0.m_fRight_U0;
o.m_fBottom_V0 = src0.m_fBottom_V0;
o.m_fLeft_U1 = src1.m_fLeft_U0;
o.m_fTop_V1 = src1.m_fTop_V0;
o.m_fRight_U1 = src1.m_fRight_U0;
o.m_fBottom_V1 = src1.m_fBottom_V0;
}
}
}
// now, fill in all unseen sequences with copies of the first seen sequence to prevent crashes
// while editing
int nFirstSequence = -1;
for(int i= 0 ; i < m_SheetInfo.Count(); i++)
{
if ( m_SheetInfo[i].m_pSamples )
{
nFirstSequence = i;
break;
}
}
if ( nFirstSequence != -1 )
{
for(int i=0 ; i < m_SheetInfo.Count(); i++)
{
if ( m_SheetInfo[i].m_pSamples == NULL )
{
m_SheetInfo[i].m_pSamples = m_SheetInfo[nFirstSequence].m_pSamples;
m_SheetInfo[i].m_SeqFlags = m_SheetInfo[nFirstSequence].m_SeqFlags;
m_SheetInfo[i].m_nNumFrames = m_SheetInfo[nFirstSequence].m_nNumFrames;
Assert( m_SheetInfo[i].m_nNumFrames >= 1 );
m_SheetInfo[i].m_bSequenceIsCopyOfAnotherSequence = true;
}
}
}
}
CSheet::~CSheet( void )
{
for( int i = 0; i < m_SheetInfo.Count(); i++ )
{
if ( m_SheetInfo[i].m_pSamples && ( !m_SheetInfo[i].m_bSequenceIsCopyOfAnotherSequence ) )
{
delete[] m_SheetInfo[i].m_pSamples;
}
}
}
const SheetSequenceSample_t *CSheet::GetSampleForSequence( float flAge, float flAgeScale, int nSequence, bool bForceLoop )
{
if ( m_SheetInfo[nSequence].m_nNumFrames == 1 )
return (const SheetSequenceSample_t *) &m_SheetInfo[nSequence].m_pSamples[0];
flAge *= flAgeScale;
unsigned int nFrame = ( int )flAge;
if ( ( m_SheetInfo[nSequence].m_SeqFlags & SEQ_FLAG_CLAMP ) && !bForceLoop )
{
nFrame = MIN( nFrame, SEQUENCE_SAMPLE_COUNT-1 );
}
else
{
nFrame &= SEQUENCE_SAMPLE_COUNT-1;
}
return (const SheetSequenceSample_t *) &m_SheetInfo[nSequence].m_pSamples[nFrame];
}
//////////////////////////////////////////////////////////////////////////
CSheetExtended::CSheetExtended( IMaterial* pMaterial )
{
m_Material.Init( pMaterial );
m_pSheetData = NULL;
LoadFromMaterial(pMaterial);
}
CSheetExtended::~CSheetExtended()
{
delete m_pSheetData;
}
void CSheetExtended::LoadFromMaterial( IMaterial* pMaterial )
{
if ( pMaterial == NULL )
return;
bool bFound = false;
IMaterialVar *pVar = pMaterial->FindVar( "$basetexture", &bFound );
if ( !pVar || !bFound || !pVar->IsDefined() )
return;
ITexture *pTex = pVar->GetTextureValue();
if ( !pTex || pTex->IsError() )
return;
size_t nBytes;
void const *pSheetData = pTex->GetResourceData( VTF_RSRC_SHEET, &nBytes );
if ( pSheetData )
{
CUtlBuffer bufLoad( pSheetData, nBytes, CUtlBuffer::READ_ONLY );
LoadFromBuffer( bufLoad );
}
}
void CSheetExtended::LoadFromBuffer( CUtlBuffer& buf )
{
m_pSheetData = new CSheet(buf);
}
int CSheetExtended::GetSheetSequenceCount()
{
if ( m_pSheetData == NULL )
{
return 0;
}
int nUniqueSequences = 0;
for ( int i = 0; i < m_pSheetData->m_SheetInfo.Count(); ++i )
{
if ( !m_pSheetData->m_SheetInfo[i].m_bSequenceIsCopyOfAnotherSequence )
{
nUniqueSequences++;
}
}
return nUniqueSequences;
}
int CSheetExtended::GetNthSequenceIndex( int nSequenceNumber )
{
if ( m_pSheetData == NULL )
{
return 0;
}
int nCountValidSequences = 0;
for ( int i = 0; i < m_pSheetData->m_SheetInfo.Count(); ++i )
{
if ( !m_pSheetData->m_SheetInfo[i].m_bSequenceIsCopyOfAnotherSequence )
{
if ( nCountValidSequences == nSequenceNumber )
{
return i;
}
else
{
nCountValidSequences++;
}
}
}
return 0;
}
static SheetSequenceSample_t s_DefaultSheetSequence =
{
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f,
};
const SheetSequenceSample_t *CSheetExtended::GetSampleForSequence( float flAge, float flAgeScale, int nSequence, bool bForceLoop )
{
if ( m_pSheetData == NULL )
return &s_DefaultSheetSequence;
return m_pSheetData->GetSampleForSequence( flAge, flAgeScale, nSequence, bForceLoop );
}
float CSheetExtended::GetSequenceTimeSpan( int nSequenceIndex )
{
if ( m_pSheetData == NULL )
{
return 0.f;
}
return m_pSheetData->m_SheetInfo[nSequenceIndex].m_flFrameSpan;
}
bool CSheetExtended::ValidSheetData()
{
return (m_pSheetData != NULL);
}
bool CSheetExtended::SequenceHasAlphaData( int nSequenceIndex )
{
return !(m_pSheetData->m_SheetInfo[nSequenceIndex].m_SeqFlags & SEQ_FLAG_NO_ALPHA);
}
bool CSheetExtended::SequenceHasColorData( int nSequenceIndex )
{
return !(m_pSheetData->m_SheetInfo[nSequenceIndex].m_SeqFlags & SEQ_FLAG_NO_COLOR);
}
inline void TexCoords0( CMeshBuilder& meshBuilder, int nChannel, const SequenceSampleTextureCoords_t* pSample )
{
meshBuilder.TexCoord4f( nChannel, pSample->m_fLeft_U0, pSample->m_fTop_V0, pSample->m_fRight_U0, pSample->m_fBottom_V0 );
}
inline void TexCoords1( CMeshBuilder& meshBuilder, int nChannel, const SequenceSampleTextureCoords_t* pSample )
{
meshBuilder.TexCoord4f( nChannel, pSample->m_fLeft_U1, pSample->m_fTop_V1, pSample->m_fRight_U1, pSample->m_fBottom_V1 );
}
inline void SpriteCardVert( CMeshBuilder& meshBuilder,
const Vector &vCenter,
const float flRadius,
const SheetSequenceSample_t * pSample,
const SequenceSampleTextureCoords_t *pSample0,
const SequenceSampleTextureCoords_t *pSecondTexture0,
const SheetSequenceSample_t *pSample1Data,
const SequenceSampleTextureCoords_t *pSample1,
float flChannel3U, float flChannel3V )
{
meshBuilder.Position3fv( vCenter.Base() );
TexCoords0( meshBuilder, 0, pSample0 );
TexCoords1( meshBuilder, 1, pSample0 );
meshBuilder.TexCoord4f( 2, pSample->m_fBlendFactor, 0.0f, flRadius, 0.0f );
meshBuilder.TexCoord2f( 3, flChannel3U, flChannel3V );
TexCoords0( meshBuilder, 4, pSecondTexture0 );
if ( pSample1 )
{
TexCoords0( meshBuilder, 5, pSample1 );
TexCoords1( meshBuilder, 6, pSample1 );
meshBuilder.TexCoord4f( 7, pSample1Data->m_fBlendFactor, 0, 0, 0 );
}
}
void CSheetExtended::DrawSheet( IMesh *pMesh, const Vector &vCenter, float flRadius, int nSheetSequence, float flAge, float flSheetPreviewSpeed, bool bLoopSheetPreview, int nSecondarySequence, bool bOverrideSpriteCard )
{
// nSecondarySequence
bool bSpriteCardMaterial = false;
bSpriteCardMaterial = !bOverrideSpriteCard && m_Material && m_Material->IsSpriteCard();
const SheetSequenceSample_t *pSample = GetSampleForSequence( flAge, flSheetPreviewSpeed, nSheetSequence, bLoopSheetPreview );
const SequenceSampleTextureCoords_t *pSample0 = &(pSample->m_TextureCoordData[0]);
const SequenceSampleTextureCoords_t *pSecondTexture0 = &(pSample->m_TextureCoordData[1]);
const SheetSequenceSample_t *pSample1Data = NULL;
const SequenceSampleTextureCoords_t *pSample1 = NULL;
if ( (nSecondarySequence != -1) && IsMaterialDualSequence( m_Material ) )
{
const float SECONDARY_AGE_MULTIPLIER = 0.1f; // hardcoded 'best guess' at relative speed, since we don't want a whole UI for a second speed
float flSecondaryAge = flAge * SECONDARY_AGE_MULTIPLIER;
pSample1Data = GetSampleForSequence( flSecondaryAge, flSheetPreviewSpeed, nSecondarySequence, bLoopSheetPreview );
pSample1 = &(pSample1Data->m_TextureCoordData[0]);
}
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
if ( bSpriteCardMaterial )
{
SpriteCardVert( meshBuilder, vCenter, flRadius, pSample, pSample0, pSecondTexture0, pSample1Data, pSample1, 0, 0 );
}
else
{
meshBuilder.Position3fv( (vCenter + Vector(-flRadius,-flRadius,0)).Base() );
meshBuilder.TexCoord2f( 0, pSample0->m_fLeft_U0, pSample0->m_fTop_V0 );
}
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
if ( bSpriteCardMaterial )
{
SpriteCardVert( meshBuilder, vCenter, flRadius, pSample, pSample0, pSecondTexture0, pSample1Data, pSample1, 1, 0 );
}
else
{
meshBuilder.Position3fv( (vCenter + Vector(+flRadius,-flRadius,0)).Base() );
meshBuilder.TexCoord2f( 0, pSample0->m_fRight_U0, pSample0->m_fTop_V0 );
}
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
if ( bSpriteCardMaterial )
{
SpriteCardVert( meshBuilder, vCenter, flRadius, pSample, pSample0, pSecondTexture0, pSample1Data, pSample1, 1, 1 );
}
else
{
meshBuilder.Position3fv( (vCenter + Vector(+flRadius,+flRadius,0)).Base() );
meshBuilder.TexCoord2f( 0, pSample0->m_fRight_U0, pSample0->m_fBottom_V0 );
}
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
if ( bSpriteCardMaterial )
{
SpriteCardVert( meshBuilder, vCenter, flRadius, pSample, pSample0, pSecondTexture0, pSample1Data, pSample1, 0, 1 );
}
else
{
meshBuilder.Position3fv( (vCenter + Vector(-flRadius,+flRadius,0)).Base() );
meshBuilder.TexCoord2f( 0, pSample0->m_fLeft_U0, pSample0->m_fBottom_V0 );
}
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
bool CSheetExtended::IsMaterialDualSequence( IMaterial* pMat )
{
if ( !pMat )
{
return false;
}
bool bFound = false;
IMaterialVar *pVar = pMat->FindVar( "$DUALSEQUENCE", &bFound );
return ( pVar && bFound && pVar->IsDefined() && pVar->GetIntValue() );
}
bool CSheetExtended::IsMaterialSeparateAlphaColorMaterial( IMaterial* pMat )
{
if ( !pMat || !IsMaterialDualSequence(pMat) )
{
return false;
}
bool bFound = false;
IMaterialVar *pVar = pMat->FindVar( "$SEQUENCE_BLEND_MODE", &bFound );
if ( !pVar || !bFound || !pVar->IsDefined() )
return false;
return (pVar->GetIntValue() == 1);
}

902
bitmap/resample.cpp Normal file
View File

@ -0,0 +1,902 @@
//======= Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//=============================================================================//
#include "nvtc.h"
#include "bitmap/imageformat.h"
#include "basetypes.h"
#include "tier0/dbg.h"
#ifndef _PS3
#include <malloc.h>
#include <memory.h>
#else
#include <stdlib.h>
#endif
#include "mathlib/mathlib.h"
#include "mathlib/vector.h"
#include "tier1/utlmemory.h"
#include "tier1/strtools.h"
#include "mathlib/compressed_vector.h"
// Should be last include
#include "tier0/memdbgon.h"
namespace ImageLoader
{
//-----------------------------------------------------------------------------
// Gamma correction
//-----------------------------------------------------------------------------
static void ConstructFloatGammaTable( float* pTable, float srcGamma, float dstGamma )
{
for( int i = 0; i < 256; i++ )
{
pTable[i] = 255.0 * pow( (float)i / 255.0f, srcGamma / dstGamma );
}
}
void ConstructGammaTable( unsigned char* pTable, float srcGamma, float dstGamma )
{
int v;
for( int i = 0; i < 256; i++ )
{
double f;
f = 255.0 * pow( (float)i / 255.0f, srcGamma / dstGamma );
v = ( int )(f + 0.5f);
if( v < 0 )
{
v = 0;
}
else if( v > 255 )
{
v = 255;
}
pTable[i] = ( unsigned char )v;
}
}
void GammaCorrectRGBA8888( unsigned char *pSrc, unsigned char* pDst, int width, int height, int depth,
unsigned char* pGammaTable )
{
for (int h = 0; h < depth; ++h )
{
for (int i = 0; i < height; ++i )
{
for (int j = 0; j < width; ++j )
{
int idx = (h * width * height + i * width + j) * 4;
// don't gamma correct alpha
pDst[idx] = pGammaTable[pSrc[idx]];
pDst[idx+1] = pGammaTable[pSrc[idx+1]];
pDst[idx+2] = pGammaTable[pSrc[idx+2]];
}
}
}
}
void GammaCorrectRGBA8888( unsigned char *src, unsigned char* dst, int width, int height, int depth,
float srcGamma, float dstGamma )
{
if (srcGamma == dstGamma)
{
if (src != dst)
{
memcpy( dst, src, GetMemRequired( width, height, depth, IMAGE_FORMAT_RGBA8888, false ) );
}
return;
}
static unsigned char gamma[256];
static float lastSrcGamma = -1;
static float lastDstGamma = -1;
if (lastSrcGamma != srcGamma || lastDstGamma != dstGamma)
{
ConstructGammaTable( gamma, srcGamma, dstGamma );
lastSrcGamma = srcGamma;
lastDstGamma = dstGamma;
}
GammaCorrectRGBA8888( src, dst, width, height, depth, gamma );
}
//-----------------------------------------------------------------------------
// Generate a NICE filter kernel
//-----------------------------------------------------------------------------
static void GenerateNiceFilter( float wratio, float hratio, float dratio, int kernelDiameter, float* pKernel, float *pInvKernel )
{
// Compute a kernel. This is a NICE filter
// sinc pi*x * a box from -3 to 3 * sinc ( pi * x/3)
// where x is the pixel # in the destination (shrunken) image.
// only problem here is that the NICE filter has a very large kernel
// (7x7 x wratio x hratio x dratio)
int kernelWidth, kernelHeight, kernelDepth;
float sx, dx, sy, dy, sz, dz;
float flInvFactor = 1.0f;
kernelWidth = kernelHeight = kernelDepth = 1;
sx = dx = sy = dy = sz = dz = 0.0f;
if ( wratio > 1.0f )
{
kernelWidth = ( int )( kernelDiameter * wratio );
dx = 1.0f / (float)wratio;
sx = -((float)kernelDiameter - dx) * 0.5f;
flInvFactor *= wratio;
}
if ( hratio > 1.0f )
{
kernelHeight = ( int )( kernelDiameter * hratio );
dy = 1.0f / (float)hratio;
sy = -((float)kernelDiameter - dy) * 0.5f;
flInvFactor *= hratio;
}
if ( dratio > 1.0f )
{
kernelDepth = ( int )( kernelDiameter * dratio );
dz = 1.0f / (float)dratio;
sz = -((float)kernelDiameter - dz) * 0.5f;
flInvFactor *= dratio;
}
float z = sz;
int h, i, j;
float total = 0.0f;
for ( h = 0; h < kernelDepth; ++h )
{
float y = sy;
for ( i = 0; i < kernelHeight; ++i )
{
float x = sx;
for ( j = 0; j < kernelWidth; ++j )
{
int nKernelIndex = kernelWidth * ( i + h * kernelHeight ) + j;
float d = sqrt( x * x + y * y + z * z );
if (d > kernelDiameter * 0.5f)
{
pKernel[nKernelIndex] = 0.0f;
}
else
{
float t = M_PI * d;
if ( t != 0 )
{
float sinc = sin( t ) / t;
float sinc3 = 3.0f * sin( t / 3.0f ) / t;
pKernel[nKernelIndex] = sinc * sinc3;
}
else
{
pKernel[nKernelIndex] = 1.0f;
}
total += pKernel[nKernelIndex];
}
x += dx;
}
y += dy;
}
z += dz;
}
// normalize
float flInvTotal = (total != 0.0f) ? 1.0f / total : 1.0f;
for ( h = 0; h < kernelDepth; ++h )
{
for ( i = 0; i < kernelHeight; ++i )
{
int nPixel = kernelWidth * ( h * kernelHeight + i );
for ( j = 0; j < kernelWidth; ++j )
{
pKernel[nPixel + j] *= flInvTotal;
pInvKernel[nPixel + j] = flInvFactor * pKernel[nPixel + j];
}
}
}
}
//-----------------------------------------------------------------------------
// Resample an image
//-----------------------------------------------------------------------------
static inline unsigned char Clamp( float x )
{
int idx = (int)(x + 0.5f);
if (idx < 0) idx = 0;
else if (idx > 255) idx = 255;
return idx;
}
inline bool IsPowerOfTwo( int x )
{
return (x & ( x - 1 )) == 0;
}
enum KernelType_t
{
KERNEL_DEFAULT = 0,
KERNEL_NORMALMAP,
KERNEL_ALPHATEST,
};
typedef void (*ApplyKernelFunc_t)( const KernelInfo_t &kernel, const ResampleInfo_t &info, int wratio, int hratio, int dratio, float* gammaToLinear, float *pAlphaResult );
//-----------------------------------------------------------------------------
// Apply Kernel to an image
//-----------------------------------------------------------------------------
template< int type, bool bNiceFilter >
class CKernelWrapper
{
public:
static inline int ActualX( int x, const ResampleInfo_t &info )
{
if ( info.m_nFlags & RESAMPLE_CLAMPS )
return clamp( x, 0, info.m_nSrcWidth - 1 );
// This works since info.m_nSrcWidth is a power of two.
// Even for negative #s!
return x & (info.m_nSrcWidth - 1);
}
static inline int ActualY( int y, const ResampleInfo_t &info )
{
if ( info.m_nFlags & RESAMPLE_CLAMPT )
return clamp( y, 0, info.m_nSrcHeight - 1 );
// This works since info.m_nSrcHeight is a power of two.
// Even for negative #s!
return y & (info.m_nSrcHeight - 1);
}
static inline int ActualZ( int z, const ResampleInfo_t &info )
{
if ( info.m_nFlags & RESAMPLE_CLAMPU )
return clamp( z, 0, info.m_nSrcDepth - 1 );
// This works since info.m_nSrcDepth is a power of two.
// Even for negative #s!
return z & (info.m_nSrcDepth - 1);
}
static void ComputeAveragedColor( const KernelInfo_t &kernel, const ResampleInfo_t &info,
int startX, int startY, int startZ, float *gammaToLinear, float *total )
{
total[0] = total[1] = total[2] = total[3] = 0.0f;
for ( int j = 0, srcZ = startZ; j < kernel.m_nDepth; ++j, ++srcZ )
{
int sz = ActualZ( srcZ, info );
sz *= info.m_nSrcWidth * info.m_nSrcHeight;
for ( int k = 0, srcY = startY; k < kernel.m_nHeight; ++k, ++srcY )
{
int sy = ActualY( srcY, info );
sy *= info.m_nSrcWidth;
int kernelIdx;
if ( bNiceFilter )
{
kernelIdx = kernel.m_nWidth * ( k + j * kernel.m_nHeight );
}
else
{
kernelIdx = 0;
}
for ( int l = 0, srcX = startX; l < kernel.m_nWidth; ++l, ++srcX, ++kernelIdx )
{
int sx = ActualX( srcX, info );
int srcPixel = (sz + sy + sx) << 2;
float flKernelFactor;
if ( bNiceFilter )
{
flKernelFactor = kernel.m_pKernel[kernelIdx];
if ( flKernelFactor == 0.0f )
continue;
}
else
{
flKernelFactor = kernel.m_pKernel[0];
}
if ( type == KERNEL_NORMALMAP )
{
total[0] += flKernelFactor * info.m_pSrc[srcPixel + 0];
total[1] += flKernelFactor * info.m_pSrc[srcPixel + 1];
total[2] += flKernelFactor * info.m_pSrc[srcPixel + 2];
total[3] += flKernelFactor * info.m_pSrc[srcPixel + 3];
}
else if ( type == KERNEL_ALPHATEST )
{
total[0] += flKernelFactor * gammaToLinear[ info.m_pSrc[srcPixel + 0] ];
total[1] += flKernelFactor * gammaToLinear[ info.m_pSrc[srcPixel + 1] ];
total[2] += flKernelFactor * gammaToLinear[ info.m_pSrc[srcPixel + 2] ];
if ( info.m_pSrc[srcPixel + 3] > 192 )
{
total[3] += flKernelFactor * 255.0f;
}
}
else
{
total[0] += flKernelFactor * gammaToLinear[ info.m_pSrc[srcPixel + 0] ];
total[1] += flKernelFactor * gammaToLinear[ info.m_pSrc[srcPixel + 1] ];
total[2] += flKernelFactor * gammaToLinear[ info.m_pSrc[srcPixel + 2] ];
total[3] += flKernelFactor * info.m_pSrc[srcPixel + 3];
}
}
}
}
}
static void AddAlphaToAlphaResult( const KernelInfo_t &kernel, const ResampleInfo_t &info,
int startX, int startY, int startZ, float flAlpha, float *pAlphaResult )
{
for ( int j = 0, srcZ = startZ; j < kernel.m_nDepth; ++j, ++srcZ )
{
int sz = ActualZ( srcZ, info );
sz *= info.m_nSrcWidth * info.m_nSrcHeight;
for ( int k = 0, srcY = startY; k < kernel.m_nHeight; ++k, ++srcY )
{
int sy = ActualY( srcY, info );
sy *= info.m_nSrcWidth;
int kernelIdx;
if ( bNiceFilter )
{
kernelIdx = k * kernel.m_nWidth + j * kernel.m_nWidth * kernel.m_nHeight;
}
else
{
kernelIdx = 0;
}
for ( int l = 0, srcX = startX; l < kernel.m_nWidth; ++l, ++srcX, ++kernelIdx )
{
int sx = ActualX( srcX, info );
int srcPixel = sz + sy + sx;
float flKernelFactor;
if ( bNiceFilter )
{
flKernelFactor = kernel.m_pInvKernel[kernelIdx];
if ( flKernelFactor == 0.0f )
continue;
}
else
{
flKernelFactor = kernel.m_pInvKernel[0];
}
pAlphaResult[srcPixel] += flKernelFactor * flAlpha;
}
}
}
}
static void AdjustAlphaChannel( const KernelInfo_t &kernel, const ResampleInfo_t &info,
int wratio, int hratio, int dratio, float *pAlphaResult )
{
// Find the delta between the alpha + source image
int i, k;
for ( k = 0; k < info.m_nSrcDepth; ++k )
{
for ( i = 0; i < info.m_nSrcHeight; ++i )
{
int dstPixel = i * info.m_nSrcWidth + k * info.m_nSrcWidth * info.m_nSrcHeight;
for ( int j = 0; j < info.m_nSrcWidth; ++j, ++dstPixel )
{
pAlphaResult[dstPixel] = fabs( pAlphaResult[dstPixel] - info.m_pSrc[dstPixel * 4 + 3] );
}
}
}
// Apply the kernel to the image
int nInitialZ = (dratio >> 1) - ((dratio * kernel.m_nDiameter) >> 1);
int nInitialY = (hratio >> 1) - ((hratio * kernel.m_nDiameter) >> 1);
int nInitialX = (wratio >> 1) - ((wratio * kernel.m_nDiameter) >> 1);
float flAlphaThreshhold = (info.m_flAlphaHiFreqThreshhold >= 0 ) ? 255.0f * info.m_flAlphaHiFreqThreshhold : 255.0f * 0.4f;
float flInvFactor = (dratio == 0) ? 1.0f / (hratio * wratio) : 1.0f / (hratio * wratio * dratio);
for ( int h = 0; h < info.m_nDestDepth; ++h )
{
int startZ = dratio * h + nInitialZ;
for ( i = 0; i < info.m_nDestHeight; ++i )
{
int startY = hratio * i + nInitialY;
int dstPixel = ( info.m_nDestWidth * (i + h * info.m_nDestHeight) ) << 2;
for ( int j = 0; j < info.m_nDestWidth; ++j, dstPixel += 4 )
{
if ( info.m_pDest[ dstPixel + 3 ] == 255 )
continue;
int startX = wratio * j + nInitialX;
float flAlphaDelta = 0.0f;
for ( int m = 0, srcZ = startZ; m < dratio; ++m, ++srcZ )
{
int sz = ActualZ( srcZ, info );
sz *= info.m_nSrcWidth * info.m_nSrcHeight;
for ( int k = 0, srcY = startY; k < hratio; ++k, ++srcY )
{
int sy = ActualY( srcY, info );
sy *= info.m_nSrcWidth;
for ( int l = 0, srcX = startX; l < wratio; ++l, ++srcX )
{
// HACK: This temp variable fixes an internal compiler error in vs2005
int temp = srcX;
int sx = ActualX( temp, info );
int srcPixel = sz + sy + sx;
flAlphaDelta += pAlphaResult[srcPixel];
}
}
}
flAlphaDelta *= flInvFactor;
if ( flAlphaDelta > flAlphaThreshhold )
{
info.m_pDest[ dstPixel + 3 ] = 255;
}
}
}
}
}
static void ApplyKernel( const KernelInfo_t &kernel, const ResampleInfo_t &info, int wratio, int hratio, int dratio, float* gammaToLinear, float *pAlphaResult )
{
float invDstGamma = 1.0f / info.m_flDestGamma;
// Apply the kernel to the image
int nInitialZ = (dratio >> 1) - ((dratio * kernel.m_nDiameter) >> 1);
int nInitialY = (hratio >> 1) - ((hratio * kernel.m_nDiameter) >> 1);
int nInitialX = (wratio >> 1) - ((wratio * kernel.m_nDiameter) >> 1);
float flAlphaThreshhold = (info.m_flAlphaThreshhold >= 0 ) ? 255.0f * info.m_flAlphaThreshhold : 255.0f * 0.4f;
for ( int k = 0; k < info.m_nDestDepth; ++k )
{
int startZ = dratio * k + nInitialZ;
for ( int i = 0; i < info.m_nDestHeight; ++i )
{
int startY = hratio * i + nInitialY;
int dstPixel = (i * info.m_nDestWidth + k * info.m_nDestWidth * info.m_nDestHeight) << 2;
for ( int j = 0; j < info.m_nDestWidth; ++j, dstPixel += 4 )
{
int startX = wratio * j + nInitialX;
float total[4];
ComputeAveragedColor( kernel, info, startX, startY, startZ, gammaToLinear, total );
// NOTE: Can't use a table here, we lose too many bits
if( type == KERNEL_NORMALMAP )
{
for ( int ch = 0; ch < 4; ++ ch )
info.m_pDest[ dstPixel + ch ] = Clamp( info.m_flColorGoal[ch] + ( info.m_flColorScale[ch] * ( total[ch] - info.m_flColorGoal[ch] ) ) );
}
else if ( type == KERNEL_ALPHATEST )
{
// If there's more than 40% coverage, then keep the pixel (renormalize the color based on coverage)
float flAlpha = ( total[3] >= flAlphaThreshhold ) ? 255 : 0;
for ( int ch = 0; ch < 3; ++ ch )
info.m_pDest[ dstPixel + ch ] = Clamp( 255.0f * pow( ( info.m_flColorGoal[ch] + ( info.m_flColorScale[ch] * ( ( total[ch] > 0 ? total[ch] : 0 ) - info.m_flColorGoal[ch] ) ) ) / 255.0f, invDstGamma ) );
info.m_pDest[ dstPixel + 3 ] = Clamp( flAlpha );
AddAlphaToAlphaResult( kernel, info, startX, startY, startZ, flAlpha, pAlphaResult );
}
else
{
for ( int ch = 0; ch < 3; ++ ch )
info.m_pDest[ dstPixel + ch ] = Clamp( 255.0f * pow( ( info.m_flColorGoal[ch] + ( info.m_flColorScale[ch] * ( ( total[ch] > 0 ? total[ch] : 0 ) - info.m_flColorGoal[ch] ) ) ) / 255.0f, invDstGamma ) );
info.m_pDest[ dstPixel + 3 ] = Clamp( info.m_flColorGoal[3] + ( info.m_flColorScale[3] * ( total[3] - info.m_flColorGoal[3] ) ) );
}
}
}
if ( type == KERNEL_ALPHATEST )
{
AdjustAlphaChannel( kernel, info, wratio, hratio, dratio, pAlphaResult );
}
}
}
};
typedef CKernelWrapper< KERNEL_DEFAULT, false > ApplyKernelDefault_t;
typedef CKernelWrapper< KERNEL_NORMALMAP, false > ApplyKernelNormalmap_t;
typedef CKernelWrapper< KERNEL_ALPHATEST, false > ApplyKernelAlphatest_t;
typedef CKernelWrapper< KERNEL_DEFAULT, true > ApplyKernelDefaultNice_t;
typedef CKernelWrapper< KERNEL_NORMALMAP, true > ApplyKernelNormalmapNice_t;
typedef CKernelWrapper< KERNEL_ALPHATEST, true > ApplyKernelAlphatestNice_t;
static ApplyKernelFunc_t g_KernelFunc[] =
{
ApplyKernelDefault_t::ApplyKernel,
ApplyKernelNormalmap_t::ApplyKernel,
ApplyKernelAlphatest_t::ApplyKernel,
};
static ApplyKernelFunc_t g_KernelFuncNice[] =
{
ApplyKernelDefaultNice_t::ApplyKernel,
ApplyKernelNormalmapNice_t::ApplyKernel,
ApplyKernelAlphatestNice_t::ApplyKernel,
};
void ComputeNiceFilterKernel( float wratio, float hratio, float dratio, KernelInfo_t *pKernel )
{
// Kernel size is measured in dst pixels
pKernel->m_nDiameter = 6;
// Compute a nice kernel...
pKernel->m_nWidth = ( wratio > 1 ) ? ( int )( pKernel->m_nDiameter * wratio ) : 1;
pKernel->m_nHeight = ( hratio > 1 ) ? ( int )( pKernel->m_nDiameter * hratio ) : 1;
pKernel->m_nDepth = ( dratio > 1 ) ? ( int )( pKernel->m_nDiameter * dratio ) : 1;
// Cache the filter (2d kernels only)....
int power = -1;
if ( (wratio == hratio) && (dratio <= 1) && ( IsPowerOfTwo( pKernel->m_nWidth ) ) && ( IsPowerOfTwo( pKernel->m_nHeight ) ) )
{
power = 0;
int tempWidth = ( int )wratio;
while (tempWidth > 1)
{
++power;
tempWidth >>= 1;
}
// Don't cache anything bigger than 512x512
if (power >= 10)
{
power = -1;
}
}
static float* s_pKernelCache[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static float* s_pInvKernelCache[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
if (power >= 0)
{
if (!s_pKernelCache[power])
{
s_pKernelCache[power] = new float[pKernel->m_nWidth * pKernel->m_nHeight];
s_pInvKernelCache[power] = new float[pKernel->m_nWidth * pKernel->m_nHeight];
GenerateNiceFilter( wratio, hratio, dratio, pKernel->m_nDiameter, s_pKernelCache[power], s_pInvKernelCache[power] );
}
pKernel->m_pKernel = s_pKernelCache[power];
pKernel->m_pInvKernel = s_pInvKernelCache[power];
}
else
{
// Don't cache non-square kernels, or 3d kernels
float *pTempMemory = new float[pKernel->m_nWidth * pKernel->m_nHeight * pKernel->m_nDepth];
float *pTempInvMemory = new float[pKernel->m_nWidth * pKernel->m_nHeight * pKernel->m_nDepth];
GenerateNiceFilter( wratio, hratio, dratio, pKernel->m_nDiameter, pTempMemory, pTempInvMemory );
pKernel->m_pKernel = pTempMemory;
pKernel->m_pInvKernel = pTempInvMemory;
}
}
void CleanupNiceFilterKernel( KernelInfo_t *pKernel )
{
if ( ( pKernel->m_nWidth != pKernel->m_nHeight ) || ( pKernel->m_nDepth > 1 ) || ( pKernel->m_nWidth > 512 ) ||
( !IsPowerOfTwo( pKernel->m_nWidth ) ) || ( !IsPowerOfTwo( pKernel->m_nHeight ) ) )
{
delete[] pKernel->m_pKernel;
delete[] pKernel->m_pInvKernel;
}
}
bool ResampleRGBA8888( const ResampleInfo_t& info )
{
// No resampling needed, just gamma correction
if ( info.m_nSrcWidth == info.m_nDestWidth && info.m_nSrcHeight == info.m_nDestHeight && info.m_nSrcDepth == info.m_nDestDepth )
{
// Here, we need to gamma convert the source image..
GammaCorrectRGBA8888( info.m_pSrc, info.m_pDest, info.m_nSrcWidth, info.m_nSrcHeight, info.m_nSrcDepth, info.m_flSrcGamma, info.m_flDestGamma );
return true;
}
// fixme: has to be power of two for now.
if( !IsPowerOfTwo(info.m_nSrcWidth) || !IsPowerOfTwo(info.m_nSrcHeight) || !IsPowerOfTwo(info.m_nSrcDepth) ||
!IsPowerOfTwo(info.m_nDestWidth) || !IsPowerOfTwo(info.m_nDestHeight) || !IsPowerOfTwo(info.m_nDestDepth) )
{
return false;
}
// fixme: can only downsample for now.
if( (info.m_nSrcWidth < info.m_nDestWidth) || (info.m_nSrcHeight < info.m_nDestHeight) || (info.m_nSrcDepth < info.m_nDestDepth) )
{
return false;
}
// Compute gamma tables...
static float gammaToLinear[256];
static float lastSrcGamma = -1;
if (lastSrcGamma != info.m_flSrcGamma)
{
ConstructFloatGammaTable( gammaToLinear, info.m_flSrcGamma, 1.0f );
lastSrcGamma = info.m_flSrcGamma;
}
int wratio = info.m_nSrcWidth / info.m_nDestWidth;
int hratio = info.m_nSrcHeight / info.m_nDestHeight;
int dratio = (info.m_nSrcDepth != info.m_nDestDepth) ? info.m_nSrcDepth / info.m_nDestDepth : 0;
KernelInfo_t kernel;
memset( &kernel, 0, sizeof( KernelInfo_t ) );
float pKernelMem[1];
float pInvKernelMem[1];
if ( info.m_nFlags & RESAMPLE_NICE_FILTER )
{
ComputeNiceFilterKernel( wratio, hratio, dratio, &kernel );
}
else
{
// Compute a kernel...
kernel.m_nWidth = wratio;
kernel.m_nHeight = hratio;
kernel.m_nDepth = dratio ? dratio : 1;
kernel.m_nDiameter = 1;
// Simple implementation of a box filter that doesn't block the stack!
pKernelMem[0] = 1.0f / (float)(kernel.m_nWidth * kernel.m_nHeight * kernel.m_nDepth);
pInvKernelMem[0] = 1.0f;
kernel.m_pKernel = pKernelMem;
kernel.m_pInvKernel = pInvKernelMem;
}
float *pAlphaResult = NULL;
KernelType_t type;
if ( info.m_nFlags & RESAMPLE_NORMALMAP )
{
type = KERNEL_NORMALMAP;
}
else if ( info.m_nFlags & RESAMPLE_ALPHATEST )
{
int nSize = info.m_nSrcHeight * info.m_nSrcWidth * info.m_nSrcDepth * sizeof(float);
pAlphaResult = (float*)malloc( nSize );
memset( pAlphaResult, 0, nSize );
type = KERNEL_ALPHATEST;
}
else
{
type = KERNEL_DEFAULT;
}
if ( info.m_nFlags & RESAMPLE_NICE_FILTER )
{
g_KernelFuncNice[type]( kernel, info, wratio, hratio, dratio, gammaToLinear, pAlphaResult );
CleanupNiceFilterKernel( &kernel );
}
else
{
g_KernelFunc[type]( kernel, info, wratio, hratio, dratio, gammaToLinear, pAlphaResult );
}
if ( pAlphaResult )
{
free( pAlphaResult );
}
return true;
}
bool ResampleRGBA16161616( const ResampleInfo_t& info )
{
// HDRFIXME: This is some lame shit right here. (We need to get NICE working, etc, etc.)
// Make sure everything is power of two.
Assert( ( info.m_nSrcWidth & ( info.m_nSrcWidth - 1 ) ) == 0 );
Assert( ( info.m_nSrcHeight & ( info.m_nSrcHeight - 1 ) ) == 0 );
Assert( ( info.m_nDestWidth & ( info.m_nDestWidth - 1 ) ) == 0 );
Assert( ( info.m_nDestHeight & ( info.m_nDestHeight - 1 ) ) == 0 );
// Make sure that we aren't upscsaling the image. . .we do`n't support that very well.
Assert( info.m_nSrcWidth >= info.m_nDestWidth );
Assert( info.m_nSrcHeight >= info.m_nDestHeight );
int nSampleWidth = info.m_nSrcWidth / info.m_nDestWidth;
int nSampleHeight = info.m_nSrcHeight / info.m_nDestHeight;
unsigned short *pSrc = ( unsigned short * )info.m_pSrc;
unsigned short *pDst = ( unsigned short * )info.m_pDest;
int x, y;
for( y = 0; y < info.m_nDestHeight; y++ )
{
for( x = 0; x < info.m_nDestWidth; x++ )
{
int accum[4];
accum[0] = accum[1] = accum[2] = accum[3] = 0;
int nSampleY;
for( nSampleY = 0; nSampleY < nSampleHeight; nSampleY++ )
{
int nSampleX;
for( nSampleX = 0; nSampleX < nSampleWidth; nSampleX++ )
{
accum[0] += ( int )pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+0];
accum[1] += ( int )pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+1];
accum[2] += ( int )pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+2];
accum[3] += ( int )pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+3];
}
}
int i;
for( i = 0; i < 4; i++ )
{
accum[i] /= ( nSampleWidth * nSampleHeight );
accum[i] = MAX( accum[i], 0 );
accum[i] = MIN( accum[i], 65535 );
pDst[(x+y*info.m_nDestWidth)*4+i] = ( unsigned short )accum[i];
}
}
}
return true;
}
bool ResampleRGB323232F( const ResampleInfo_t& info )
{
// HDRFIXME: This is some lame shit right here. (We need to get NICE working, etc, etc.)
// Make sure everything is power of two.
Assert( ( info.m_nSrcWidth & ( info.m_nSrcWidth - 1 ) ) == 0 );
Assert( ( info.m_nSrcHeight & ( info.m_nSrcHeight - 1 ) ) == 0 );
Assert( ( info.m_nDestWidth & ( info.m_nDestWidth - 1 ) ) == 0 );
Assert( ( info.m_nDestHeight & ( info.m_nDestHeight - 1 ) ) == 0 );
// Make sure that we aren't upscaling the image. . .we do`n't support that very well.
Assert( info.m_nSrcWidth >= info.m_nDestWidth );
Assert( info.m_nSrcHeight >= info.m_nDestHeight );
int nSampleWidth = info.m_nSrcWidth / info.m_nDestWidth;
int nSampleHeight = info.m_nSrcHeight / info.m_nDestHeight;
float *pSrc = ( float * )info.m_pSrc;
float *pDst = ( float * )info.m_pDest;
for( int y = 0; y < info.m_nDestHeight; y++ )
{
for( int x = 0; x < info.m_nDestWidth; x++ )
{
float accum[4];
accum[0] = accum[1] = accum[2] = accum[3] = 0;
for( int nSampleY = 0; nSampleY < nSampleHeight; nSampleY++ )
{
for( int nSampleX = 0; nSampleX < nSampleWidth; nSampleX++ )
{
accum[0] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*3+0];
accum[1] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*3+1];
accum[2] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*3+2];
}
}
for( int i = 0; i < 3; i++ )
{
accum[i] /= ( nSampleWidth * nSampleHeight );
pDst[(x+y*info.m_nDestWidth)*3+i] = accum[i];
}
}
}
return true;
}
bool ResampleRGBA32323232F( const ResampleInfo_t& info )
{
// HDRFIXME: This is some lame shit right here. (We need to get NICE working, etc, etc.)
// Make sure everything is power of two.
Assert( ( info.m_nSrcWidth & ( info.m_nSrcWidth - 1 ) ) == 0 );
Assert( ( info.m_nSrcHeight & ( info.m_nSrcHeight - 1 ) ) == 0 );
Assert( ( info.m_nDestWidth & ( info.m_nDestWidth - 1 ) ) == 0 );
Assert( ( info.m_nDestHeight & ( info.m_nDestHeight - 1 ) ) == 0 );
// Make sure that we aren't upscaling the image. . .we don't support that very well.
Assert( info.m_nSrcWidth >= info.m_nDestWidth );
Assert( info.m_nSrcHeight >= info.m_nDestHeight );
int nSampleWidth = info.m_nSrcWidth / info.m_nDestWidth;
int nSampleHeight = info.m_nSrcHeight / info.m_nDestHeight;
float *pSrc = ( float * )info.m_pSrc;
float *pDst = ( float * )info.m_pDest;
for( int y = 0; y < info.m_nDestHeight; y++ )
{
for( int x = 0; x < info.m_nDestWidth; x++ )
{
float accum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
for( int nSampleY = 0; nSampleY < nSampleHeight; nSampleY++ )
{
for( int nSampleX = 0; nSampleX < nSampleWidth; nSampleX++ )
{
accum[0] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+0];
accum[1] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+1];
accum[2] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+2];
accum[3] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+3];
}
}
for( int i = 0; i < 4; i++ )
{
accum[i] /= ( nSampleWidth * nSampleHeight );
pDst[(x+y*info.m_nDestWidth)*4+i] = accum[i];
}
}
}
return true;
}
//-----------------------------------------------------------------------------
// Generates mipmap levels
//-----------------------------------------------------------------------------
void GenerateMipmapLevels( unsigned char* pSrc, unsigned char* pDst, int width,
int height, int depth, ImageFormat imageFormat, float srcGamma, float dstGamma, int numLevels )
{
int dstWidth = width;
int dstHeight = height;
int dstDepth = depth;
// temporary storage for the mipmaps
int tempMem = GetMemRequired( dstWidth, dstHeight, dstDepth, IMAGE_FORMAT_RGBA8888, false );
CUtlMemory<unsigned char> tmpImage;
tmpImage.EnsureCapacity( tempMem );
while( true )
{
// This generates a mipmap in RGBA8888, linear space
ResampleInfo_t info;
info.m_pSrc = pSrc;
info.m_pDest = tmpImage.Base();
info.m_nSrcWidth = width;
info.m_nSrcHeight = height;
info.m_nSrcDepth = depth;
info.m_nDestWidth = dstWidth;
info.m_nDestHeight = dstHeight;
info.m_nDestDepth = dstDepth;
info.m_flSrcGamma = srcGamma;
info.m_flDestGamma = dstGamma;
ResampleRGBA8888( info );
// each mipmap level needs to be color converted separately
ConvertImageFormat( tmpImage.Base(), IMAGE_FORMAT_RGBA8888,
pDst, imageFormat, dstWidth, dstHeight, 0, 0 );
if (numLevels == 0)
{
// We're done after we've made the 1x1 mip level
if (dstWidth == 1 && dstHeight == 1 && dstDepth == 1)
return;
}
else
{
if (--numLevels <= 0)
return;
}
// Figure out where the next level goes
int memRequired = ImageLoader::GetMemRequired( dstWidth, dstHeight, dstDepth, imageFormat, false);
pDst += memRequired;
// shrink by a factor of 2, but clamp at 1 pixel (non-square textures)
dstWidth = dstWidth > 1 ? dstWidth >> 1 : 1;
dstHeight = dstHeight > 1 ? dstHeight >> 1 : 1;
dstDepth = dstDepth > 1 ? dstDepth >> 1 : 1;
}
}
} // ImageLoader namespace ends

274
bitmap/texturepacker.cpp Normal file
View File

@ -0,0 +1,274 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if IS_WINDOWS_PC
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "bitmap/texturepacker.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CTexturePacker::CTexturePacker( int texWidth, int texHeight, int pixelGap )
{
m_PageWidth = texWidth;
m_PageHeight = texHeight;
m_PixelGap = pixelGap;
Clear();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CTexturePacker::~CTexturePacker()
{
// remove all existing data
m_Tree.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: Resets the tree
//-----------------------------------------------------------------------------
void CTexturePacker::Clear()
{
// remove all existing data
m_Tree.RemoveAll();
// Add root item, everything else is procedurally generated
int rootIndex = m_Tree.InsertChildAfter( m_Tree.InvalidIndex(), m_Tree.InvalidIndex() );
TreeEntry_t &topNode = m_Tree[rootIndex];
topNode.rc.x = 0;
topNode.rc.y = 0;
topNode.rc.width = m_PageWidth;
topNode.rc.height = m_PageHeight;
topNode.bInUse = false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CTexturePacker::IsLeaf( int nodeIndex )
{
int leftChildIndex = m_Tree.FirstChild( nodeIndex );
if ( leftChildIndex == m_Tree.InvalidIndex() )
{
return true;
}
else if ( m_Tree.NextSibling( leftChildIndex ) == m_Tree.InvalidIndex() )
{
return true;
}
return false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CTexturePacker::IsLeftChild( int nodeIndexParent, int nodeIndexChild )
{
int leftChildIndex = m_Tree.FirstChild( nodeIndexParent );
if ( leftChildIndex == nodeIndexChild )
{
return true;
}
else
{
return false;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CTexturePacker::IsRightChild( int nodeIndexParent, int nodeIndexChild )
{
return !IsLeftChild( nodeIndexParent, nodeIndexChild );
}
#ifdef _PS3
// Remove some annoying GCC warnings by specializing these template functions to remove a redundant (i>=0) clause
template <>
inline bool CUtlNTree<CTexturePacker::TreeEntry_t,short unsigned int>::IsValidIndex( short unsigned int i ) const
{
return (i < m_MaxElementIndex);
}
template <>
inline bool CUtlNTree<CTexturePacker::TreeEntry_t,short unsigned int>::IsInTree( short unsigned int i ) const
{
return (i < m_MaxElementIndex) && (InternalNode(i).m_PrevSibling != i);
}
#endif // _PS3
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CTexturePacker::InsertRect( const Rect_t& texRect, int nodeIndex )
{
if ( nodeIndex == -1 )
{
nodeIndex = m_Tree.Root();
Assert( nodeIndex != m_Tree.InvalidIndex() );
}
if ( !IsLeaf( nodeIndex) ) // not a leaf
{
// try inserting under left child
int leftChildIndex = m_Tree.FirstChild( nodeIndex );
int newIndex = InsertRect( texRect, leftChildIndex );
if ( m_Tree.IsValidIndex( newIndex ) )
{
return newIndex;
}
// no room, insert under right child
int rightChildIndex = m_Tree.NextSibling( leftChildIndex );
return InsertRect( texRect, rightChildIndex );
}
else
{
if ( m_Tree[nodeIndex].bInUse ) // there is already a glpyh here
{
return -1;
}
int cacheSlotWidth = m_Tree[nodeIndex].rc.width;
int cacheSlotHeight = m_Tree[nodeIndex].rc.height;
if ( ( texRect.width > cacheSlotWidth ) ||
( texRect.height > cacheSlotHeight ) )
{
// if this node's box is too small, return
return -1;
}
if ( ( texRect.width == cacheSlotWidth) &&
( texRect.height == cacheSlotHeight ) )
{
// if we're just right, accept
m_Tree[nodeIndex].bInUse = true;
return nodeIndex;
}
// otherwise, gotta split this node and create some kids
// decide which way to split
int dw = cacheSlotWidth - texRect.width;
int dh = cacheSlotHeight - texRect.height;
int leftChildIndex;
if ( dw > dh ) // split along x
{
leftChildIndex = m_Tree.InsertChildAfter( nodeIndex, m_Tree.InvalidIndex() );
Assert( IsLeftChild( nodeIndex, leftChildIndex ) );
TreeEntry_t &leftChild = m_Tree[leftChildIndex];
leftChild.rc.x = m_Tree[nodeIndex].rc.x;
leftChild.rc.y = m_Tree[nodeIndex].rc.y;
leftChild.rc.width = texRect.width;
leftChild.rc.height = cacheSlotHeight;
leftChild.bInUse = false;
int rightChildIndex = m_Tree.InsertChildAfter( nodeIndex, leftChildIndex );
Assert( IsRightChild( nodeIndex, rightChildIndex ) );
TreeEntry_t &rightChild = m_Tree[rightChildIndex];
rightChild.rc.x = m_Tree[nodeIndex].rc.x + texRect.width + m_PixelGap;
rightChild.rc.y = m_Tree[nodeIndex].rc.y;
rightChild.rc.width = dw - m_PixelGap;
rightChild.rc.height = cacheSlotHeight;
rightChild.bInUse = false;
Assert( m_Tree.Parent( leftChildIndex ) == m_Tree.Parent( rightChildIndex ) );
Assert( m_Tree.Parent( leftChildIndex ) == nodeIndex );
}
else // split along y
{
leftChildIndex = m_Tree.InsertChildAfter( nodeIndex, m_Tree.InvalidIndex() );
Assert( IsLeftChild( nodeIndex, leftChildIndex ) );
TreeEntry_t &leftChild = m_Tree[leftChildIndex];
leftChild.rc.x = m_Tree[nodeIndex].rc.x;
leftChild.rc.y = m_Tree[nodeIndex].rc.y;
leftChild.rc.width = cacheSlotWidth;
leftChild.rc.height = texRect.height;
leftChild.bInUse = false;
int rightChildIndex = m_Tree.InsertChildAfter( nodeIndex, leftChildIndex );
Assert( IsRightChild( nodeIndex, rightChildIndex ) );
TreeEntry_t &rightChild = m_Tree[rightChildIndex];
rightChild.rc.x = m_Tree[nodeIndex].rc.x;
rightChild.rc.y = m_Tree[nodeIndex].rc.y + texRect.height + m_PixelGap;
rightChild.rc.width = cacheSlotWidth;
rightChild.rc.height = dh - m_PixelGap;
rightChild.bInUse = false;
Assert( m_Tree.Parent( leftChildIndex ) == m_Tree.Parent( rightChildIndex ) );
Assert( m_Tree.Parent( leftChildIndex ) == nodeIndex );
}
// insert into first child we created
return InsertRect( texRect, leftChildIndex );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CTexturePacker::RemoveRect( int nodeIndex )
{
if ( !m_Tree.IsInTree( nodeIndex ) )
{
return false;
}
m_Tree[nodeIndex].bInUse = false;
// If its a leaf, see if its peer is empty, if it is the split can go away.
if ( IsLeaf( nodeIndex) ) // a leaf
{
int parentIndex = m_Tree.Parent( nodeIndex );
// Is this node the left child?
if ( nodeIndex == m_Tree.FirstChild( parentIndex ) )
{
// Get the index of the right child
int peerIndex = m_Tree.NextSibling( nodeIndex );
if ( IsLeaf( peerIndex ) && !m_Tree[peerIndex].bInUse )
{
// Both children are leaves and neither is in use, remove the split here.
m_Tree.Remove( nodeIndex );
m_Tree.Remove( peerIndex );
}
}
else // Its the right child
{
// Get the index of the left child
int peerIndex = m_Tree.FirstChild( parentIndex );
Assert( nodeIndex == m_Tree.NextSibling( peerIndex ) );
if ( IsLeaf( peerIndex ) && !m_Tree[peerIndex].bInUse )
{
// Both children are leaves and neither is in use, remove the split here.
m_Tree.Remove( nodeIndex );
m_Tree.Remove( peerIndex );
}
}
}
return true;
}

1023
bitmap/tgaloader.cpp Normal file

File diff suppressed because it is too large Load Diff

496
bitmap/tgawriter.cpp Normal file
View File

@ -0,0 +1,496 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include <stdlib.h>
#include <stdio.h>
#include "tier0/dbg.h"
#ifndef _PS3
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include "filesystem.h"
#include "bitmap/tgawriter.h"
#include "tier1/utlbuffer.h"
#include "bitmap/imageformat.h"
#include "tier2/tier2.h"
#include "tier2/fileutils.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
namespace TGAWriter
{
#pragma pack(1)
struct TGAHeader_t
{
unsigned char id_length;
unsigned char colormap_type;
unsigned char image_type;
unsigned short colormap_index;
unsigned short colormap_length;
unsigned char colormap_size;
unsigned short x_origin;
unsigned short y_origin;
unsigned short width;
unsigned short height;
unsigned char pixel_size;
unsigned char attributes;
};
#pragma pack()
#define fputc myfputc
#define fwrite myfwrite
static void fputLittleShort( unsigned short s, CUtlBuffer &buffer )
{
buffer.PutChar( s & 0xff );
buffer.PutChar( s >> 8 );
}
static inline void myfputc( unsigned char c, FileHandle_t fileHandle )
{
g_pFullFileSystem->Write( &c, 1, fileHandle );
}
static inline void myfwrite( void const *data, int size1, int size2, FileHandle_t fileHandle )
{
g_pFullFileSystem->Write( data, size1 * size2, fileHandle );
}
//-----------------------------------------------------------------------------
// FIXME: assumes that we don't need to do gamma correction.
//-----------------------------------------------------------------------------
bool WriteToBuffer( unsigned char *pImageData, CUtlBuffer &buffer, int width, int height,
ImageFormat srcFormat, ImageFormat dstFormat )
{
TGAHeader_t header;
// Fix the dstFormat to match what actually is going to go into the file
switch( dstFormat )
{
case IMAGE_FORMAT_RGB888:
dstFormat = IMAGE_FORMAT_BGR888;
break;
#if defined( _X360 )
case IMAGE_FORMAT_LINEAR_RGB888:
dstFormat = IMAGE_FORMAT_LINEAR_BGR888;
break;
#endif
case IMAGE_FORMAT_RGBA8888:
dstFormat = IMAGE_FORMAT_BGRA8888;
break;
}
header.id_length = 0; // comment length
header.colormap_type = 0; // ???
switch( dstFormat )
{
case IMAGE_FORMAT_BGR888:
#if defined( _X360 )
case IMAGE_FORMAT_LINEAR_BGR888:
#endif
header.image_type = 2; // 24/32 bit uncompressed TGA
header.pixel_size = 24;
break;
case IMAGE_FORMAT_BGRA8888:
header.image_type = 2; // 24/32 bit uncompressed TGA
header.pixel_size = 32;
break;
case IMAGE_FORMAT_I8:
header.image_type = 1; // 8 bit uncompressed TGA
header.pixel_size = 8;
break;
default:
return false;
break;
}
header.colormap_index = 0;
header.colormap_length = 0;
header.colormap_size = 0;
header.x_origin = 0;
header.y_origin = 0;
header.width = ( unsigned short )width;
header.height = ( unsigned short )height;
header.attributes = 0x20; // Makes it so we don't have to vertically flip the image
buffer.PutChar( header.id_length );
buffer.PutChar( header.colormap_type );
buffer.PutChar( header.image_type );
fputLittleShort( header.colormap_index, buffer );
fputLittleShort( header.colormap_length, buffer );
buffer.PutChar( header.colormap_size );
fputLittleShort( header.x_origin, buffer );
fputLittleShort( header.y_origin, buffer );
fputLittleShort( header.width, buffer );
fputLittleShort( header.height, buffer );
buffer.PutChar( header.pixel_size );
buffer.PutChar( header.attributes );
int nSizeInBytes = width * height * ImageLoader::SizeInBytes( dstFormat );
buffer.EnsureCapacity( buffer.TellPut() + nSizeInBytes );
unsigned char *pDst = (unsigned char*)buffer.PeekPut();
if ( !ImageLoader::ConvertImageFormat( pImageData, srcFormat, pDst, dstFormat, width, height ) )
return false;
buffer.SeekPut( CUtlBuffer::SEEK_CURRENT, nSizeInBytes );
return true;
}
bool WriteDummyFileNoAlloc( const char *fileName, int width, int height, enum ImageFormat dstFormat )
{
TGAHeader_t tgaHeader;
Assert( g_pFullFileSystem );
if( !g_pFullFileSystem )
{
return false;
}
COutputFile fp( fileName );
int nBytesPerPixel, nImageType, nPixelSize;
switch( dstFormat )
{
case IMAGE_FORMAT_BGR888:
#if defined( _X360 )
case IMAGE_FORMAT_LINEAR_BGR888:
#endif
nBytesPerPixel = 3; // 24/32 bit uncompressed TGA
nPixelSize = 24;
nImageType = 2;
break;
case IMAGE_FORMAT_BGRA8888:
nBytesPerPixel = 4; // 24/32 bit uncompressed TGA
nPixelSize = 32;
nImageType = 2;
break;
case IMAGE_FORMAT_I8:
nBytesPerPixel = 1; // 8 bit uncompressed TGA
nPixelSize = 8;
nImageType = 1;
break;
default:
return false;
break;
}
memset( &tgaHeader, 0, sizeof(tgaHeader) );
tgaHeader.id_length = 0;
tgaHeader.image_type = (unsigned char) nImageType;
tgaHeader.width = (unsigned short) width;
tgaHeader.height = (unsigned short) height;
tgaHeader.pixel_size = (unsigned char) nPixelSize;
tgaHeader.attributes = 0x20;
// Write the Targa header
fp.Write( &tgaHeader, sizeof(TGAHeader_t) );
// Write out width * height black pixels
unsigned char black[4] = { 0x00, 0x00, 0x00, 0x00 }; // Valve Orange would be: { 0x1E, 0x9A, 0xFF, 0x00 }
for (int i = 0; i < width * height; i++)
{
fp.Write( black, nBytesPerPixel );
}
return true;
}
bool WriteTGAFile( const char *fileName, int width, int height, enum ImageFormat srcFormat, uint8 const *srcData, int nStride )
{
TGAHeader_t tgaHeader;
COutputFile fp( fileName );
int nBytesPerPixel, nImageType, nPixelSize;
bool bMustConvert = false;
ImageFormat dstFormat = srcFormat;
switch( srcFormat )
{
case IMAGE_FORMAT_BGR888:
#if defined( _X360 )
case IMAGE_FORMAT_LINEAR_BGR888:
#endif
nBytesPerPixel = 3; // 24/32 bit uncompressed TGA
nPixelSize = 24;
nImageType = 2;
break;
case IMAGE_FORMAT_BGRA8888:
nBytesPerPixel = 4; // 24/32 bit uncompressed TGA
nPixelSize = 32;
nImageType = 2;
break;
case IMAGE_FORMAT_RGBA8888:
bMustConvert = true;
dstFormat = IMAGE_FORMAT_BGRA8888;
nBytesPerPixel = 4; // 24/32 bit uncompressed TGA
nPixelSize = 32;
nImageType = 2;
break;
case IMAGE_FORMAT_I8:
nBytesPerPixel = 1; // 8 bit uncompressed TGA
nPixelSize = 8;
nImageType = 1;
break;
default:
return false;
break;
}
memset( &tgaHeader, 0, sizeof(tgaHeader) );
tgaHeader.id_length = 0;
tgaHeader.image_type = (unsigned char) nImageType;
tgaHeader.width = (unsigned short) width;
tgaHeader.height = (unsigned short) height;
tgaHeader.pixel_size = (unsigned char) nPixelSize;
tgaHeader.attributes = 0x20;
// Write the Targa header
fp.Write( &tgaHeader, sizeof(TGAHeader_t) );
// Write out image data
if ( bMustConvert )
{
uint8 *pLineBuf = new uint8[ nBytesPerPixel * width ];
while( height-- )
{
ImageLoader::ConvertImageFormat( srcData, srcFormat, pLineBuf, dstFormat, width, 1 );
fp.Write( pLineBuf, nBytesPerPixel * width );
srcData += nStride;
}
delete[] pLineBuf;
}
else
{
while( height-- )
{
fp.Write( srcData, nBytesPerPixel * width );
srcData += nStride;
}
}
return true;
}
// This routine writes into a width x height subrect of an existing file at the offset ( nXOrigin, nYOrigin ) where the target image has a stride of nStride
bool WriteRectNoAlloc( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height, int nStride, enum ImageFormat srcFormat )
{
Assert( g_pFullFileSystem );
if( !g_pFullFileSystem )
{
return false;
}
FileHandle_t fp;
fp = g_pFullFileSystem->Open( fileName, "r+b" );
// Read in the targa header
TGAHeader_t tgaHeader;
g_pFullFileSystem->Read( &tgaHeader, sizeof(tgaHeader), fp );
int nBytesPerPixel, nImageType, nPixelSize;
switch( srcFormat )
{
case IMAGE_FORMAT_BGR888:
#if defined( _X360 )
case IMAGE_FORMAT_LINEAR_BGR888:
#endif
nBytesPerPixel = 3; // 24/32 bit uncompressed TGA
nPixelSize = 24;
nImageType = 2;
break;
case IMAGE_FORMAT_BGRA8888:
nBytesPerPixel = 4; // 24/32 bit uncompressed TGA
nPixelSize = 32;
nImageType = 2;
break;
case IMAGE_FORMAT_I8:
nBytesPerPixel = 1; // 8 bit uncompressed TGA
nPixelSize = 8;
nImageType = 1;
break;
default:
return false;
break;
}
// Verify src data matches the targa we're going to write into
if ( nPixelSize != tgaHeader.pixel_size )
{
Warning( "TGA doesn't match source data.\n" );
return false;
}
// Seek to the origin of the target subrect from the beginning of the file
g_pFullFileSystem->Seek( fp, nBytesPerPixel * (tgaHeader.width * nYOrigin + nXOrigin), FILESYSTEM_SEEK_CURRENT );
unsigned char *pSrc = pImageData;
// Run through each scanline of the incoming rect
for (int row=0; row < height; row++ )
{
g_pFullFileSystem->Write( pSrc, nBytesPerPixel * width, fp );
// Advance src pointer to next scanline
pSrc += nBytesPerPixel * nStride;
// Seek ahead in the file
g_pFullFileSystem->Seek( fp, nBytesPerPixel * ( tgaHeader.width - width ), FILESYSTEM_SEEK_CURRENT );
}
g_pFullFileSystem->Close( fp );
return true;
}
// Returns weight for Source pixel based on its position in the guardbanded source tile
static float GetSrcWeight( int nFileY, int nFileX, int nFileHeight, int nFileWidth,
int nRow, int nCol, int nHeight, int nWidth, int nGuardBandHeight, int nGuardBandWidth )
{
float flXWeight = 1.0f;
float flYWeight = 1.0f;
if ( nFileX < nGuardBandWidth ) // Left edge of file doesn't feather in X
{
flXWeight = 1.0f;
}
else if ( nFileX > ( nFileWidth - nGuardBandWidth ) ) // Right edge of file doesn't feather in X
{
flXWeight = 1.0f;
}
else if ( nCol < 2*nGuardBandWidth ) // Left guardband
{
flXWeight = nCol / ( (float) nGuardBandWidth * 2.0f );
}
else if ( nCol > nWidth ) // Right guardband
{
flXWeight = 1.0f - ( ( nCol - nWidth ) / ( (float) nGuardBandWidth * 2.0f ) );
}
if ( nFileY < nGuardBandHeight ) // Top edge of file doesn't feather in Y
{
flYWeight = 1.0f;
}
else if ( nFileY > ( nFileHeight - nGuardBandHeight ) ) // Bottom edge of file doesn't feather in Y
{
flYWeight = 1.0f;
}
else if ( nRow < 2*nGuardBandHeight ) // Top guardband
{
flYWeight = nRow / ( (float) nGuardBandHeight * 2.0f );
}
else if ( nRow > nHeight ) // Bottom guardband
{
flYWeight = 1.0f - ( ( nRow - nHeight ) / ( (float) nGuardBandHeight * 2.0f ) );
}
float flWeight = flXWeight * flYWeight;
Assert( ( flWeight >= 0 ) && ( flWeight <= 1.0f ) );
return flWeight;
}
// This flavor of this routine also writes a subrect into an existing file, but it feathers in a ( nGuardBandWidth, nGuardBandHeight ) border,
bool WriteRectNoAllocFeather( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height,
int nGuardBandWidth, int nGuardBandHeight, int nStride, enum ImageFormat srcFormat )
{
Assert( g_pFullFileSystem );
if( !g_pFullFileSystem )
return false;
FileHandle_t fp;
fp = g_pFullFileSystem->Open( fileName, "r+b" );
// Read in the targa header
TGAHeader_t tgaHeader;
g_pFullFileSystem->Read( &tgaHeader, sizeof(tgaHeader), fp );
int nBytesPerPixel, nImageType, nPixelSize;
switch( srcFormat )
{
case IMAGE_FORMAT_BGR888:
#if defined( _X360 )
case IMAGE_FORMAT_LINEAR_BGR888:
#endif
nBytesPerPixel = 3; // 24/32 bit uncompressed TGA
nPixelSize = 24;
nImageType = 2;
break;
case IMAGE_FORMAT_BGRA8888:
nBytesPerPixel = 4; // 24/32 bit uncompressed TGA
nPixelSize = 32;
nImageType = 2;
break;
case IMAGE_FORMAT_I8:
nBytesPerPixel = 1; // 8 bit uncompressed TGA
nPixelSize = 8;
nImageType = 1;
break;
default:
return false;
break;
}
// Verify src data matches the targa we're going to write into
if ( nPixelSize != tgaHeader.pixel_size )
{
Warning( "TGA doesn't match source data.\n" );
return false;
}
// Run through each scanline of the incoming tile, including guardbands
for ( int row=0; row < ( height + 2*nGuardBandHeight ) ; row++ )
{
// Point to start of row
unsigned char *pSrc = pImageData + ( row * nBytesPerPixel * nStride );
unsigned char filePixel[4] = { 0, 0, 0, 0 };
// Run through each column of the incoming tile, including guardbands
for ( int col=0; col < ( width + 2*nGuardBandWidth ) ; col++ )
{
// Pixel location in the file
int fileX = nXOrigin - nGuardBandWidth + col;
int fileY = nYOrigin - nGuardBandHeight + row;
// If we're within the limits of the file's image
if ( ( fileX >= 0 ) && ( fileY >= 0 ) && ( fileX < tgaHeader.width ) && ( fileY < tgaHeader.height ) )
{
// Always just seek from the head of the file to the pixel in question and read it in
g_pFullFileSystem->Seek( fp, sizeof(tgaHeader) + nBytesPerPixel * ( tgaHeader.width * fileY + fileX ), FILESYSTEM_SEEK_HEAD );
g_pFullFileSystem->Read( filePixel, 3, fp ); // Just read B, G, R bytes
// Add weighted src pixel to the data from the file (which should be initialized to be black at start of day)
float flWeight = GetSrcWeight( fileY, fileX, tgaHeader.height, tgaHeader.width, row, col, height, width, nGuardBandHeight, nGuardBandWidth );
filePixel[0] = (int) ( flWeight * (float)pSrc[0] + (float)filePixel[0] );
filePixel[1] = (int) ( flWeight * (float)pSrc[1] + (float)filePixel[1] );
filePixel[2] = (int) ( flWeight * (float)pSrc[2] + (float)filePixel[2] );
// Jump back to start of current pixel and write over it
g_pFullFileSystem->Seek( fp, -3, FILESYSTEM_SEEK_CURRENT );
g_pFullFileSystem->Write( filePixel, nBytesPerPixel, fp );
}
// Advance src pointer to next column
pSrc += nBytesPerPixel;
}
}
g_pFullFileSystem->Close( fp );
return true;
}
} // end namespace TGAWriter

2
bitmap/vsi.nul Normal file
View File

@ -0,0 +1,2 @@
SN Visual Studio Integration
IMPORTANT: Do not remove the custom build step for this file

View File

@ -0,0 +1,40 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\bonesetup\bone_constraints.cpp
Debug output file: F:\csgo_64\cstrike15_src\bonesetup\bone_constraints.cpp
Release output file: F:\csgo_64\cstrike15_src\bonesetup\bone_constraints.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bonesetup\bone_decode.cpp
Debug output file: F:\csgo_64\cstrike15_src\bonesetup\bone_decode.cpp
Release output file: F:\csgo_64\cstrike15_src\bonesetup\bone_decode.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bonesetup\bone_ik.cpp
Debug output file: F:\csgo_64\cstrike15_src\bonesetup\bone_ik.cpp
Release output file: F:\csgo_64\cstrike15_src\bonesetup\bone_ik.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bonesetup\bone_setup.cpp
Debug output file: F:\csgo_64\cstrike15_src\bonesetup\bone_setup.cpp
Release output file: F:\csgo_64\cstrike15_src\bonesetup\bone_setup.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\bonesetup\bone_utils.cpp
Debug output file: F:\csgo_64\cstrike15_src\bonesetup\bone_utils.cpp
Release output file: F:\csgo_64\cstrike15_src\bonesetup\bone_utils.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:

View File

@ -0,0 +1,898 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// Routines used for various prodcedural bones but meant to be called from
// datamodel or maya as well
//
// In a separate source file so linking bonesetup.lib doesn't get more than
// needed
//
//===============================================================================
// Valve includes
#include "mathlib/mathlib.h"
#include "mathlib/vector.h"
#include "tier1/strtools.h"
#include "bone_setup.h"
#include "bone_constraints.h"
#include "bone_accessor.h"
#include "studio.h"
#include "tier0/tslist.h"
#include "tier0/miniprofiler.h"
#include "bone_utils.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//=============================================================================
//=============================================================================
//
// CConstraintBones
//
//=============================================================================
//=============================================================================
//-----------------------------------------------------------------------------
// Compute the aggregate target position and orientation from the weighted target list and return
// the resulting position and orientation in addition to updating the target dag.
// All passed arrays must be nTargetCount in length
//-----------------------------------------------------------------------------
float CConstraintBones::ComputeTargetPosition(
Vector &vTargetPosition,
int nTargetCount,
float *flTargetWeights,
Vector *vTargetPositions,
Vector *vTargetOffsets )
{
vTargetPosition = vec3_origin;
float flWeightSum = 0.0;
for ( int i = 0; i < nTargetCount; ++i )
{
vTargetPosition += ( flTargetWeights[i] * ( vTargetPositions[i] + vTargetOffsets[i] ) );
flWeightSum += flTargetWeights[i];
}
if ( flWeightSum > 0.0f )
{
vTargetPosition *= 1.0f / flWeightSum;
}
return MIN( 1.0f, flWeightSum );
}
//-----------------------------------------------------------------------------
// Compute the aggregate target orientation from the weighted target list and
// return the total weight
// All passed arrays must be nTargetCount in length
//-----------------------------------------------------------------------------
float CConstraintBones::ComputeTargetOrientation(
Quaternion &qTargetOrientation,
int nTargetCount,
float *pflTargetWeights,
Quaternion *pqTargetOrientations,
Quaternion *pqTargetOffsets )
{
// If there is only one target, for efficiency don't bother with the weighting
if ( nTargetCount == 1 )
{
QuaternionMult( pqTargetOrientations[0], pqTargetOffsets[0], qTargetOrientation );
return MIN( 1.0f, pflTargetWeights[0] );
}
qTargetOrientation = quat_identity;
// If no targets, return identity quaternion and weight of 0
if ( nTargetCount <= 0 )
return 0.0f;
Quaternion *pQuats = reinterpret_cast< Quaternion * >( stackalloc( nTargetCount * sizeof( Quaternion ) ) );
float flWeightSum = 0.0f;
for ( int i = 0; i < nTargetCount; ++i )
{
QuaternionMult( pqTargetOrientations[i], pqTargetOffsets[i], pQuats[i] );
flWeightSum += pflTargetWeights[i];
}
QuaternionAverageExponential( qTargetOrientation, nTargetCount, pQuats, pflTargetWeights );
return MIN( 1.0f, flWeightSum );
}
//-----------------------------------------------------------------------------
// Compute the aggregate target position and orientation from the weighted
// target list and return the total weight
// All passed arrays must be nTargetCount in length
//-----------------------------------------------------------------------------
float CConstraintBones::ComputeTargetPositionOrientation(
Vector &vTargetPosition,
Quaternion &qTargetOrientation,
int nTargetCount,
float *pflTargetWeights,
Vector *pvTargetPositions,
Vector *pvTargetOffsets,
Quaternion *pqTargetOrientations,
Quaternion *pqTargetOffsets )
{
Quaternion *pQuats = reinterpret_cast< Quaternion *>( stackalloc( nTargetCount * sizeof( Quaternion ) ) );
float flWeightSum = 0.0f;
vTargetPosition = vec3_origin;
qTargetOrientation = quat_identity;
for ( int i = 0; i < nTargetCount; ++i )
{
float flWeight = pflTargetWeights[i];
matrix3x4a_t mTarget;
AngleMatrix( RadianEuler(pqTargetOrientations[i]), pvTargetPositions[i], mTarget );
matrix3x4a_t mOffset;
AngleMatrix( RadianEuler(pqTargetOffsets[i]), pvTargetOffsets[i], mOffset );
matrix3x4a_t mAbs;
ConcatTransforms( mTarget, mOffset, mAbs );
Vector vPos;
MatrixAngles( mAbs, pQuats[i], vPos );
vTargetPosition += ( flWeight * vPos );
// For normalization
flWeightSum += flWeight;
}
if ( flWeightSum > 0.0f )
{
vTargetPosition *= 1.0f / flWeightSum;
}
QuaternionAverageExponential( qTargetOrientation, nTargetCount, pQuats, pflTargetWeights );
return MIN( 1.0f, flWeightSum );
}
//-----------------------------------------------------------------------------
// Compute the aggregate target position and orientation from the weighted
// target list and return the total weight
// All passed arrays must be nTargetCount in length
//-----------------------------------------------------------------------------
float CConstraintBones::ComputeTargetPositionOrientation(
Vector &vTargetPosition,
Quaternion &qTargetOrientation,
int nTargetCount,
float *pflTargetWeights,
matrix3x4a_t *pmTargets,
matrix3x4a_t *pmOffsets )
{
Quaternion *pQuats = reinterpret_cast< Quaternion *>( stackalloc( nTargetCount * sizeof( Quaternion ) ) );
float flWeightSum = 0.0f;
vTargetPosition = vec3_origin;
qTargetOrientation = quat_identity;
matrix3x4a_t mAbs;
Vector vPos;
for ( int i = 0; i < nTargetCount; ++i )
{
float flWeight = pflTargetWeights[i];
ConcatTransforms( pmTargets[i], pmOffsets[i], mAbs );
MatrixAngles( mAbs, pQuats[i], vPos );
vTargetPosition += ( flWeight * vPos );
// For normalization
flWeightSum += flWeight;
}
if ( flWeightSum > 0.0f )
{
vTargetPosition *= 1.0f / flWeightSum;
}
QuaternionAverageExponential( qTargetOrientation, nTargetCount, pQuats, pflTargetWeights );
return MIN( 1.0f, flWeightSum );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CConstraintBones::ComputeAimConstraintOffset(
Quaternion &qAimOffset,
bool bPreserveOffset,
const Vector &vTargetWorldPos,
const matrix3x4_t &mSlaveParentToWorld,
const Vector &vUp,
const Vector &vSlaveLocalPos,
const Quaternion &qSlaveLocal,
matrix3x4_t *pmUpToWorld,
AimConstraintUpType_t eUpType )
{
if ( !bPreserveOffset )
{
qAimOffset = quat_identity;
return;
}
// Calculate the desired orientation based the target position
Quaternion qAim;
ComputeAimConstraint( qAim, vTargetWorldPos, mSlaveParentToWorld, vUp, vSlaveLocalPos, pmUpToWorld, eUpType );
// Compute the difference between the slave's current orientation and the target orientation
Quaternion qAimInv;
QuaternionInvert( qAim, qAimInv );
QuaternionMult( qAimInv, qSlaveLocal, qAimOffset );
RadianEuler eAim(qAim);
RadianEuler eSlaveLocal(qSlaveLocal);
RadianEuler eAimOffset(qAimOffset);
}
//-----------------------------------------------------------------------------
// Calculate the orientation needed to make a transform where the y
// vector of the transform matches the forward vector and the z vector matches
// the up reference vector as closely as possible. The x vector will be in the
// plane defined by using the forward vector as the normal.
//-----------------------------------------------------------------------------
void CConstraintBones::ComputeAimConstraintAimAt(
Quaternion &qAim,
const Vector &vForward,
const Vector &vReferenceUp )
{
Vector vFwd = vForward;
vFwd.NormalizeInPlace();
const float flRatio = DotProduct( vFwd, vReferenceUp );
Vector vUp = vReferenceUp - ( vFwd * flRatio );
vUp.NormalizeInPlace();
Vector vRight = vFwd.Cross( vUp );
vRight.NormalizeInPlace();
const Vector &vX = vRight;
const Vector &vY = vFwd;
const Vector &vZ = vUp;
const float flTr = vX.x + vY.y + vZ.z;
qAim.Init( vY.z - vZ.y , vZ.x - vX.z, vX.y - vY.x, flTr + 1.0f );
const float flRadius = qAim[0] * qAim[0] + qAim[1] * qAim[1] + qAim[2] * qAim[2] + qAim[3] * qAim[3];
if ( flRadius > FLT_EPSILON )
{
QuaternionNormalize( qAim );
}
else
{
matrix3x4_t mRot;
MatrixSetColumn( vX, 0, mRot );
MatrixSetColumn( vY, 1, mRot );
MatrixSetColumn( vZ, 2, mRot );
MatrixQuaternion( mRot, qAim );
}
}
//-----------------------------------------------------------------------------
// Given the various parameters, computes the local vForward & vReferenceUp
// and calls ComputeAimConstraintAimAt
//-----------------------------------------------------------------------------
void CConstraintBones::ComputeAimConstraint(
Quaternion &qAim,
const Vector &vTargetWorldPos,
const matrix3x4_t &mParentToWorld,
const Vector &vUp,
const Vector &vSlaveLocalPos,
const matrix3x4_t *pmUpToWorld,
AimConstraintUpType_t eUpType )
{
matrix3x4_t mWorldToParent;
MatrixInvert( mParentToWorld, mWorldToParent );
// If the up vector is in world space, convert it into local space
Vector vWorldUp;
ComputeWorldUpVector( &vWorldUp, mParentToWorld, vUp, vSlaveLocalPos, pmUpToWorld, eUpType );
Vector vLocalUp;
VectorRotate( vWorldUp, mWorldToParent, vLocalUp );
// Convert the target's world space position into the local space of the slave.
Vector vTargetLocalPos;
VectorTransform( vTargetWorldPos, mWorldToParent, vTargetLocalPos );
// Compute the local space forward vector
Vector vLocalForward = vTargetLocalPos - vSlaveLocalPos;
vLocalForward.NormalizeInPlace();
// Compute the orientation
CConstraintBones::ComputeAimConstraintAimAt( qAim, vLocalForward, vLocalUp );
RadianEuler e(qAim);
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CConstraintBones::ComputeWorldUpVector(
Vector *pvWorldUp,
const matrix3x4_t & mParentToWorld,
const Vector &vUp,
const Vector &vSlaveLocalPos,
const matrix3x4_t *pmUpToWorld,
AimConstraintUpType_t eUpType )
{
switch ( eUpType )
{
case AC_UP_TYPE_VECTOR:
VectorCopy( vUp, *pvWorldUp );
break;
case AC_UP_TYPE_OBJECT:
if ( pmUpToWorld )
{
Vector vUpObjectWorldPos;
MatrixPosition( *pmUpToWorld, vUpObjectWorldPos );
Vector vSlaveWorldPos;
VectorTransform( vSlaveLocalPos, mParentToWorld, vSlaveWorldPos );
VectorSubtract( vUpObjectWorldPos, vSlaveWorldPos, *pvWorldUp );
VectorNormalize( *pvWorldUp );
}
else
{
VectorCopy( vUp, *pvWorldUp );
}
break;
case AC_UP_TYPE_PARENT_ROTATION:
VectorRotate( vUp, mParentToWorld, *pvWorldUp );
break;
default:
case AC_UP_TYPE_OBJECT_ROTATION:
if ( pmUpToWorld )
{
VectorRotate( vUp, *pmUpToWorld, *pvWorldUp );
}
else
{
VectorCopy( vUp, *pvWorldUp );
}
break;
}
}
//=============================================================================
//=============================================================================
//
// CStudioConstraintBones
//
//=============================================================================
//=============================================================================
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
float CStudioConstraintBones::ComputeTargetPosition(
Vector &vTargetPosition,
mstudioconstrainttarget_t *pTargets,
int nTargetCount,
CBoneAccessor &boneToWorld )
{
float *pflTargetWeights = reinterpret_cast< float * >( stackalloc( nTargetCount * sizeof( float ) ) );
Vector *pvTargetPositions = reinterpret_cast< Vector * >( stackalloc( nTargetCount * sizeof( Vector ) ) );
Vector *pvTargetOffsets = reinterpret_cast< Vector * >( stackalloc( nTargetCount * sizeof( Vector ) ) );
mstudioconstrainttarget_t *pTarget;
for ( int i = 0; i < nTargetCount; ++i )
{
pTarget = pTargets + i;
pflTargetWeights[i] = pTarget->m_flWeight;
pvTargetOffsets[i] = pTarget->m_vOffset;
MatrixPosition( boneToWorld.GetBone( pTarget->m_nBone ), pvTargetPositions[i] );
}
return CConstraintBones::ComputeTargetPosition( vTargetPosition, nTargetCount, pflTargetWeights, pvTargetPositions, pvTargetOffsets );
}
//=============================================================================
// CStudioConstraintBones : Studio Interface Functions
//=============================================================================
//-----------------------------------------------------------------------------
// studio interface
//-----------------------------------------------------------------------------
float CStudioConstraintBones::ComputeTargetOrientation(
Quaternion &qTargetOrientation,
mstudioconstrainttarget_t *pTargets,
int nTargetCount,
CBoneAccessor &boneToWorld )
{
float *pflTargetWeights = reinterpret_cast< float * >( stackalloc( nTargetCount * sizeof( float ) ) );
Quaternion *pqTargetOrientations = reinterpret_cast< Quaternion * >( stackalloc( nTargetCount * sizeof( Quaternion ) ) );
Quaternion *pqTargetOffsets = reinterpret_cast< Quaternion * >( stackalloc( nTargetCount * sizeof( Quaternion ) ) );
mstudioconstrainttarget_t *pTarget;
for ( int i = 0; i < nTargetCount; ++i )
{
pTarget = pTargets + i;
pflTargetWeights[i] = pTarget->m_flWeight;
pqTargetOffsets[i] = pTarget->m_qOffset;
MatrixQuaternion( boneToWorld.GetBone( pTarget->m_nBone ), pqTargetOrientations[i] );
}
return CConstraintBones::ComputeTargetOrientation( qTargetOrientation, nTargetCount, pflTargetWeights, pqTargetOrientations, pqTargetOffsets );
}
//-----------------------------------------------------------------------------
// studio interface
//-----------------------------------------------------------------------------
float CStudioConstraintBones::ComputeTargetPositionOrientation(
Vector &vTargetPosition,
Quaternion &qTargetOrientation,
mstudioconstrainttarget_t *pTargets,
int nTargetCount,
CBoneAccessor &boneToWorld )
{
float *pflTargetWeights = reinterpret_cast< float * >( stackalloc( nTargetCount * sizeof( float ) ) );
matrix3x4a_t *pmTargets = reinterpret_cast< matrix3x4a_t * >( stackalloc( nTargetCount * sizeof( matrix3x4a_t ) ) );
matrix3x4a_t *pmOffsets = reinterpret_cast< matrix3x4a_t * >( stackalloc( nTargetCount * sizeof( matrix3x4a_t ) ) );
mstudioconstrainttarget_t *pTarget = pTargets;
for ( int i = 0; i < nTargetCount; ++i, ++pTarget )
{
pflTargetWeights[i] = pTarget->m_flWeight;
QuaternionMatrix( pTarget->m_qOffset, pTarget->m_vOffset, pmOffsets[i] );
pmTargets[i] = boneToWorld.GetBone( pTarget->m_nBone );
}
return CConstraintBones::ComputeTargetPositionOrientation( vTargetPosition, qTargetOrientation, nTargetCount, pflTargetWeights, pmTargets, pmOffsets );
}
//-----------------------------------------------------------------------------
// studio interface
//-----------------------------------------------------------------------------
void CStudioConstraintBones::ComputeBaseWorldMatrix(
matrix3x4a_t &mBaseWorldMatrix,
mstudioconstraintslave_t *pSlave,
CBoneAccessor &boneToWorld,
const CStudioHdr *pStudioHdr,
const matrix3x4_t *pmViewTransform /* = NULL */ )
{
// studiomdl shouldn't create mstudioconstraintslave_t's with invalid bone indices
Assert( pSlave->m_nBone >= 0 && pSlave->m_nBone < MAXSTUDIOBONES );
const int nBoneParent = pStudioHdr->boneParent( pSlave->m_nBone );
if ( nBoneParent < 0 )
{
if ( pmViewTransform )
{
matrix3x4a_t mTmp;
QuaternionMatrix( pSlave->m_qBaseOrientation, pSlave->m_vBasePosition, mTmp );
ConcatTransforms( *pmViewTransform, mTmp, mBaseWorldMatrix );
}
else
{
QuaternionMatrix( pSlave->m_qBaseOrientation, pSlave->m_vBasePosition, mBaseWorldMatrix );
}
}
else
{
matrix3x4a_t mTmp;
QuaternionMatrix( pSlave->m_qBaseOrientation, pSlave->m_vBasePosition, mTmp );
ConcatTransforms( boneToWorld.GetBone( nBoneParent ), mTmp, mBaseWorldMatrix );
}
}
//-----------------------------------------------------------------------------
// studio interface
//-----------------------------------------------------------------------------
void CStudioConstraintBones::ComputePointConstraint(
const mstudiobone_t *pBones,
int nBone,
CBoneAccessor &boneToWorld,
const CStudioHdr *pStudioHdr )
{
BONE_PROFILE_FUNC();
mstudiopointconstraint_t *pProc = ( mstudiopointconstraint_t * )pBones[nBone].pProcedure();
// Calculate the current target position and the total weight
// of the the targets contributing to the target position.
Vector vTargetPosition;
const float flWeight = CStudioConstraintBones::ComputeTargetPosition( vTargetPosition, pProc->pTarget( 0 ), pProc->m_nTargetCount, boneToWorld );
Vector vFinalPosition;
matrix3x4a_t &mBaseWorldMatrix = boneToWorld.GetBoneForWrite( nBone );
CStudioConstraintBones::ComputeBaseWorldMatrix( mBaseWorldMatrix, &( pProc->m_slave ), boneToWorld, pStudioHdr );
// Blend between the target position and the base position using the target weight
if ( flWeight < 1.0f )
{
Vector vBasePosition;
MatrixPosition( mBaseWorldMatrix, vBasePosition );
vFinalPosition = Lerp( flWeight, vBasePosition, vTargetPosition );
}
else
{
vFinalPosition = vTargetPosition;
}
// Update the bone the new position.
PositionMatrix( vFinalPosition, mBaseWorldMatrix );
}
//-----------------------------------------------------------------------------
// studio interface
//-----------------------------------------------------------------------------
void CStudioConstraintBones::ComputeOrientConstraint(
const mstudiobone_t *pBones,
int nBone,
CBoneAccessor &boneToWorld,
const CStudioHdr *pStudioHdr,
const matrix3x4_t *pmViewTransform )
{
BONE_PROFILE_FUNC();
mstudioorientconstraint_t *pProc = ( mstudioorientconstraint_t * )pBones[nBone].pProcedure();
// Calculate the current target position and the total weight
// of the the targets contributing to the target position.
Quaternion qTargetOrientation;
const float flWeight = CStudioConstraintBones::ComputeTargetOrientation( qTargetOrientation, pProc->pTarget( 0 ), pProc->m_nTargetCount, boneToWorld );
// Blend between the target orientation and the base orientation using the target weight
Quaternion qFinalOrientation;
matrix3x4a_t &mBaseWorldMatrix = boneToWorld.GetBoneForWrite( nBone );
CStudioConstraintBones::ComputeBaseWorldMatrix( mBaseWorldMatrix, &( pProc->m_slave ), boneToWorld, pStudioHdr, pmViewTransform );
if ( flWeight < 1.0f )
{
Quaternion qBaseOrientation;
MatrixQuaternion( mBaseWorldMatrix, qBaseOrientation );
QuaternionSlerp( qBaseOrientation, qTargetOrientation, flWeight, qFinalOrientation );
}
else
{
qFinalOrientation = qTargetOrientation;
}
// Quaternion matrix wipes out the translate component
Vector vTmpPosition;
MatrixPosition( mBaseWorldMatrix, vTmpPosition );
QuaternionMatrix( qFinalOrientation, vTmpPosition, mBaseWorldMatrix );
}
//-----------------------------------------------------------------------------
// studio interface
//
// pmViewTransform is for hlmv which modifies the actual parentless bones
// to position things in the viewer
//
// TODO: Split into hlmv and "normal" versions, i.e. hlmv needs ViewTransform
//-----------------------------------------------------------------------------
void CStudioConstraintBones::ComputeAimConstraint(
const mstudiobone_t *pBones,
int nBone,
CBoneAccessor &boneToWorld,
const CStudioHdr *pStudioHdr,
const matrix3x4_t *pmViewTransform,
AimConstraintUpType_t eType )
{
BONE_PROFILE_FUNC();
mstudioaimconstraint_t *pProc = ( mstudioaimconstraint_t * )pBones[nBone].pProcedure();
// Calculate the current target position and the total weight
// of the the targets contributing to the target position.
Vector vTargetPos;
const float flWeight = CStudioConstraintBones::ComputeTargetPosition( vTargetPos, pProc->pTarget( 0 ), pProc->m_nTargetCount, boneToWorld );
Vector vTargetWorldPos;
matrix3x4a_t mSlaveParentToWorld;
const int nParentBone = pBones[nBone].parent;
if ( pmViewTransform )
{
matrix3x4_t mInv;
MatrixInvert( *pmViewTransform, mInv );
VectorTransform( vTargetPos, mInv, vTargetWorldPos );
if ( nParentBone >= 0 )
{
ConcatTransforms( mInv, boneToWorld[nParentBone], mSlaveParentToWorld );
}
else
{
SetIdentityMatrix( mSlaveParentToWorld );
}
}
else
{
VectorCopy( vTargetPos, vTargetWorldPos );
if ( nParentBone >= 0 )
{
MatrixCopy( boneToWorld[nParentBone], mSlaveParentToWorld );
}
else
{
SetIdentityMatrix( mSlaveParentToWorld );
}
}
Quaternion qTargetOrientation;
CConstraintBones::ComputeAimConstraint(
qTargetOrientation,
vTargetWorldPos,
mSlaveParentToWorld,
pProc->m_vUp,
pProc->m_slave.m_vBasePosition,
pProc->m_nUpSpaceTarget >= 0 ? &boneToWorld[ pProc->m_nUpSpaceTarget ] : NULL,
eType );
// Add in initial offset
Quaternion qOffsetOrientation;
QuaternionMult( qTargetOrientation, pProc->m_qAimOffset, qOffsetOrientation );
// Add in parent matrix
Quaternion qParentToWorld;
MatrixQuaternion( mSlaveParentToWorld, qParentToWorld );
Quaternion qTmp;
QuaternionMult( qParentToWorld, qOffsetOrientation, qTmp );
qOffsetOrientation = qTmp;
// Blend between the target orientation and the base orientation using the target weight
Quaternion qFinalOrientation;
matrix3x4a_t &mBaseWorldMatrix = boneToWorld.GetBoneForWrite( nBone );
CStudioConstraintBones::ComputeBaseWorldMatrix( mBaseWorldMatrix, &( pProc->m_slave ), boneToWorld, pStudioHdr, pmViewTransform );
if ( flWeight < 1.0f )
{
Quaternion qBaseOrientation;
MatrixQuaternion( mBaseWorldMatrix, qBaseOrientation );
QuaternionSlerp( qBaseOrientation, qOffsetOrientation, flWeight, qFinalOrientation );
}
else
{
qFinalOrientation = qOffsetOrientation;
}
if ( pmViewTransform )
{
Quaternion qTmp0;
Quaternion qTmp1;
MatrixQuaternion( *pmViewTransform, qTmp0 );
QuaternionMult( qTmp0, qFinalOrientation, qTmp1 );
qFinalOrientation = qTmp1;
}
// Quaternion matrix wipes out the translate component
Vector vTmpPosition;
MatrixPosition( mBaseWorldMatrix, vTmpPosition );
QuaternionMatrix( qFinalOrientation, vTmpPosition, mBaseWorldMatrix );
}
//-----------------------------------------------------------------------------
// studio interface
//-----------------------------------------------------------------------------
void CStudioConstraintBones::ComputeParentConstraint(
const mstudiobone_t *pBones,
int nBone,
CBoneAccessor &boneToWorld,
const CStudioHdr *pStudioHdr )
{
BONE_PROFILE_FUNC();
mstudioorientconstraint_t *pProc = ( mstudioorientconstraint_t * )pBones[nBone].pProcedure();
// Calculate the current target position and the total weight
// of the the targets contributing to the target position.
Vector vTargetPosition;
Quaternion qTargetOrientation;
const float flWeight = CStudioConstraintBones::ComputeTargetPositionOrientation( vTargetPosition, qTargetOrientation, pProc->pTarget( 0 ), pProc->m_nTargetCount, boneToWorld );
// Blend between the target orientation and the base orientation using the target weight
Quaternion qFinalOrientation;
Vector vFinalPosition;
matrix3x4a_t &mBaseWorldMatrix = boneToWorld.GetBoneForWrite( nBone );
CStudioConstraintBones::ComputeBaseWorldMatrix( mBaseWorldMatrix, &( pProc->m_slave ), boneToWorld, pStudioHdr );
if ( flWeight < 1.0f )
{
Vector vBasePosition;
Quaternion qBaseOrientation;
MatrixAngles( mBaseWorldMatrix, qBaseOrientation, vBasePosition );
QuaternionSlerp( qBaseOrientation, qTargetOrientation, flWeight, qFinalOrientation );
VectorLerp( vBasePosition, vTargetPosition, flWeight, vFinalPosition );
}
else
{
qFinalOrientation = qTargetOrientation;
vFinalPosition = vTargetPosition;
}
QuaternionMatrix( qFinalOrientation, vFinalPosition, mBaseWorldMatrix );
}
//-----------------------------------------------------------------------------
//
// Twist bones are bones which take a portion of the rotation around a specified
// axis.
//
// The axis is defined as the vector between a parent and child bone
// The twist bones must also be children of the parent
//
// + parent
// |
// +--+ twist 0.25
// |
// +--+ twist 0.5
// |
// +--+ twist 0.75
// |
// +--+ child
//
// If inverse is false each twist takes a portion of the child rotation around
// the specified axis
//
// If inverse is true each twist takes a portion of the parent rotation around
// the specified axis from a specified reference orientation
//
// All specified matrices & Quaternions are local to the bone, they are not
// worldToBone transformations
//
// pqTwists, pflWeights, pqTwistBinds are all pointers to arrays which must be
// at least nCount in size
//
// This code is called directly from:
// maya, datamodel & CalcProceduralBone/DoTwistBones
//-----------------------------------------------------------------------------
void ComputeTwistBones(
Quaternion *pqTwists,
int nCount,
bool bInverse,
const Vector &vUp,
const Quaternion &qParent,
const matrix3x4_t &mChild,
const Quaternion &qBaseInv,
const float *pflWeights,
const Quaternion *pqTwistBinds )
{
const float flEps = FLT_EPSILON * 10.0f;
const float flEpsSq = flEps * flEps;
Vector vUpRotate;
Vector vLocalTranslation;
Vector vRotatedTranslation;
Quaternion qTmp0;
Quaternion qTmp1;
{
Quaternion qChild;
MatrixAngles( mChild, qChild, vLocalTranslation );
// Check for 0 length translation - perhaps use Vector::IsZero?
if ( vLocalTranslation.LengthSqr() < flEpsSq )
{
// No translation, can't compute rotation axis, do nothing
V_memcpy( pqTwists, pqTwistBinds, nCount * sizeof( Quaternion ) );
return;
}
VectorNormalize( vLocalTranslation );
if ( bInverse )
{
QuaternionMult( qBaseInv, qParent, qTmp0 );
VectorRotate( vUp, qTmp0, vUpRotate );
VectorRotate( vLocalTranslation, qTmp0, vRotatedTranslation );
}
else
{
QuaternionMult( qBaseInv, qChild, qTmp0 );
VectorRotate( vUp, qTmp0, vUpRotate );
VectorRotate( vLocalTranslation, qBaseInv, vRotatedTranslation );
}
}
// If the specified up axis and the rotated translation vector are parallel then quit
if ( 1.0f - FloatMakePositive( DotProduct( vRotatedTranslation, vUp ) ) < flEps )
{
V_memcpy( pqTwists, pqTwistBinds, nCount * sizeof( Quaternion ) );
return;
}
// If the rotated up axis and the rotated translation vector are parallel then quit
if ( 1.0f - FloatMakePositive( DotProduct( vRotatedTranslation, vUpRotate ) ) < flEps )
{
V_memcpy( pqTwists, pqTwistBinds, nCount * sizeof( Quaternion ) );
return;
}
// Project Up (V) & Rotated Up (V) into the plane defined by the
// rotated up vector (N)
//
// U = V - ( V dot N ) N;
//
// U is V projected into plane with normal N
Vector vTmp0;
vTmp0 = vRotatedTranslation;
Vector vUpProject;
vTmp0 *= DotProduct( vUp, vRotatedTranslation );
VectorSubtract( vUp, vTmp0, vUpProject );
VectorNormalize( vUpProject );
vTmp0 = vRotatedTranslation;
Vector vUpRotateProject;
vTmp0 *= DotProduct( vUpRotate, vRotatedTranslation );
VectorSubtract( vUpRotate, vTmp0, vUpRotateProject );
VectorNormalize( vUpRotateProject );
if ( VectorsAreEqual( vUpProject, vUpRotateProject, 0.001 ) )
{
V_memcpy( pqTwists, pqTwistBinds, nCount * sizeof( Quaternion ) );
}
else
{
CrossProduct( vUpProject, vUpRotateProject, vTmp0 );
VectorNormalize( vTmp0 );
const float flDot = DotProduct( vUpProject, vUpRotateProject );
const float flAngle = DotProduct( vTmp0, vRotatedTranslation ) < 0.0f ? -acos( flDot ) : acos( flDot );
AxisAngleQuaternion( vLocalTranslation, RAD2DEG( flAngle ), qTmp0 );
if ( bInverse )
{
for ( int i = 0; i < nCount; ++i )
{
QuaternionScale( qTmp0, pflWeights[i] - 1.0f, qTmp1 );
QuaternionMult( qTmp1, pqTwistBinds[i], pqTwists[i] );
}
}
else
{
for ( int i = 0; i < nCount; ++i )
{
QuaternionScale( qTmp0, pflWeights[i], qTmp1 );
QuaternionMult( qTmp1, pqTwistBinds[i], pqTwists[i] );
}
}
}
}

1681
bonesetup/bone_decode.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2226
bonesetup/bone_ik.cpp Normal file

File diff suppressed because it is too large Load Diff

1509
bonesetup/bone_ik_PS3.cpp Normal file

File diff suppressed because it is too large Load Diff

1559
bonesetup/bone_setup.cpp Normal file

File diff suppressed because it is too large Load Diff

1556
bonesetup/bone_setup_PS3.cpp Normal file

File diff suppressed because it is too large Load Diff

3745
bonesetup/bone_utils.cpp Normal file

File diff suppressed because it is too large Load Diff

91
bonesetup/bone_utils.h Normal file
View File

@ -0,0 +1,91 @@
DLL_IMPORT CLinkedMiniProfiler *g_pPhysicsMiniProfilers;
#if 0
#define BONE_PROFILE(ID) static CLinkedMiniProfiler s_miniprofiler_##ID(#ID, &g_pPhysicsMiniProfilers); \
CMiniProfilerGuard mpguard_##ID(&s_miniprofiler_##ID);
#define BONE_PROFILE_LOOP(ID,COUNT) static CLinkedMiniProfiler s_miniprofiler_##ID(#ID, &g_pPhysicsMiniProfilers); \
CMiniProfilerGuard mpguard_##ID(&s_miniprofiler_##ID,(COUNT));
#define BONE_PROFILE_FUNC() static CLinkedMiniProfiler s_miniprofiler_FUNC(__FUNCTION__, &g_pPhysicsMiniProfilers); \
CMiniProfilerGuard mpguard_##ID(&s_miniprofiler_FUNC);
#else
#define BONE_PROFILE(ID)
#define BONE_PROFILE_LOOP(ID,COUNT)
#define BONE_PROFILE_FUNC()
#endif
template <typename T>
class CBoneSetupMemoryPool
{
public:
T *Alloc()
{
T *p = (T *)m_FreeBlocks.Pop();
if ( !p )
{
p = (T *)MemAlloc_AllocAligned( sizeof( T ) * MAXSTUDIOBONES, 16 );
if ( ((size_t)p) % MAX(TSLIST_NODE_ALIGNMENT,16) != 0 )
DebuggerBreak();
}
return p;
}
void Free( T *p )
{
m_FreeBlocks.Push( (TSLNodeBase_t *)p );
}
private:
CTSListBase m_FreeBlocks;
};
extern CBoneSetupMemoryPool<BoneQuaternionAligned> g_QuaternionPool;
extern CBoneSetupMemoryPool<BoneVector> g_VectorPool;
extern CBoneSetupMemoryPool<matrix3x4a_t> g_MatrixPool;
void CalcDecompressedAnimation( const mstudiocompressedikerror_t *pCompressed, int iFrame, float fraq, BoneVector &pos, BoneQuaternion &q );
void QuaternionAccumulate( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt );
void CalcAnimation( const CStudioHdr *pStudioHdr, BoneVector *pos, BoneQuaternion *q, mstudioseqdesc_t &seqdesc, int sequence, int animation, float cycle, int boneMask );
void BlendBones( const CStudioHdr *pStudioHdr, BoneQuaternionAligned q1[MAXSTUDIOBONES], BoneVector pos1[MAXSTUDIOBONES], mstudioseqdesc_t &seqdesc, int sequence, const BoneQuaternionAligned q2[MAXSTUDIOBONES], const BoneVector pos2[MAXSTUDIOBONES], float s, int boneMask );
void ScaleBones( const CStudioHdr *pStudioHdr, BoneQuaternion q1[MAXSTUDIOBONES], BoneVector pos1[MAXSTUDIOBONES], int sequence, float s, int boneMask );
void CalcPose( const CStudioHdr *pStudioHdr, CIKContext *pIKContext, BoneVector pos[], BoneQuaternionAligned q[], int sequence, float cycle, const float poseParameter[], int boneMask, float flWeight = 1.0f, float flTime = 0.0f );
bool CalcPoseSingle( const CStudioHdr *pStudioHdr, BoneVector pos[], BoneQuaternionAligned q[], mstudioseqdesc_t &seqdesc, int sequence, float cycle, const float poseParameter[], int boneMask, float flTime );
void CalcBoneAdj( const CStudioHdr *pStudioHdr, BoneVector pos[], BoneQuaternion q[], const float controllers[], int boneMask );
void BuildBoneChainPartial(
const CStudioHdr *pStudioHdr,
const matrix3x4_t &rootxform,
const BoneVector pos[],
const BoneQuaternion q[],
int iBone,
matrix3x4_t *pBoneToWorld,
CBoneBitList &boneComputed,
int iRoot );
class CBoneSetup
{
public:
CBoneSetup( const CStudioHdr *pStudioHdr, int boneMask, const float poseParameter[], IPoseDebugger *pPoseDebugger = NULL );
void InitPose( BoneVector pos[], BoneQuaternionAligned q[] );
void AccumulatePose( BoneVector pos[], BoneQuaternion q[], int sequence, float cycle, float flWeight, float flTime, CIKContext *pIKContext );
void CalcAutoplaySequences( BoneVector pos[], BoneQuaternion q[], float flRealTime, CIKContext *pIKContext );
private:
void AddSequenceLayers( BoneVector pos[], BoneQuaternion q[], mstudioseqdesc_t &seqdesc, int sequence, float cycle, float flWeight, float flTime, CIKContext *pIKContext );
void AddLocalLayers( BoneVector pos[], BoneQuaternion q[], mstudioseqdesc_t &seqdesc, int sequence, float cycle, float flWeight, float flTime, CIKContext *pIKContext );
public:
const CStudioHdr *m_pStudioHdr;
int m_boneMask;
const float *m_flPoseParameter;
IPoseDebugger *m_pPoseDebugger;
};

2120
bonesetup/bone_utils_PS3.cpp Normal file

File diff suppressed because it is too large Load Diff

359
bonesetup/bone_utils_PS3.h Normal file
View File

@ -0,0 +1,359 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BONE_UTILS_PS3_H
#define BONE_UTILS_PS3_H
#ifndef _PS3
#error "This header is for PS3 target only"
#endif
#include "vjobs_interface.h"
#if defined(__SPU__)
#include "ps3/spu_job_shared.h"
#include "cell/dma.h"
#endif
#if 1
#define DotProduct_PS3 DotProduct
#define MatrixAngles_PS3 MatrixAngles
#define VectorRotate_PS3 VectorRotate
#define VectorSubtract_PS3 VectorSubtract
#define MatrixPosition_PS3 MatrixPosition
#define _VMX_VectorNormalize_PS3 _VMX_VectorNormalize
#define VectorNormalize_PS3 VectorNormalize
#define VectorMultiply_PS3 VectorMultiply
#define VectorScale_PS3 VectorScale
#define VectorMAInline_PS3 VectorMAInline
#define VectorMA_PS3 VectorMA
#define SimpleSpline_PS3 SimpleSpline
#define ConcatTransforms_PS3 ConcatTransforms
#define ConcatTransforms_Aligned_PS3 ConcatTransforms_Aligned
//#define QuaternionMatrix_PS3 QuaternionMatrix
//#define QuaternionAlign_PS3 QuaternionAlign
//#define QuaternionSlerp_PS3 QuaternionSlerp
//#define QuaternionSlerpNoAlign_PS3 QuaternionSlerpNoAlign
//#define QuaternionNormalize_PS3 QuaternionNormalize
//#define QuaternionBlend_PS3 QuaternionBlend
//#define QuaternionBlendNoAlign_PS3 QuaternionBlendNoAlign
//#define QuaternionIdentityBlend_PS3 QuaternionIdentityBlend
//#define QuaternionScale_PS3 QuaternionScale
//#define QuaternionAdd_PS3 QuaternionAdd
//#define QuaternionDotProduct_PS3 QuaternionDotProduct
//#define QuaternionMult_PS3 QuaternionMult
#define MatrixSetColumn_PS3 MatrixSetColumn
#define MatrixGetColumn_PS3 MatrixGetColumn
#define MatrixInvert_PS3 MatrixInvert
#define VectorRotate_PS3 VectorRotate
#define AngleMatrix_PS3 AngleMatrix
#define AngleQuaternion_PS3 AngleQuaternion
#define Hermite_Spline_PS3 Hermite_Spline
#define Hermite_SplineBasis_PS3 Hermite_SplineBasis
#define SetIdentityMatrix_PS3 SetIdentityMatrix
FORCEINLINE Vector Lerp_PS3( float flPercent, Vector const &A, Vector const &B )
{
return A + (B - A) * flPercent;
}
#endif
// from mathlib.h, mathlib_base.cpp
#if 0
FORCEINLINE float DotProduct_PS3(const Vector& a, const Vector& b)
{
// return( a.x*b.x + a.y*b.y + a.z*b.z );
return a.Dot(b);
}
FORCEINLINE float DotProduct_PS3(const float* a, const float* b)
{
return( a[0]*b[0] + a[1]*b[1] + a[2]*b[2] );
}
void ConcatTransforms_PS3( const matrix3x4a_t &m0, const matrix3x4a_t &m1, matrix3x4a_t &out );
void ConcatTransforms_Aligned_PS3( const matrix3x4a_t &m0, const matrix3x4a_t &m1, matrix3x4a_t &out );
void MatrixAngles_PS3( const matrix3x4_t & matrix, float *angles ); // !!!!
void MatrixAngles_PS3( const matrix3x4_t& matrix, RadianEuler &angles, Vector &position );
void MatrixAngles_PS3( const matrix3x4_t &matrix, Quaternion &q, Vector &pos );
inline void MatrixAngles_PS3( const matrix3x4_t &matrix, RadianEuler &angles )
{
MatrixAngles_PS3( matrix, &angles.x );
angles.Init( DEG2RAD( angles.z ), DEG2RAD( angles.x ), DEG2RAD( angles.y ) );
}
void MatrixGetColumn_PS3( const matrix3x4_t& in, int column, Vector &out );
void MatrixSetColumn_PS3( const Vector &in, int column, matrix3x4_t& out );
void MatrixInvert_PS3( const matrix3x4_t& in, matrix3x4_t& out );
void VectorRotate_PS3( const float *in1, const matrix3x4_t & in2, float *out);
inline void VectorRotate_PS3( const Vector& in1, const matrix3x4_t &in2, Vector &out)
{
VectorRotate_PS3( &in1.x, in2, &out.x );
}
FORCEINLINE void VectorSubtract_PS3( const Vector& a, const Vector& b, Vector& c )
{
c.x = a.x - b.x;
c.y = a.y - b.y;
c.z = a.z - b.z;
}
inline void MatrixPosition_PS3( const matrix3x4_t &matrix, Vector &position )
{
position[0] = matrix[0][3];
position[1] = matrix[1][3];
position[2] = matrix[2][3];
}
FORCEINLINE float _VMX_VectorNormalize_PS3( Vector &vec )
{
vec_float4 vIn;
vec_float4 v0, v1;
vector unsigned char permMask;
v0 = vec_ld( 0, vec.Base() );
permMask = vec_lvsl( 0, vec.Base() );
v1 = vec_ld( 11, vec.Base() );
vIn = vec_perm(v0, v1, permMask);
float mag = vmathV3Length((VmathVector3 *)&vIn);
float den = 1.f / (mag + FLT_EPSILON );
vec.x *= den;
vec.y *= den;
vec.z *= den;
return mag;
}
FORCEINLINE float VectorNormalize_PS3( Vector& v )
{
return _VMX_VectorNormalize_PS3( v );
}
FORCEINLINE void VectorMultiply_PS3( const Vector& a, float b, Vector& c )
{
c.x = a.x * b;
c.y = a.y * b;
c.z = a.z * b;
}
FORCEINLINE void VectorMultiply_PS3( const Vector& a, const Vector& b, Vector& c )
{
c.x = a.x * b.x;
c.y = a.y * b.y;
c.z = a.z * b.z;
}
inline void VectorScale_PS3 ( const Vector& in, float scale, Vector& result )
{
VectorMultiply_PS3( in, scale, result );
}
FORCEINLINE Vector Lerp_PS3( float flPercent, Vector const &A, Vector const &B )
{
return A + (B - A) * flPercent;
}
FORCEINLINE void VectorMAInline_PS3( const float* start, float scale, const float* direction, float* dest )
{
dest[0]=start[0]+direction[0]*scale;
dest[1]=start[1]+direction[1]*scale;
dest[2]=start[2]+direction[2]*scale;
}
FORCEINLINE void VectorMAInline_PS3( const Vector& start, float scale, const Vector& direction, Vector& dest )
{
dest.x=start.x+direction.x*scale;
dest.y=start.y+direction.y*scale;
dest.z=start.z+direction.z*scale;
}
FORCEINLINE void VectorMA_PS3( const Vector& start, float scale, const Vector& direction, Vector& dest )
{
VectorMAInline_PS3(start, scale, direction, dest);
}
FORCEINLINE void VectorMA_PS3( const float * start, float scale, const float *direction, float *dest )
{
VectorMAInline_PS3(start, scale, direction, dest);
}
void AngleMatrix_PS3( RadianEuler const &angles, const Vector &position, matrix3x4_t& matrix );
void AngleMatrix_PS3( const RadianEuler& angles, matrix3x4_t& matrix );
void AngleMatrix_PS3( const QAngle &angles, const Vector &position, matrix3x4_t& matrix );
void AngleMatrix_PS3( const QAngle &angles, matrix3x4_t& matrix );
void AngleQuaternion_PS3( const RadianEuler &angles, Quaternion &outQuat );
void Hermite_Spline_PS3( const Vector &p1, const Vector &p2, const Vector &d1, const Vector &d2, float t, Vector& output );
float Hermite_Spline_PS3( float p1, float p2, float d1, float d2, float t );
void Hermite_SplineBasis_PS3( float t, float basis[4] );
void Hermite_Spline_PS3( const Vector &p0, const Vector &p1, const Vector &p2, float t, Vector& output );
float Hermite_Spline_PS3( float p0, float p1, float p2, float t );
void Hermite_Spline_PS3( const Quaternion &q0, const Quaternion &q1, const Quaternion &q2, float t, Quaternion &output );
inline float SimpleSpline_PS3( float value )
{
float valueSquared = value * value;
// Nice little ease-in, ease-out spline-like curve
return (3.0f * valueSquared - 2.0f * valueSquared * value);
}
#endif
void QuaternionMatrix_PS3( const Quaternion &q, const Vector &pos, matrix3x4a_t& matrix );
void QuaternionAlign_PS3( const Quaternion &p, const Quaternion &q, QuaternionAligned &qt );
void QuaternionSlerp_PS3( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
void QuaternionSlerpNoAlign_PS3( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
float QuaternionNormalize_PS3( Quaternion &q );
void QuaternionBlend_PS3( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
void QuaternionBlendNoAlign_PS3( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
void QuaternionIdentityBlend_PS3( const Quaternion &p, float t, Quaternion &qt );
void QuaternionScale_PS3( const Quaternion &p, float t, Quaternion &q );
void QuaternionAdd_PS3( const Quaternion &p, const Quaternion &q, Quaternion &qt );
float QuaternionDotProduct_PS3( const Quaternion &p, const Quaternion &q );
void QuaternionMult_PS3( const Quaternion &p, const Quaternion &q, Quaternion &qt );
void AddDependencies_SPU( bonejob_SPU *pBonejobSPU, accumposeentry_SPU *pPoseEntry, float flWeight = 1.0f );
//void AddDependencies_PPU( CStudioHdr *pHdr, float m_flTime, int m_boneMask, mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, const float poseParameters[], float flWeight );
void GetBoneMapBoneWeight_SPU( bonejob_SPU *pSPUJob, accumposeentry_SPU *pPoseEntry, int *&pLS_boneMap, float *&pLS_boneWeight );
void CalcDecompressedAnimation_PS3( void *pEA_Compressed, const mstudiocompressedikerror_t_PS3 *pLS_Compressed, int iFrame, float fraq, BoneVector &pos, BoneQuaternion &q );
void QuaternionAccumulate_PS3( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt );
void CalcAnimation_PS3( const bonejob_SPU *pBonejob, const accumposeentry_SPU *pPoseEntry, BoneVector *pos, BoneQuaternion *q, const int *boneMap, const float *boneWeight, int animIndex, float cycle, int boneMask );
void BlendBones_PS3( const bonejob_SPU *pBonejob, const accumposeentry_SPU *pPoseEntry, BoneQuaternion *q1, BoneVector *pos1, const int *boneMap, const float *boneWeight, const BoneQuaternion *q2, const BoneVector *pos2, float s, int boneMask );
void ScaleBones_PS3( const bonejob_SPU *pBonejob, const accumposeentry_SPU *pPoseEntry, BoneQuaternion *q1, BoneVector *pos1, const int *boneMap, const float *boneWeight, float s, int boneMask );
// void CalcPose( const CStudioHdr *pStudioHdr, CIKContext *pIKContext, Vector pos[], BoneQuaternion q[], int sequence, float cycle, const float poseParameter[], int boneMask, float flWeight = 1.0f, float flTime = 0.0f );
//bool CalcPoseSingle( const CStudioHdr *pStudioHdr, Vector pos[], BoneQuaternion q[], mstudioseqdesc_t &seqdesc, int sequence, float cycle, const float poseParameter[], int boneMask, float flTime );
// void CalcBoneAdj( const CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], const float controllers[], int boneMask );
void BuildBoneChainPartial_PS3(
const int *pBoneParent,
const matrix3x4a_t &rootxform,
const BoneVector pos[],
const BoneQuaternion q[],
int iBone,
matrix3x4a_t *pBoneToWorld,
CBoneBitList_PS3 &boneComputed,
int iRoot );
struct PS3BoneJobData;
#define BONEJOB_ERROR_EXCEEDEDPQSTACK (1<<0)
#define BONEJOB_ERROR_EXCEEDEDMAXCALLS (1<<1)
#define BONEJOB_ERROR_LOCALHIER (1<<2)
#if !defined(__SPU__)
class CBoneSetup_PS3
{
public:
CBoneSetup_PS3( const CStudioHdr *pStudioHdr, int boneMask, const float poseParameter[], bonejob_SPU *pBoneJobSPU );
void CalcAutoplaySequences_AddPoseCalls( float flRealTime );
void AccumulatePose_AddToBoneJob( bonejob_SPU* pSPUJob, int sequence, float cycle, float flWeight, CIKContext *pIKContext, int pqStackLevel );
int RunAccumulatePoseJobs_PPU( bonejob_SPU *pBoneJob );
int RunAccumulatePoseJobs_SPU( bonejob_SPU *pBoneJob, job_accumpose::JobDescriptor_t *pJobDescriptor );
private:
bool SetAnimData( accumposeentry_SPU *pPoseEntry, const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int sequence, int x, int y, int animIndex, float weight );
bool CalcPoseSingle( accumposeentry_SPU *pPoseEntry, const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int sequence, float cycle, const float poseParameter[], float flTime );
int AddSequenceLayers( bonejob_SPU *pSPUJob, mstudioseqdesc_t &seqdesc, int sequence, float cycle, float flWeight, CIKContext *pIKContext, int pqStackLevel );
int AddLocalLayers( bonejob_SPU *pSPUJob, mstudioseqdesc_t &seqdesc, int sequence, float cycle, float flWeight, CIKContext *pIKContext, int pqStackLevel );
public:
const CStudioHdr *m_pStudioHdr;
int m_boneMask;
const float *m_flPoseParameter;
bonejob_SPU *m_pBoneJobSPU;
int m_errorFlags; // accpose call failure flags (if so do not run on SPU, could be for a number of reasons, right now => exceeded PQ stack, or an anim uses the local hierarchy path
};
#endif // #if !defined(__SPU__)
//-------------------------------------------------------------------------------------------------------------
// SPU dummy funcs
//-------------------------------------------------------------------------------------------------------------
#define DMATAG_ANIM_SYNC_BONEMAPWEIGHT (DMATAG_ANIM+1)
#define DMATAG_ANIM_SYNC_POSQ (DMATAG_ANIM+2)
FORCEINLINE void *SPUmemcpy_UnalignedGet( void *ls, uint32 ea, uint32_t size )
{
void *aligned_ls;
aligned_ls = (void *)((uint32)ls | (ea & 0xf)); // + 0xf in case ls not 16B aligned
#if defined(__SPU__)
//spu_printf("GET ls:0x%x, ea:0x%x, size:%d\n", (uint32_t)aligned_ls, ea, size);
// SPU
cellDmaUnalignedGet( aligned_ls, ea, size, DMATAG_SYNC, 0, 0 );
cellDmaWaitTagStatusAny( 1 << DMATAG_SYNC );
#else
// PPU
memcpy( aligned_ls, (void *)ea, size );
#endif
return aligned_ls;
}
FORCEINLINE void *SPUmemcpy_UnalignedGet_MustSync( void *ls, uint32 ea, uint32_t size, uint32_t dmatag )
{
void *aligned_ls;
aligned_ls = (void *)((uint32)ls | (ea & 0xf)); // + 0xf in case ls not 16B aligned
#if defined(__SPU__)
//spu_printf("GET ls:0x%x, ea:0x%x, size:%d\n", (uint32_t)aligned_ls, ea, size);
// SPU
cellDmaUnalignedGet( aligned_ls, ea, size, dmatag, 0, 0 );
#else
// PPU
memcpy( aligned_ls, (void *)ea, size );
#endif
return aligned_ls;
}
FORCEINLINE void SPUmemcpy_Sync( uint32_t dmatag )
{
#if defined(__SPU__)
// cellDmaWaitTagStatusAll( 1 << dmatag );
cellDmaWaitTagStatusAll( dmatag );
#endif
}
FORCEINLINE void SPUmemcpy_UnalignedPut( void *ls, uint32 ea, uint32_t size )
{
#if defined(__SPU__)
//spu_printf("PUT ls:0x%x, ea:0x%x, size:%d\n", (uint32_t)ls, ea, size);
// SPU
cellDmaUnalignedPut( ls, ea, size, DMATAG_SYNC, 0, 0 );
cellDmaWaitTagStatusAny( 1 << DMATAG_SYNC );
#else
Assert(((uint32)ls&0xf) == ea&0xf);
// PPU
memcpy( (void *)ea, ls, size );
#endif
}
//=============================================================================//
//
//
//
//
//
//=============================================================================//
#endif

47
bonesetup/bonesetup.vpc Normal file
View File

@ -0,0 +1,47 @@
//-----------------------------------------------------------------------------
// MATHLIB.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;..\public"
}
}
$Project "bonesetup"
{
$Folder "Source Files"
{
$File "bone_setup_PS3.cpp" [$PS3]
$File "bone_ik_PS3.cpp" [$PS3]
$File "bone_utils_PS3.cpp" [$PS3]
$File "bone_decode_PS3.cpp" [$PS3]
$File "bone_setup.cpp"
$File "bone_ik.cpp"
$File "bone_utils.cpp"
$File "bone_decode.cpp"
$File "bone_constraints.cpp"
}
$Folder "Header Files"
{
$File "bone_utils.h"
$File "bone_utils_PS3.h" [$PS3]
}
$Folder "Public Header Files"
{
$File "$SRCDIR\public\bone_setup.h" [$WINDOWS||$POSIX]
$File "$SRCDIR\public\bone_setup_PS3.h" [$PS3]
}
}

View File

@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "bonesetup.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "bonesetup.vcxproj"
"1" "bonesetup.vcxproj.filters"
}
}
}

2
bonesetup/vsi.nul Normal file
View File

@ -0,0 +1,2 @@
SN Visual Studio Integration
IMPORTANT: Do not remove the custom build step for this file

View File

@ -0,0 +1,40 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\game\shared\choreoactor.cpp
Debug output file: F:\csgo_64\cstrike15_src\game\shared\choreoactor.cpp
Release output file: F:\csgo_64\cstrike15_src\game\shared\choreoactor.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\game\shared\choreochannel.cpp
Debug output file: F:\csgo_64\cstrike15_src\game\shared\choreochannel.cpp
Release output file: F:\csgo_64\cstrike15_src\game\shared\choreochannel.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\game\shared\choreoevent.cpp
Debug output file: F:\csgo_64\cstrike15_src\game\shared\choreoevent.cpp
Release output file: F:\csgo_64\cstrike15_src\game\shared\choreoevent.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\game\shared\choreoscene.cpp
Debug output file: F:\csgo_64\cstrike15_src\game\shared\choreoscene.cpp
Release output file: F:\csgo_64\cstrike15_src\game\shared\choreoscene.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\game\shared\sceneimage.cpp
Debug output file: F:\csgo_64\cstrike15_src\game\shared\sceneimage.cpp
Release output file: F:\csgo_64\cstrike15_src\game\shared\sceneimage.cpp
Containing unity file:
PCH file:

View File

@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// CHOREOOBJECTS.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;..\game\shared;..\utils\common"
}
}
$Project "choreoobjects"
{
$Folder "Source Files"
{
$File "$SRCDIR\game\shared\choreoactor.cpp"
$File "$SRCDIR\game\shared\choreochannel.cpp"
$File "$SRCDIR\game\shared\choreoevent.cpp"
$File "$SRCDIR\game\shared\choreoscene.cpp"
$File "$SRCDIR\game\shared\sceneimage.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\game\shared\choreoactor.h"
$File "$SRCDIR\game\shared\choreochannel.h"
$File "$SRCDIR\game\shared\choreoevent.h"
$File "$SRCDIR\game\shared\choreoscene.h"
$File "$SRCDIR\game\shared\ichoreoeventcallback.h"
$File "$SRCDIR\game\shared\sceneimage.h"
}
$Folder "Public Header Files"
{
$File "$SRCDIR\public\mathlib\mathlib.h"
$File "$SRCDIR\public\mathlib\vector.h"
$File "$SRCDIR\public\mathlib\vector2d.h"
}
}

View File

@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "choreoobjects.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "choreoobjects.vcxproj"
"1" "choreoobjects.vcxproj.filters"
}
}
}

2
choreoobjects/vsi.nul Normal file
View File

@ -0,0 +1,2 @@
SN Visual Studio Integration
IMPORTANT: Do not remove the custom build step for this file

907
common/CegClient.h Normal file
View File

@ -0,0 +1,907 @@
// Copyright © 2008-, Valve LLC, All rigStahts reserved.
//
// cegclient.h
//
// This file is to be imported by client applications that wish to link with our DRM library !
//
// Performance Note :
//
// There are several points within cegclient.h where we'll place a 'Performance Note' to indicate
// the potential performance consequences of particular CEG functions.
//
//
//
//
// CEG Initialization -
//
// The first and last functions within the CEG SDK that must be called are :
// Steamworks_InitCEGLibrary()
// Steamworks_TermCEGLibrary()
//
// There are alternate versions of these functions, for people who restrict their usage of the
// CEG SDK to a subset of the available API's (more on the subset later). These functions are :
//
// Steamworks_MinimumInitCEGLibrary()
// Steamworks_MinimumTermCEGLibrary().
//
// In the event that the CEG library is initialized through Steamworks_InitCEGLibrary(), then the
// following functions must also be called, on each thread on which CEG code may execute, before any
// other CEG code code executes on the thread (these functions are not necessary if Steamworks_MinimumInitCEGLibrary() is called).
//
// Steamworks_RegisterThread()
// Steamworks_UnRegisterThread().
//
// The only function which can be called before Steamworks_RegisterThread() is Steamworks_InitCEGLibrary().
// Steamworks_RegisterThread() must be called on the thread that calls Steamworks_InitCEGLibrary(), if it calls any
// other CEG functions.
// For example, your main() will probably look like :
//
// int main( int argc, char* argv[] )
// {
// Steamworks_InitCEGLibrary();
// Steamworks_RegisterThread();
//
// /* Real work here */
//
// Steamworks_UnRegisterThread();
// Steamworks_TermCEGLibrary();
// return 0;
// }
//
//
//
// CEG Minimum API :
//
// Steamworks_SimpleCheck()
//
// This API is provided for people who are trying to combine CEG with other DRM technology.
// This function does a very basic check that the machine is executing on the machine it was produced for.
// This function doesn't conceal any of the data it is using to evaluate the machine, and therefore should not be
// used with the full CEG SDK. It it not necessary to call Steamworks_RegisterThread()/Steamworks_UnRegisterThread()
// if CEG API usage is restricted to this function.
//
// CEG Full API's :
//
// The full set of CEG API's takes the form of direct function calls, who's performance impacts may be easily analyzed
// versus macros, which cause sophisticated manipulations of your .obj files before the final executable is linked.
//
//
// Direct Functions Calls -
// Steamworks_TestSecret()
// Steamworks_TestSecretAlways(),
// Steamorks_SelfCheck().
//
// Steamworks_TestSecret() and Steamworks_TestSecretAlways() are focused on evaluating the current
// computer to determine whether it is the machine the binary was produced for.
// Because a hacker may be 'tracing' all windows API calls with a tool such as sysinternal's Process Monitor
// ( http://technet.microsoft.com/en-us/sysinternals/bb896645 ), Steamworks_TestSecret() will not always
// evaluate it's secret. The intention is to make it harder to record CEG activity.
// Steamworks_TestSecretAlways() will always evaluate it's portion of secret data.
//
// Steamworks_SelfCheck() - this function is focused on determining whether the executable has been modified.
//
//
// Macro Mechanisms:
//
// CEG's macro mechanisms attempt to entwine machine specific information into the correct operation of the game
// product. As a result, unlike CEG function calls (which a hacker can simply stub out), a hacker must
// take the time to determine how the CEG code is entwined within the product, and make a more significant effort
// to modify the game.
//
// Specific Macro Mechanisms:
//
// CEG_EncryptFunction()
//
// The function which contains this macro will be modified, so that the opcodes comprising the function
// are encrypted within the executable file. The decryption key is derived from machine specific data.
// If decryption of the code fails, the function will not be executed, and the game will to continue to run.
// Whether the executable immediately terminates or not depends on what the encrypted function does for the game,
// as well as calling convention and architecture issues, as the CEG code may not clean up the stack correctly
// when the function fails to execute.
// (Please note : Many CEG functions are themselves encrypted using this mechanism).
//
// This mechanism can be used an unlimited number of times - the following macros have restrictions on
// the number of times they can be used within your executable.
//
// Performance Note :
// Every time a function containing CEG_EncryptFunction() macro is invoked, CEG code must execute to
// produce the function in a ready to run form in temporarily allocated memory.
// CEG will keep a cached version of the function for up to 10 seconds, so that the full cost of decryption
// is not paid on every invocation. However, every invocation does incur some CEG overhead to
// either decrypt or locate the cached form and to properly martial the call to the decrypted form of the function.
//
//-----------------------------------------
// CEG_ProtectFunction()
//
// The function which contains this macro will be modified, so that it's address must be computed
// by every caller of the function. The address computation will involve machine specific data,
// as well as checksum computations which verify that the executable has not been modified.
//
// This mechanism cannot be used (in conjunction with CEG_Define_Constant_Function) more then 130 times.
//
// Performance Note:
//
// The full cost of the CEG_ProtectFunction() will be paid on every call of the target function.
// Because this mechanism involves computing checksums of the executable image, this will be more
// expensive then CEG_EncryptFunction(). However, this mechanism is much more likely to cause problems
// for somebody who is attacking the executable with a debugger, as the checksums are likely to find
// the breakpoints being used by the debugger.
//
//----------------------------------------
// CEG_Define_Constant_Function( name, value )
// CEG_Declare_Constant_Function( name )
// CEG_GetConstantValue( name )
//
// These macros create and declare a functions that the game can use to get interesting constants
// for game play. (i.e. Field Of View angle, maximum player velocity etc...)
//
// Computation of CEG_GetConstantValue() involves machine specific information as well as checksums
// of the executing binary (same as CEG_ProtectFunction).
// If the machine is different, or the executable has been modified, then the results returned
// by CEG_GetConstantValue() will be different. The results in the game will depend on how
// the constant is used.
//
// The same Performance Note as for CEG_ProtectFunction() apply to this mechanism.
//
//
// Some General Notes on CEG's macro mechanisms:
//
// The Compiler can eliminate CEG_ProtectFunction() and CEG_EncryptFunction() if it chooses to
// inline your function !!! In general, it's better to use these macros only in function which appear in
// .cpp files (not in inline functions which appear in header files). It's also better if the function
// in which CEG_ProtectFunction() or CEG_EncryptFunction() is placed is not called from within the same file!
//
// C++ Constructors and Destructors :
//
// You can use CEG_ProtectFunction() and CEG_EncryptFunction() within your C++ constructors.
// HOWEVER - if there is a global variable that invokes the constructor, you will be invoking
// the CEG mechanisms before you have executed Steamworks_InitCEGLibrary() - and this will probably crash your game.
//
//
//
#ifndef _CEGCLIENT_H_
#define _CEGCLIENT_H_
#pragma once
//
// Many of the CEG functions implement below compute CRC's over the executing image
// of the game when invoked. This results in their performance impact varying with
// the size of the game executable file.
// A typical result for Steamworks_SelfCheck() and CEG_Protect_Member_Function() is
// 3ms of overhead in a 6MB executable. (Measured in L4D2).
//
// In order to allow more fine grain control of which part of the executable is covered
// by CEG CRC's this macro is provided.
//
// Executable code that is placed in this section WILL NOT have any CRC's covering the code.
// To place code in this section on an entire source file basis use '#pragma code_seg( NO_CEG_SECTION )'
// This places all of the code following the pragma into the NO_CEG_SECTION of the executable.
//
// Care should be taken that the marked code cannot be modified to prevent execution of CEG checks.
// Do not put direct CEG call sites into this section, or most of the call stack leading to a CEG call site.
// This can be used to improve the performance of the Steamwork_SelfCheck() and CEG_Protect_Member_Function() mechanisms
// as they will operate on a smaller portion of the game image.
// Do not overuse, as placing all code into such sections would mean that the hackers could easily
// identify CEG library code - which would be the code not in NO_CEG_SECTION.
//
#define NO_CEG_SECTION ".textnc"
//
// This is the result code the DRM library passes to ExitProcess() when it terminates
// a process that requires DRM processing.
//
#define STEAM_PROCESS_TERMINATE_DRM_REQUIRED 0x8000DEAD
//
// This function should be called exactly once by a client application.
// The Steamworks_InitCEGLibrary() and Steamworks_TermCEGLibrary() will let steam know that a game was
// running no matter what mechanism the user used to start the game.
//
extern bool __cdecl Steamworks_InitCEGLibrary() ;
//
// This function should be called exactly once by a client application -
// A client application should call only one of Steamworks_InitCEGLibrary or Steamworks_MinimumInitCEGLibrary() - NOT BOTH!
//
// This function is provided for those applications incorporating additional DRM mechanisms into their application.
// In those cases it may be appropriate to use Steamworks_MinimumInitCEGLibrary().
// Otherwise, Steamworks_InitCEGLibrary() is the interface that should be used.
//
extern bool __cdecl Steamworks_MinimumInitCEGLibrary();
//
// This function should be called exactly once by a client application, immediately
// before it is going to exit the game.
//
extern bool __cdecl Steamworks_TermCEGLibrary() ;
//
// This function pairs with Steamworks_MinimumInitCEGLibrary().
//
extern bool __cdecl Steamworks_MinimumTermCEGLibrary();
//
// This pair of functions must be called on each thread that uses any CEG mechanism.
// Steamworks_RegisterThread() must be called before any CEG mechanism executes on
// the thread, including all of the CEG_Protect_Member* macros.
// Steamworks_UnRegisterThread() must be called AFTER all CEG mechanisms have been
// executed on a particular thread.
//
// IMPORTANT NOTE REGARDING CEG IN MULTIPLE COMPONENTS -
// This Comment ONLY applies if you are using CEG in multiple DLL's (or a .DLL and .EXE)
// which are loaded in the same process.
// If Steamworks_RegisterThread() is called in DLL A, which invokes DLL B which also
// contains CEG code, then DLL B must call Steamworks_RegisterThread() before any CEG
// function within DLL B is executed, and must call Steamworks_UnRegisterThread() before
// it returns to DLL A.
//
// If a thread executes exclusively in DLL A without calling DLL B, then Steamworks_RegisterThread()
// only needs to be called in DLL A.
//
extern bool __cdecl Steamworks_RegisterThread() ;
extern bool __cdecl Steamworks_UnRegisterThread() ;
//
// This function performs the most basic CEG checks for ownership, and makes no attempt
// to conceal it's inner workings, unlike the remaining API's
//
// If bTerminateIfUnowned is non zero then the CEG will crash the process
// and attempt to return STEAM_PROCESS_TERMINATE_DRM_REQUIRED to the steam client.
// The caller may pass zero (false) to the function, and take responsibility for terminating the game.
// This allows the caller to separate the legitimacy test from the enforcement.
// It is very important that the process have an exit code of STEAM_PROCESS_TERMINATE_DRM_REQUIRED
// if this is done - the Steam Client will use that to report CEG errors to Steam
// and to repair a customer installation. This may arise if the customer
// has upgraded their Operating System, in which case the first time the game
// is launched after the upgrade, CEG may fail to identify the system and cause the game to exit.
// In this situation, the steam client will repair the customer's installation before
// the game is launched again.
//
// The variable argument list to the function is ignored by the steam client,
// but may be used to mask the signature of the function.
//
extern bool __cdecl Steamworks_SimpleCheck( DWORD bTerminateIfUnowned, ... );
//
// This function checks to see whether an application has been 'stolen' - it does
// so by examining properties of the system on which we are running and checking if
// those properties match those expected through the encoding we've done into the binary !
//
// IMPORTANT NOTE : This function has internal metering, it does not always perform its
// full check. The goal is to make it more difficult to discover for hackers to locate
// all of these checks.
//
extern bool __cdecl Steamworks_TestSecret() ;
//
// This function performs the same type of checks as Steamworks_TestSecret(), however
// it has no internal metering - it will always perform a check.
//
extern bool __cdecl Steamworks_TestSecretAlways() ;
//
// This function checks to see whether an application has been 'stolen' - it does
// so by examining the PE file (.dll or .exe) in which the DRM library has been linked
// and determines whether the PE file has been modified.
//
extern bool __cdecl Steamworks_SelfCheck() ;
//
// This function takes an interface pointer returned from a steam dll, and verifies
// that it actually references a legitimate steam client.
//
extern bool __cdecl Steamworks_ValidateComponentInterface(void** lpv) ;
//
// By default - we use WinCrypt API's to do signature validation -
// if somebody desires, they can provide their own implementation.
//
class ISignatureImplementation {
public :
virtual bool
VerifyHash(
//
// First - we specify the data structure which has been 'signed' -
// We sign our signature using Wincrypt's PROV_RSA_FULL provider
// with the CALG_SHA1 algorithm.
//
LPBYTE lpbSignedData,
DWORD cbSignedData,
//
// The signature block is generated using
// CryptCreateHash( RSA FULL PROVIDER, CALG_SHA1 ) and CryptHashData().
// The Hash is then signed using CryptSignHash( Hash(), AT_SIGNATURE, .... )
// generating the specified SignatureBlock !
//
LPBYTE lpbSignatureBlock,
DWORD cbSignatureBlock,
//
// The public key associated with the private key that signed the Hash data !
//
LPBYTE lpbPublicKey,
DWORD cbPublicKey
) = 0 ;
} ;
//
// This function checks a signature of all the read-only portions of the executing image.
// Unlike other CEG mechanisms, this uses cryptographic mechanisms that are not easily concealed from reverse engineering.
// Additionally, this is a higher cost mechanism as it involves the entire executing image.
// This check can be used at game launch, (before any user interface is displayed) where it will serve as a stalking horse,
// and occasionally throughout execution.
//
// Additionally, neither of Steamworks_ValidateComponentInterface() or Steamworks_SelfValidate() provide multiple implementations.
// Steamworks_TestSecret(), Steamworks_TestSecretAlways(), Steamworks_SelfCheck() will all be multi-plexed across many distinct
// implementations (this is done by mingle.exe). Additional call sites for Steamworks_SelfValidate() are not as valuable as
// additional call sites for the previously mentioned CEG functions.
//
extern bool __cdecl Steamworks_SelfValidate(ISignatureImplementation* pISignatureImplementation) ;
////////////////////////////////////////////////////
//
// DO NOT CALL THIS FUNCTION !
// This is referenced only through the CEG_Define_Constant_Function
//
typedef DWORD (*PFNSteamworks_ComputeDwordValue)();
extern DWORD __cdecl Steamworks_ComputeDwordValue() ;
//
// DO NOT DO NOT CALL THIS FUNCTION !
//
// This is only referenced indirectly through the CEG_Protect_Virtual_Function macro !
//
extern void* __cdecl Steamworks_ProtectFunction( void*, void* ) ;
//
// DO NOT CALL THIS FUNCTION !
//
// This declaration is used within CEG Concealed function mechanisms to incorporate
// machine specific data into the function concealment mechanism. It's not to be
// directly called.
//
extern void __cdecl Steamworks_GetSecretData( unsigned __int32 /* 32bit unsigned int - all platforms.*/, union _16BYTES_U& );
//
// DO NOT DO NOT CALL THIS FUNCTION !
//
// This function should only be referenced through the CEG_EncryptFunction macro !
//
extern bool __cdecl Steamworks_EncryptedFunctionLoad();
//
// DO NOT DO NOT CALL THIS FUNCTION !
//
// This symbol exists for the benefit of mingle.exe when it processes your .obj files
// and should only appear in the initializers of a CEGProtectedFunction structure !
//
extern void __cdecl Steamworks_InvalidReference() ;
//
// DO NOT CALL THIS FUNCTION - Exists solely for use in macros defined below !
//
// This function exists so we can force optimizing compilers to emit all the CEG
// relevant data, as otherwise the compiler would discard them as unreferenced.
//
extern void __cdecl CEG_ForceReference(const struct CEG_Protection_Thunk&, const char* ) ;
//
// This class is defined purely so we can create derived classes in the CEG_Protect_Member_Function() macro.
// Because that macro must be used within a function, defining a class allows us to generate the necessary
// compiler references to ensure that the compiler does not optimize out CEG functions and symbols.
//
class I_CEG_ForceReference_Interface
{
virtual const CEG_Protection_Thunk* ReferencingFunction(unsigned index) = 0 ;
} ;
////////////////////////////////////////////////////////////////////////////////
// DO NOT CALL THIS FUNCTION - Exists solely for use in macros defined below !
//
// Together with the I_CEG_ForceReference_Interface allows us to force compilation
// of some of our fancy CEG symbols !
//
extern int __cdecl CEG_ForceReference( class I_CEG_ForceReference_Interface* p ) ;
//
//
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// CEG Internal Macros -
//
// The following are not intended for direct use, but will be instantiated
// by CEG_EncryptFunction()/CEG_ProtectFunction()/CEG_GetConstantValue().
//
//
// These handy macros help to generate unique variable names, as well as messages
// through __pragma( message() ) !
//
#define CEG_UNIQNAME2(x,y) x##y
#define CEG_UNIQNAME1(x,y) CEG_UNIQNAME2(x,y)
#define CEG_UNIQNAME(x) CEG_UNIQNAME1(x,__COUNTER__)
#define CEG_STRING(z) #z
#define CEG_LINE_NUMBER(x) CEG_STRING(x)
#if defined( _M_X64 )
#define CEG_UNIQNAME3(x, y) CEG_STRING( x##y )
#else
#define CEG_UNIQNAME3(x, y) CEG_STRING( _##x##y )
#endif
//
// Too bad there's no hexadecimal 'G', F+1 will do
//
#define CEG_PROTECT_SIGNATURE 0xCEF1CEF1
#define CEG_PROTECT_VIRTUAL_SIGNATURE 0xCEF10000
//
// Define various strings used by CEG as section names through __pragma() directives.
//
#if !defined(CEG_PUBLIC_SECTION_STRINGS)
#define CEG_PUBLIC_SECTION_STRINGS
//
// These macros correspond to section names used by CEG.
//
// The following macros will use C++ pragma's to allocate objects into these
// various sections. No direct reference to these macros should be necessary.
//
#define CEG_META_GRAPH_START ".cegm$ga"
#define CEG_META_GRAPH_END ".cegm$gz"
//
// This section will contain the signature tested by the Steamworks_ValidateSelf() interface
//
#define CEG_SIGNATURE_SECTION ".crsig"
//
// This section will contain the data CEG uses to generate the Constant Function mechanisms !
//
#define CEG_EXTERNAL_VALUE ".cegi$d"
#endif
extern DWORD __cdecl Steamworks_RevealFunction( DWORD_PTR, DWORD_PTR );
extern void __cdecl Steamworks_ForceRef( struct CEG_SwapStruct* );
//
// We use this macro to generate identifiers that Mingle may modify.
// In some .obj manipulations, Mingle will change identifiers in the .obj file -
// And will expect the identifiers to be produced by this macro!
//
// NOTE that the __XXXXXXXX will be turned into digits (essentially a counter)
// by mingle !
//
#define Steamworks_CEG_MingleModifiableName_Prefix Steamworks_CEGIdentifier_
#define Steamworks_CEG_MingleModifiableName_Suffix __XXXXXXXX
#define Steamworks_CEG_MingleModifiableName(name) Steamworks_CEGIdentifier_ ## name ## __XXXXXXXX
#define CEG_TEMPLATE_USE_START_SECTION ".cegtu$a"
#define CEG_TEMPLATE_USE_SECTION ".cegtu$m"
#define CEG_TEMPLATE_USE_END_SECTION ".cegtu$z"
//
// Reserve scratch space for the CEG Implementation to cache results!
//
//
struct Steamworks_ThunkFunction_Scratch
{
DWORD m_rgdw[16] ;
};
//
// Identify the version number of the CEG_SwapStruct structure.
//
#define Steamworks_CEG_SwapVersion 1
//
// This mask specifies that the function specified by CEG_SwapStruct should be prepped by mingle
// to have runtime encryption operations applied to it.
//
#define Steamworks_CEG_EncryptSectionMask 1
//
// This mask specifies that the function specified by CEG_SwapStruct should be marked as COMDAT Select
// Associative to the specification section. The select associative option is only used if
// the original section was already COMDAT Select Any (common for templates and inline functions).
// This flag is used by code within the CEG library implementing various secrets - where we want to
// ensure that the target executable file links the absolute minimum amount of stuff, and does not
// pull in any un-necessary objects.
//
#define Steamworks_CEG_SelectAssocMask 2
//
// This is the macro we use to cause the 'consumption' of a template !
//
#define Steamworks_CEG_InvokeTemplate( arg, flags ) \
static char CEG_SwapName_Local[] = __FUNCDNAME__ ; \
__pragma( section(CEG_TEMPLATE_USE_SECTION, read, write) ) \
static CEG_SwapStruct __declspec(align(1)) __declspec(allocate(CEG_TEMPLATE_USE_SECTION)) \
LocalSwap = { \
Steamworks_CEG_SwapVersion, \
CEG_SwapName_Local, \
Steamworks_CEG_MingleModifiableName( arg ), \
flags, NULL, 0, 0 \
} ; \
Steamworks_ForceRef(&LocalSwap)
#define Steamworks_DeclareCEGTemplate( arg ) \
extern DWORD_PTR __cdecl Steamworks_CEG_MingleModifiableName( arg )( DWORD_PTR )
Steamworks_DeclareCEGTemplate( CacheConcealThunk );
Steamworks_DeclareCEGTemplate( ProtectFunction );
#pragma pack(push, 1)
#if !defined(CEG_LINKOBJECT_DEFINED)
#define CEG_LINKOBJECT_DEFINED
//
// The 'ID' of an object identified by mingle - this
// is large enough to be a GUID or an MD5 computation !
//
struct LinkObjectId
{
BYTE m_rgb[16];
};
#endif
struct CEG_SwapStruct {
//
// Tell Mingle what version of this structure the file was compiled with !
//
DWORD_PTR m_Version;
//
// This field is the decorated name of the function that is being manipulated.
// This is generated through the __FUNCDNAME__ preprocessor directive of Visual Studio.
//
char* m_szDecoratedName;
//
// This points to the function that will 'replace' the specified function.
//
void* m_pfnOriginal;
//
// Reserve space in the structure for communication with mingle.exe and
// cegdll.dll regarding the details of what happens to the swapped code !
//
DWORD_PTR m_SectionOptions;
//
// Based on the Section Options, these fields will be interpreted by Mingle and the CEG runtime.
//
void* m_Reserved1;
DWORD_PTR m_Reserved2;
//
// Mingle will give us the size of the Swap Target function, in bytes !
//
DWORD_PTR m_cbTarget;
//
// This is a mingle generated identifier, that will be used by cegdll.dll and drmpe.exe
// to identify the template used and it's associated metadata !
//
LinkObjectId m_LinkObjectId;
};
//
// This structure must have the exact same size as CEG_SwapStruct, and will be the runtime interpretation
// of the structure ! Mingle will modify relocation records so that the final linked form stores 'distances'
// to the actual referenced items instead of pointers. We do this to reduce relocation records in the final
// target executable, which we believe give data structure feedback to hackers.
//
struct CEG_Runtime_SwapStruct {
//
// This field carries the version of the structure.
//
DWORD_PTR m_Version;
//
// This is the 'distance' to the function that Mingle placed into the .obj file.
// This function is called directly instead of the original 'TargetFunction'
//
// Note that 'distances' are stored by mingle.exe using a relocation type that is appropriate for code.
// That means that distances on both 32 and 64bit platforms are 32 bit signed integers -
// However, this field is 64bits on a 64bit platform. The linker will have stored a 32 bit signed
// integer into the field, so we must do appropriate casting, because we don't have a genuine 64 bit signed integer in here.
// When manipulating the structures, we will at a time turn this field into a full 'pointer like' value
// (i.e. during the CEG process) - so it is convenient for us that it can hold that.
//
INT_PTR m_OffsetSubstitute;
//
// NOTE : All the same comments that apply to m_OffsetSubstitute apply to this field !
//
// This is the distance to the 'Target' function - the function containing the Steamworks_CEG_InvokeTemplate macro
// This TargetFunction may be in an encrypted form, depending on the flags specified in m_SectionOptions!
//
INT_PTR m_OffsetOriginal;
//
// These options specify manipulations that mingle will perform on the 'Original' function
// before it is linked. In particular, it may be turned into a 'Concealed' function - which
// is a self-contained data structure containing the functions op-codes and metadata that can
// be encrypted during the CEG process.
//
DWORD_PTR m_SectionOptions;
//
// We allow the macro to request what Encryption thunk is used in the event that the
// Section Options specify
//
DWORD_PTR m_SectionThunk;
//
// For future use ....
//
DWORD_PTR m_Reserved2;
//
// Mingle will give us the size of the Substitute function, in bytes !
// It is usefull to know the Substitute function size - as during runtime we may
// need to 'search' for it.
//
DWORD_PTR m_cbTarget;
//
// This is a mingle generated identifier, that will be used by cegdll.dll and drmpe.exe
// to identify the template used and it's associated metadata !
//
LinkObjectId m_LinkObjectId;
void* GetOriginalFunction() const
{
return reinterpret_cast<void*>(reinterpret_cast<INT_PTR>(&m_OffsetOriginal)+static_cast<INT32>(m_OffsetOriginal)+sizeof(INT32));
}
void* GetSubstituteFunction() const
{
return reinterpret_cast<void*>(reinterpret_cast<INT_PTR>(&m_OffsetSubstitute)+static_cast<INT32>(m_OffsetSubstitute)+sizeof(INT32));
}
};
#pragma pack(pop)
//
// End of CEG Internal Macros -
//
////////////////////////////////////////////////////////////////////////////////
//
// The flowing three macros :
// CEG_Define_Constant_Function( name, value ),
// CEG_Declare_Constant_Function( name ),
// CEG_GetConstantValue( name )
//
// Operate together to provide another CEG mechanism for protecting your binary.
//
// Example usage :
//
// header.h :
// /* macro is at File Scope !*/
// CEG_Declare_Constant_Function( ZombiesPerSecond ) ;
//
// main.cpp :
// /* macro is at File Scope !*/
// CEG_Define_Constant_Function( ZombiesPerSecond, 17 ) ;
//
// zombies.cpp :
// /* CEG_GetConstantValue( ZombiesPerSecond ) must be used within a function !*/
//
// void
// ClockTick()
// {
// if( ElapsedTime > 1 ) /* Has 1 second passed ? */
// {
// DWORD cZombies = CEG_GetConstantValue( ZombiesPerSecond ) ;
// for( DWORD i=0; i<cZombies; ++i )
// {
// /* Create a Zombie !*/
// }
// }
// }
//
// Explanation :
//
// CEG_Define_Constant_Fucntion( ZombiesPerSecond, 17 ) defines a function
// that will return 17 (as a DWORD) every time it is called, IF your executable
// has not been tampered with, or copied. This function must NOT be inlined,
// when your game is CEG'd, the code bytes of the function will be modified.
// Putting the Definition in the same file as the usage may allow aggressive compiler
// settings to inline some usages of the function - we recommend that the definition
// never appear with the usage.
//
// CEG_Declare_Constant_Function( ZombiesPerSecond ) generates an extern declaration
// of this function.
//
// CEG_GetConstantValue( ZombiesPerSecond ) calls the function defined by
// CEG_Define_Constant_Function() and declared by CEG_Declare_Constant_Function().
//
// How it Works :
//
// This mechanism is very similar to that provided by CEG_Protect_Member_Function()
// The CEG code will compute checksums over your executing image, and these checksums
// will come to the result specified in the CEG_Declare_Constant_Function() if the
// image has not been tampered with. If a hacker has tampered, this will return a
// random number. By choosing appropriate constants, your game may be rendered
// unplayable, although CEG will not crash the game.
//
// Recommendation :
//
// This CEG functionality degrades the game when the game is tampered with.
// It should be used in conjunction with all the other CEG mechanisms.
// The other CEG mechanisms will immediately crash the game when tampered,
// which makes these mechanisms easy to identify in support calls, online forums etc...
//
// Make sure you include a small number of Steamworks_TestSecretAlways() call
// during the start/load of the game. These will catch Casual Piracy.
// The game degradation caused through this the CEG_Define_Constant_Function() is
// directed at sophisticated pirates, who will have a hard time tracking
// down the results of their modifications of the game image.
//
// IMPORTANT NOTE ABOUT THE VALUE ZERO !
//
// Don't use :
// CEG_Define_Constant_Function( Zero, 0 )
// or :
// CEG_Define_ConstantFloat_Function( FloatZero, 0.0f )
//
// The .obj and .exe parsing mechanisms assume 0 (also known as NULL) is an unbound
// usage - and the resulting calls to CEG_GetConstantValue() will not return 0 (zero)
// (The string 'zero' is fine, of course).
//
//
#define CEG_GetConstantValue( name ) \
CEG_UNIQNAME1( CEG_ConstantValue_, name )()
#define CEG_Declare_ConstantFloat_Function( name ) \
extern float __cdecl CEG_UNIQNAME1( CEG_ConstantValue_, name )()
#define Steamworks_CEG_ValueBind_Signature 0xCEF1DDEE
#define CEG_Define_Constant_Function( name, value ) \
extern "C" { \
__pragma( section(CEG_EXTERNAL_VALUE, read, write) ) \
Steamworks_CEG_ValueBinding __declspec(align(8)) __declspec(allocate(CEG_EXTERNAL_VALUE)) \
CEG_UNIQNAME1( Steamworks_CEG_ValueBinding_, name ) = { \
Steamworks_CEG_ValueBind_Signature, \
0, \
value, \
reinterpret_cast<DWORD_PTR>( Steamworks_ComputeDwordValue ) , \
} ; \
__pragma( comment( linker, "/INCLUDE:" CEG_UNIQNAME3( Steamworks_CEG_ValueBinding_, name ) ) ) \
}; \
extern DWORD CEG_UNIQNAME1( CEG_ConstantValue_, name )( void ); \
DWORD CEG_UNIQNAME1( CEG_ConstantValue_, name )( void ) \
{ \
INT32* pOffset = reinterpret_cast<INT32*>( & CEG_UNIQNAME1( Steamworks_CEG_ValueBinding_, name ).m_ImplementationFunction ) ; \
PFNSteamworks_ComputeDwordValue pfn = reinterpret_cast<PFNSteamworks_ComputeDwordValue>( reinterpret_cast<BYTE*>(pOffset+1) + *pOffset ); \
return (*pfn)(); \
}
#define CEG_Declare_Constant_Function( name ) \
extern DWORD CEG_UNIQNAME1( CEG_ConstantValue_, name )()
//
// These forms of CEG_Define_Constant_Function() appeared in older CEG SDK's, but are no longer available !
//
//
#define CEG_Define_Constant_Function2( name, value ) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Defined_Constant_Function2 has been retired and can no longer be used! - use CEG_Define_Constant_Function!") )
#define CEG_Define_ConstantFloat_Function( name, value ) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Defined_ConstantFloat_Function has been retired and can no longer be used! - use CEG_Define_Constant_Function!") )
#define CEG_Define_ConstantFloat_Function2( name, value ) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Defined_ConstantFloat_Function2 has been retired and can no longer be used! - use CEG_Define_Constant_Function!") )
/***************************************************
****************************************************
CEG_ProtectFunction and CEG_EncryptFunction
These macros must be placed within the body of a function.
Here is a small example, which describes how CEG_ProtectFunction() operates :
class CMyClass {
virtual void MyVirtualFunction( int SomeArg ) ;
} ;
__declspec(noinline) // This is necessary to prevent compiler optimizations from eliminating CEG check.
void
CMyClass::MyVirtualFunction( int SomeArg ) {
CEG_ProtectFunction();
//
// Now do the real work !
//
}
Void ExampleCall(CMyClass * p )
{
p->MyVirtualFunction( EXAMPLE_CONSTANT ) ; }
}
Now what happens to your binary is the following :
The vtable for CMyClass has been changed to reference a CEG function. When ExampleCall() is executed,
It will actually end up calling CEG code through the vtable. This CEG code preserves the state of the stack
and arguments in a fashion similar to the CRT setjmp() function.
The CEG code will then compute a checksum that incorporates machine identifying information into the checksum.
If nobody has modified the executable (by setting breakpoints, or by changing the executable file) and the executable
is running on the machine it was produced for, then the checksum results in the address of CMyClass::MyVirtualFunction().
In this case, CEG will patch the CONTEXT it got from it's setjmp() operation and longjmp() to CMyClass::MyVirtualFunction().
The setjmp()/longjmp() manipulations allow CEG to do it's work, without having to understand the calling convention
between ExampleCall() and CMyClass::MyVirtualFunction().
Before the CEG code invokes longjmp(), it checks that the address it computed is correct, by computing an MD5 of the
address, and comparing this to a stored MD5. If this comparison fail, CEG terminates the process directly.
You can use CEG_ProtectFunction()/CEG_EncryptFunction() in any kind of function -
C++ member functions, C++ static member functions etc....
*******************************************************
******************************************************/
#define CEG_ProtectFunction( ) \
Steamworks_CEG_InvokeTemplate( ProtectFunction, 0 )
#define CEG_EncryptFunction( ) \
Steamworks_CEG_InvokeTemplate( CacheConcealThunk, Steamworks_CEG_EncryptSectionMask )
//
// These are previus forms of CEG_ProtectFunction() that appeared in older SDK's - and should be replaced by either CEG_ProtectFunction()
// or CEG_EncryptFunction().
//
#define CEG_Protect_Function(x) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Protect_Function has been retired and can no longer be used! - use CEG_ProtectFunction!") )
#define CEG_Protect_StaticMemberFunction(x, y) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Protect_StaticMemberFunction has been retired and can no longer be used! - use CEG_ProtectFunction!") )
#define CEG_Protect_Virtual_Function3( name ) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Protect_Virtual_Function3 has been retired and can no longer be used! - use CEG_ProtectFunction!") )
#define CEG_Protect_Member_Function( name ) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Protect_Member_Function has been retired and can no longer be used! - use CEG_ProtectFunction!") )
#define CEG_Protect_Member_Function2( name ) \
__pragma( message( __FILE__ "(" CEG_LINE_NUMBER(__LINE__) ") : CEG_Protect_Member_Function2 has been retired and can no longer be used! - use CEG_ProtectFunction!") )
//
// This structure is declared to be a platform invariant size !
//
struct Steamworks_CEG_ValueBinding
{
DWORD32 m_Signature;
DWORD32 m_BindingUse;
DWORD64 m_DesiredResult;
DWORD64 m_ImplementationFunction;
};
//////////////////////////////////////////////////////////////
//
// Reference Macros !
//
// These macro's instantiate several CEG data structures as the CEG tools
// (mingle.exe and drmpe.exe) will see them in .obj and .exe files.
//
//
#define CEG_PROTECT_START_SIGNATURE 0xCCEEFF11
#define CEG_PROTECT_END_SIGNATURE 0x11ffeeCC
//
// DO NOT REFERENCE
//
// We specify these symbols here so that the linker will properly
// concatenate the CEG sections together in the final image.
//
// These symbols are only for use by internal code of the CEG library !
//
//
//
//////////////////////////////////////////////////////////////
#endif // _CEGCLIENT_H_

View File

@ -0,0 +1,46 @@
#include "CegClientWrapper.h"
#if defined( CLIENT_DLL ) || defined( GAME_DLL ) // shared
#include "cbase.h" // prerequisite for more than one of the below headers
#include "bspflags.h" // defines SURF_NOPORTAL and SURF_NOPAINT
#if defined ( CSTRIKE15 )
#endif // defined CSTRIKE15
#endif // defined CLIENT_DLL or GAME_DLL
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if defined( PROFILE_CEG )
CAverageCycleCounter allCEG;
CAverageCycleCounter allTestSecret;
CAverageCycleCounter allSelfCheck;
CAverageCycleCounter allProtectMember;
CAverageCycleCounter allProtectVirtual;
#endif // defined( PROFILE_CEG )
#if defined( CLIENT_DLL ) // client-side only
void Init_GCVs()
{
// function calls to prime statics and ensure CEG init hitches happen before game is interactive
InitHudAllowTextChatFlag();
InitUiAllowProperTintFlag();
}
CEG_DEFINE_CONSTANT_FUNCTION( HudAllowTextChatFlag, ALLOW_TEXTCHAT_FLAG );
CEG_DEFINE_CONSTANT_FUNCTION( UiAllowProperTintFlag, ALLOW_PROPER_TINT_FLAG );
#elif defined( GAME_DLL ) // server-side only
void Init_GCVs()
{
}
#endif // defined( GAME_DLL )

301
common/CegClientWrapper.h Normal file
View File

@ -0,0 +1,301 @@
#ifndef _CEGCLIENTWRAPPER_H_
#define _CEGCLIENTWRAPPER_H_
#pragma once
#include "xbox/xboxstubs.h" // defines DWORD, DWORD_PTR, etc.
// required by cegclient.h, but no need to pull in all of windef.h
#if defined( PLATFORM_64BITS )
typedef int64 INT_PTR;
#else
typedef int32 INT_PTR;
#endif
typedef unsigned char BYTE;
typedef BYTE *LPBYTE;
typedef int32 INT32;
typedef uint32 DWORD32;
typedef uint64 DWORD64;
#define CEG_GET_CONSTANT_VALUE_AVOID_CEG( fn_name ) fn_name() // makes it easy for us to turn off CEG checks if one of the CEG'ed functions has a bigger impact on perf than expected
// To disable CEG in your build for one or more modules, add "/NO_CEG" to your VPC parameters
#if (!defined( USE_CEG ) || ( !defined( CLIENT_DLL ) && !defined( GAME_DLL ) ) )
#define CEG_NOINLINE
// Stub out functions if CEG is disabled
#define STEAMWORKS_REGISTERTHREAD() (true)
#define STEAMWORKS_UNREGISTERTHREAD() (true)
#define STEAMWORKS_INITCEGLIBRARY() (true)
#define STEAMWORKS_TERMCEGLIBRARY() (true)
#define STEAMWORKS_TESTSECRET()
#define STEAMWORKS_TESTSECRETALWAYS()
#define STEAMWORKS_SELFCHECK()
#define STEAMWORKS_TESTSECRET_AMORTIZE( period )
#define STEAMWORKS_TESTSECRETALWAYS_AMORTIZE( period )
#define STEAMWORKS_SELFCHECK_AMORTIZE( period )
#define RANDOM_CEG_TEST_SECRET()
#define RANDOM_CEG_TEST_SECRET_PERIOD( testPeriod, checkPeriod )
#define RANDOM_CEG_TEST_SECRET_LINE_PERIOD( testPeriod, testLinePeriod, checkPeriod, checkLinePeriod )
#define CEG_PROTECT_FUNCTION( unquotedSymbolHelper )
#define CEG_ENCRYPT_FUNCTION( unquotedSymbolHelper )
#define CEG_PROTECT_MEMBER_FUNCTION( unquotedSymbolHelper )
#define CEG_PROTECT_VIRTUAL_FUNCTION( unquotedSymbolHelper )
#define CEG_PROTECT_STATIC_MEMBER_FUNCTION( unquotedSymbolHelper, fn_name )
#define CEG_DECLARE_CONSTANT_FUNCTION( fn_name ) extern DWORD __cdecl fn_name();
#define CEG_DECLARE_CONSTANT_FLOAT_FUNCTION( fn_name ) extern float __cdecl fn_name();
#define CEG_DEFINE_CONSTANT_FUNCTION( fn_name, val ) DWORD __cdecl fn_name() { return val; }
#define CEG_DEFINE_CONSTANT_FLOAT_FUNCTION( fn_name, val ) float __cdecl fn_name() { return val; }
#define CEG_GET_CONSTANT_VALUE( fn_name ) fn_name()
#define CEG_GCV_PRE()
#define CEG_GCV_POST()
#else // CEG is enabled
#if defined( _GAMECONSOLE ) || defined( POSIX ) || defined( NO_STEAM )
#error
#endif
#include "cegclient.h"
// use this on any functions where we use CEG_PROTECT to ensure they don't get inlined in the CEG build
#define CEG_NOINLINE __declspec(noinline)
// wrapping CEG calls in macros allows us to hide interface changes and centrally add checks and perf instrumentation
#define STEAMWORKS_REGISTERTHREAD() Steamworks_RegisterThread()
#define STEAMWORKS_UNREGISTERTHREAD() Steamworks_UnRegisterThread()
#define STEAMWORKS_INITCEGLIBRARY() Steamworks_InitCEGLibrary()
#define STEAMWORKS_TERMCEGLIBRARY() Steamworks_TermCEGLibrary()
#define CEG_DECLARE_CONSTANT_FUNCTION( fn_name ) CEG_Declare_Constant_Function( fn_name )
#define CEG_DECLARE_CONSTANT_FLOAT_FUNCTION( fn_name ) CEG_Declare_ConstantFloat_Function( fn_name )
#define CEG_DEFINE_CONSTANT_FUNCTION( fn_name, val ) CEG_Define_Constant_Function( fn_name, val )
#define CEG_DEFINE_CONSTANT_FLOAT_FUNCTION( fn_name, val ) CEG_Define_ConstantFloat_Function2( fn_name, val )
#define CEG_GET_CONSTANT_VALUE( fn_name ) CEG_GetConstantValue( fn_name )
// seeded with large primes at frequencies that lead to approximately one check every 30 seconds
#define RANDOM_CEG_TEST_SECRET() \
RANDOM_CEG_TEST_SECRET_LINE_PERIOD( 128449, 19, 1102441, 397 )
#define RANDOM_CEG_TEST_SECRET_PERIOD( testPeriod, checkPeriod ) \
RANDOM_CEG_TEST_SECRET_LINE_PERIOD( testPeriod, 0, checkPeriod, 0 )
// uncomment here to enable dev messages per CEG call, including CEG performance numbers
//#define PROFILE_CEG
#if !defined( PROFILE_CEG )
#define CEG_PROFILE_DECL
#define CEG_PROFILE_BLOCK( fn_name, fn_type, identifier ) fn_name;
#define CEG_GCV_PRE()
#define CEG_GCV_POST()
#else // defined( PROFILE_CEG )
#include "tier0\fasttimer.h"
extern CAverageCycleCounter allCEG;
extern CAverageCycleCounter allTestSecret;
extern CAverageCycleCounter allSelfCheck;
extern CAverageCycleCounter allProtectMember;
extern CAverageCycleCounter allProtectVirtual;
#if !defined( MEMOVERRIDE_MODULE )
#define MEMOVERRIDE_MODULE UNKNOWN_MODULE
#endif
#define _MKSTRING(arg) #arg
#define MKSTRING(arg) _MKSTRING(arg)
#define CEG_PROFILE_BLOCK( fn_name, fn_type, identifier ) \
static unsigned long s_##fn_type##Hits = 0; \
s_##fn_type##Hits++; \
static CAverageCycleCounter this##fn_type; \
{ \
CAverageTimeMarker this##fn_type##Marker( &this##fn_type ); \
CAverageTimeMarker all##fn_type##Marker( &all##fn_type ); \
CAverageTimeMarker allCEGMarker( &allCEG ); \
fn_name; \
} \
DevMsg( "%s: %s%s %s:%d - %.2fms avg (%.2fms total, %.2fms peak, %d iters), %lu/%lu = %.5f%% hit rate.\n" \
"Avg CEG %s Cost: %.2fms Avg CEG Cost: %.2fms\n", \
MKSTRING(MEMOVERRIDE_MODULE), identifier, #fn_type, __FILE__, __LINE__, \
this##fn_type.GetAverageMilliseconds(), this##fn_type.GetTotalMilliseconds(), this##fn_type.GetPeakMilliseconds(), this##fn_type.GetIters(), \
s_##fn_type##Hits, s_tests, \
float( s_##fn_type##Hits * 100 ) / float( s_tests ), \
#fn_type, \
all##fn_type.GetAverageMilliseconds(), \
allCEG.GetAverageMilliseconds() );
#define CEG_PROFILE_DECL \
static unsigned long int s_tests = 0; \
s_tests++;
#define CEG_GCV_PRE() \
CFastTimer __FUNCTION__##Timer; \
__FUNCTION__##Timer.Start();
#define CEG_GCV_POST() \
__FUNCTION__##Timer.End(); \
if( __FUNCTION__##Timer.GetDuration().GetMillisecondsF() > 0.5f ) \
{ \
DevMsg( "%s: GetConstantValue in %s : %.2fms\n", \
MKSTRING(MEMOVERRIDE_MODULE), __FUNCTION__, __FUNCTION__##Timer.GetDuration().GetMillisecondsF() ); \
}
#endif // PROFILE_CEG off/on
// the below macros allow us to turn profiling on or off with a single #ifdef, using the same underlying implementation in each case
#define RANDOM_CEG_TEST_SECRET_LINE_PERIOD( testPeriod, testLinePeriod, checkPeriod, checkLinePeriod ) \
do { \
const unsigned long tp = testPeriod + testLinePeriod * __LINE__; \
const unsigned long cp = checkPeriod + checkLinePeriod * __LINE__; \
static unsigned long s_nCegCounter = __LINE__ ^ __COUNTER__ ^ reinterpret_cast<int>( &s_nCegCounter ); \
++s_nCegCounter; \
CEG_PROFILE_DECL; \
if ( !( ( s_nCegCounter ) % ( tp ) ) ) \
{ \
CEG_PROFILE_BLOCK( Steamworks_TestSecretAlways(), TestSecret, "Random " ); \
} \
else if ( !( ( s_nCegCounter ) % ( cp ) ) ) \
{ \
CEG_PROFILE_BLOCK( Steamworks_SelfCheck(), SelfCheck, "Random " ); \
} \
} \
while( 0 );
//
// Can't grab metrics - although this is placed within the scope a function -
// The effect is to change calls to the function to first execute some CEG code,
// and this CEG code is not available within this scope.
// The CEG code computes the address of the containing function, and jumps to it.
//
#define CEG_PROTECT_FUNCTION( unquotedSymbolHelper ) \
CEG_ProtectFunction( );
//
// Can't grab metrics - although this is placed within the scope a function -
// The effect is to change calls to the function to first execute some CEG code,
// and this CEG code is not available within this scope.
//
// The body of the function that contains this macro is encrypted, and the CEG code
// decrypts the opcodes and places them in executable memory, and then executes it.
// Upon return, the executable memory is released.
//
#define CEG_ENCRYPT_FUNCTION( unquotedSymbolHelper ) \
CEG_EncryptFunction( );
#define CEG_PROTECT_MEMBER_FUNCTION( unquotedSymbolHelper ) \
do { \
CEG_PROFILE_DECL; \
CEG_PROFILE_BLOCK( CEG_ProtectFunction( ), ProtectMember, "" ); \
} \
while( 0 );
#define CEG_PROTECT_VIRTUAL_FUNCTION( unquotedSymbolHelper ) \
do { \
CEG_PROFILE_DECL; \
CEG_PROFILE_BLOCK( CEG_ProtectFunction( ), ProtectVirtual, "" ); \
} while( 0 );
// defined outside the scope of a function, so can't trivially grab metrics
#define CEG_PROTECT_STATIC_MEMBER_FUNCTION( unquotedSymbolHelper, fn_name ) \
CEG_Protect_StaticMemberFunction( unquotedSymbolHelper, fn_name );
#define STEAMWORKS_TESTSECRET() \
do { \
CEG_PROFILE_DECL; \
CEG_PROFILE_BLOCK( Steamworks_TestSecret(), TestSecret, "" ); \
} while( 0 );
#define STEAMWORKS_TESTSECRETALWAYS() \
do { \
CEG_PROFILE_DECL; \
CEG_PROFILE_BLOCK( Steamworks_TestSecretAlways(), TestSecret, "" ); \
} while( 0 );
#define STEAMWORKS_SELFCHECK() \
do { \
CEG_PROFILE_DECL; \
CEG_PROFILE_BLOCK( Steamworks_SelfCheck(), SelfCheck, "" ); \
} while( 0 );
// AMORTIZED
#define STEAMWORKS_TESTSECRET_AMORTIZE( period ) \
do { \
const unsigned long tp = period; \
static unsigned long s_nCegCounter = __LINE__ ^ __COUNTER__ ^ reinterpret_cast<int>( &s_nCegCounter ); \
++s_nCegCounter; \
CEG_PROFILE_DECL; \
if ( !( ( s_nCegCounter ) % ( tp ) ) ) \
{ \
CEG_PROFILE_BLOCK( Steamworks_TestSecret(), TestSecret, "Amortized " ); \
} \
} while( 0 );
#define STEAMWORKS_TESTSECRETALWAYS_AMORTIZE( period ) \
do { \
const unsigned long tp = period; \
static unsigned long s_nCegCounter = __LINE__ ^ __COUNTER__ ^ reinterpret_cast<int>( &s_nCegCounter ); \
++s_nCegCounter; \
CEG_PROFILE_DECL; \
if ( !( ( s_nCegCounter ) % ( tp ) ) ) \
{ \
CEG_PROFILE_BLOCK( Steamworks_TestSecretAlways(), TestSecret, "Amortized " ); \
} \
} while( 0 );
#define STEAMWORKS_SELFCHECK_AMORTIZE( period ) \
do { \
const unsigned long tp = period; \
static unsigned long s_nCegCounter = __LINE__ ^ __COUNTER__ ^ reinterpret_cast<int>( &s_nCegCounter ); \
++s_nCegCounter; \
CEG_PROFILE_DECL; \
if ( !( ( s_nCegCounter ) % ( tp ) ) ) \
{ \
CEG_PROFILE_BLOCK( Steamworks_SelfCheck(), TestSecret, "Amortized " ); \
} \
} while( 0 );
#endif // CEG disabled/enabled
#if defined( CLIENT_DLL ) // client-only
void Init_GCVs();
CEG_DECLARE_CONSTANT_FUNCTION( HudAllowTextChatFlag );
CEG_DECLARE_CONSTANT_FUNCTION( HudAllowBuyMenuFlag );
CEG_DECLARE_CONSTANT_FUNCTION( UiAllowProperTintFlag );
#elif defined( GAME_DLL ) // server-only
void Init_GCVs();
#endif // defined( GAME_DLL )
// Worst-case, if you need to debug CEG calls or CEG perf, and CEG profiling isn't doing the trick (it doesn't cover everything), you can
// do a binary search on one or all of the below calls by restoring part of the #if 0 block below. You'll get a duplicate definition warning,
// but anything redefined below will be a no-op in the build, allowing you to rule it out as a potential perf issue.
// Remember that CEG builds neeed to be rebuilds (CEG'ed dlls only), but the /MP flag should make it about 60 seconds per rebuild.
#if 0
#define STEAMWORKS_TESTSECRET()
#define STEAMWORKS_TESTSECRETALWAYS()
#define STEAMWORKS_SELFCHECK()
#define RANDOM_CEG_TEST_SECRET()
#define RANDOM_CEG_TEST_SECRET_PERIOD( testPeriod, checkPeriod )
#define RANDOM_CEG_TEST_SECRET_LINE_PERIOD( testPeriod, testLinePeriod, checkPeriod, checkLinePeriod )
#define CEG_PROTECT_FUNCTION( unquotedSymbolHelper )
#define CEG_PROTECT_MEMBER_FUNCTION( unquotedSymbolHelper )
#define CEG_PROTECT_VIRTUAL_FUNCTION( unquotedSymbolHelper )
#define CEG_PROTECT_STATIC_MEMBER_FUNCTION( unquotedSymbolHelper, fn_name )
#define CEG_DECLARE_CONSTANT_FUNCTION( fn_name ) extern DWORD __cdecl fn_name();
#define CEG_DECLARE_CONSTANT_FLOAT_FUNCTION( fn_name ) extern float __cdecl fn_name();
#define CEG_DEFINE_CONSTANT_FUNCTION( fn_name, val ) DWORD __cdecl fn_name() { return val; }
#define CEG_DEFINE_CONSTANT_FLOAT_FUNCTION( fn_name, val ) float __cdecl fn_name() { return val; }
#define CEG_GET_CONSTANT_VALUE( fn_name ) fn_name()
#endif
#endif //_CEGCLIENTWRAPPER_H_

977
common/ConfigManager.cpp Normal file
View File

@ -0,0 +1,977 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <windows.h>
#include "interface.h"
#include "tier0/icommandline.h"
#include "filesystem_tools.h"
#include "KeyValues.h"
#include "UtlBuffer.h"
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "ConfigManager.h"
#include "SourceAppInfo.h"
#include "steam/steam_api.h"
extern CSteamAPIContext *steamapicontext;
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#define GAME_CONFIG_FILENAME "GameConfig.txt"
#define TOKEN_SDK_VERSION "SDKVersion"
// Version history:
// 0 - Initial release
// 1 - Versioning added, DoD configuration added
// 2 - Ep1 added
// 3 - Ep2, TF2, and Portal added
// 4 - Portal 2 added
// 5 - CSS 1.5
#define SDK_LAUNCHER_VERSION 5
// Half-Life 2
defaultConfigInfo_t HL2Info =
{
"Half-Life 2",
"hl2",
"halflife2.fgd",
"half-life 2",
"info_player_start",
"hl2.exe",
GetAppSteamAppId( k_App_HL2 )
};
// Counter-Strike: Source
defaultConfigInfo_t CStrikeInfo =
{
"Counter-Strike: Source",
"cstrike",
"cstrike.fgd",
"counter-strike source",
"info_player_terrorist",
"hl2.exe",
GetAppSteamAppId( k_App_CSS )
};
// Counter-Strike: Source
defaultConfigInfo_t CStrike15Info =
{
"Counter-Strike: Global Offensive",
"csgo",
"csgo.fgd",
"counter-strike global offensive",
"info_player_terrorist",
"csgo.exe",
GetAppSteamAppId( k_App_CSS15 )
};
//Half-Life 2: Deathmatch
defaultConfigInfo_t HL2DMInfo =
{
"Half-Life 2: Deathmatch",
"hl2mp",
"hl2mp.fgd",
"half-life 2 deathmatch",
"info_player_deathmatch",
"hl2.exe",
GetAppSteamAppId( k_App_HL2MP )
};
// Day of Defeat: Source
defaultConfigInfo_t DODInfo =
{
"Day of Defeat: Source",
"dod",
"dod.fgd",
"day of defeat source",
"info_player_allies",
"hl2.exe",
GetAppSteamAppId( k_App_DODS )
};
// Half-Life 2 Episode 1
defaultConfigInfo_t Episode1Info =
{
"Half-Life 2: Episode One",
"episodic",
"halflife2.fgd",
"half-life 2 episode one",
"info_player_start",
"hl2.exe",
GetAppSteamAppId( k_App_HL2_EP1 )
};
// Half-Life 2 Episode 2
defaultConfigInfo_t Episode2Info =
{
"Half-Life 2: Episode Two",
"ep2",
"halflife2.fgd",
"half-life 2 episode two",
"info_player_start",
"hl2.exe",
GetAppSteamAppId( k_App_HL2_EP2 )
};
// Team Fortress 2
defaultConfigInfo_t TF2Info =
{
"Team Fortress 2",
"tf",
"tf.fgd",
"team fortress 2",
"info_player_teamspawn",
"hl2.exe",
GetAppSteamAppId( k_App_TF2 )
};
// Portal
defaultConfigInfo_t PortalInfo =
{
"Portal",
"portal",
"portal.fgd",
"portal",
"info_player_start",
"hl2.exe",
GetAppSteamAppId( k_App_PORTAL )
};
// Portal 2
defaultConfigInfo_t Portal2Info =
{
"Portal 2",
"portal2",
"portal2.fgd",
"portal 2",
"info_player_start",
"portal2.exe",
GetAppSteamAppId( k_App_PORTAL2 )
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameConfigManager::CGameConfigManager( void ) : m_pData( NULL ), m_LoadStatus( LOADSTATUS_NONE )
{
// Start with default directory
GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), m_szBaseDirectory, sizeof( m_szBaseDirectory ) );
Q_StripLastDir( m_szBaseDirectory, sizeof( m_szBaseDirectory ) ); // Get rid of the filename.
Q_StripTrailingSlash( m_szBaseDirectory );
m_eSDKEpoch = (eSDKEpochs) SDK_LAUNCHER_VERSION;
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CGameConfigManager::~CGameConfigManager( void )
{
// Release the keyvalues
if ( m_pData != NULL )
{
m_pData->deleteThis();
}
}
//-----------------------------------------------------------------------------
// Purpose: Config loading interface
// Input : *baseDir - base directory for our file
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CGameConfigManager::LoadConfigs( const char *baseDir )
{
return LoadConfigsInternal( baseDir, false );
}
//-----------------------------------------------------------------------------
// Purpose: Loads a file into the given utlbuffer.
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ReadUtlBufferFromFile( CUtlBuffer &buffer, const char *szPath )
{
struct _stat fileInfo;
if ( _stat( szPath, &fileInfo ) == -1 )
{
return false;
}
buffer.EnsureCapacity( fileInfo.st_size );
int nFile = _open( szPath, _O_BINARY | _O_RDONLY );
if ( nFile == -1 )
{
return false;
}
if ( _read( nFile, buffer.Base(), fileInfo.st_size ) != fileInfo.st_size )
{
_close( nFile );
return false;
}
_close( nFile );
buffer.SeekPut( CUtlBuffer::SEEK_HEAD, fileInfo.st_size );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Loads a file into the given utlbuffer.
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool SaveUtlBufferToFile( CUtlBuffer &buffer, const char *szPath )
{
int nFile = _open( szPath, _O_TEXT | _O_CREAT | _O_TRUNC | _O_RDWR, _S_IWRITE );
if ( nFile == -1 )
{
return false;
}
int nSize = buffer.TellMaxPut();
if ( _write( nFile, buffer.Base(), nSize ) < nSize )
{
_close( nFile );
return false;
}
_close( nFile );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Load a game configuration file (with fail-safes)
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CGameConfigManager::LoadConfigsInternal( const char *baseDir, bool bRecursiveCall )
{
// Init the config if it doesn't exist
if ( !IsLoaded() )
{
m_pData = new KeyValues( GAME_CONFIG_FILENAME );
if ( !IsLoaded() )
{
m_LoadStatus = LOADSTATUS_ERROR;
return false;
}
}
// Clear it out
m_pData->Clear();
// Build our default directory
if ( baseDir != NULL && baseDir[0] != NULL )
{
SetBaseDirectory( baseDir );
}
// Make a full path name
char szPath[MAX_PATH];
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME );
bool bLoaded = false;
CUtlBuffer buffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
if ( ReadUtlBufferFromFile( buffer, szPath ) )
{
bLoaded = m_pData->LoadFromBuffer( szPath, buffer, NULL, NULL );
}
if ( !bLoaded )
{
// Attempt to re-create the configs
if ( CreateAllDefaultConfigs() )
{
// Only allow this once
if ( !bRecursiveCall )
return LoadConfigsInternal( baseDir, true );
// Version the config.
VersionConfig();
}
m_LoadStatus = LOADSTATUS_ERROR;
return false;
}
else
{
// Check to see if the gameconfig.txt is up to date.
UpdateConfigsInternal();
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Add to the current config.
//-----------------------------------------------------------------------------
void CGameConfigManager::UpdateConfigsInternal( void )
{
// Check to a valid gameconfig.txt file buffer.
if ( !IsLoaded() )
return;
// Check for version first. If the version is up to date, it is assumed to be accurate
if ( IsConfigCurrent() )
return;
KeyValues *pGameBlock = GetGameBlock();
if ( !pGameBlock )
{
// If we don't have a game block, reset the config file.
ResetConfigs();
return;
}
KeyValues *pDefaultBlock = new KeyValues( "DefaultConfigs" );
if ( pDefaultBlock != NULL )
{
// Compile our default configurations
GetDefaultGameBlock( pDefaultBlock );
// Compare our default block to our current configs
KeyValues *pNextSubKey = pDefaultBlock->GetFirstTrueSubKey();
while ( pNextSubKey != NULL )
{
// If we already have the name, we don't care about it
if ( pGameBlock->FindKey( pNextSubKey->GetName() ) )
{
// Advance by one key
pNextSubKey = pNextSubKey->GetNextTrueSubKey();
continue;
}
// Copy the data through to our game block
KeyValues *pKeyCopy = pNextSubKey->MakeCopy();
pGameBlock->AddSubKey( pKeyCopy );
// Advance by one key
pNextSubKey = pNextSubKey->GetNextTrueSubKey();
}
// All done
pDefaultBlock->deleteThis();
}
// Save the new config.
SaveConfigs();
// Add the new version as we have been updated.
VersionConfig();
}
//-----------------------------------------------------------------------------
// Purpose: Update the gameconfig.txt version number.
//-----------------------------------------------------------------------------
void CGameConfigManager::VersionConfig( void )
{
// Check to a valid gameconfig.txt file buffer.
if ( !IsLoaded() )
return;
// Look for the a version key value pair and update it.
KeyValues *pKeyVersion = m_pData->FindKey( TOKEN_SDK_VERSION );
// Update the already existing version key value pair.
if ( pKeyVersion )
{
if ( pKeyVersion->GetInt() == m_eSDKEpoch )
return;
m_pData->SetInt( TOKEN_SDK_VERSION, m_eSDKEpoch );
}
// Create a new version key value pair.
else
{
m_pData->SetInt( TOKEN_SDK_VERSION, m_eSDKEpoch );
}
// Save the configuration.
SaveConfigs();
}
//-----------------------------------------------------------------------------
// Purpose: Check to see if the version of the gameconfig.txt is up to date.
//-----------------------------------------------------------------------------
bool CGameConfigManager::IsConfigCurrent( void )
{
// Check to a valid gameconfig.txt file buffer.
if ( !IsLoaded() )
return false;
KeyValues *pKeyValue = m_pData->FindKey( TOKEN_SDK_VERSION );
if ( !pKeyValue )
return false;
int nVersion = pKeyValue->GetInt();
if ( nVersion == m_eSDKEpoch )
return true;
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Get the base path for a default config's install (handling steam's paths)
//-----------------------------------------------------------------------------
void CGameConfigManager::GetRootGameDirectory( char *out, size_t outLen, const char *rootDir, const char *steamDir )
{
// NOTE: This has since been depricated due to Steam filesystem changes -- jdw
Q_strncpy( out, rootDir, outLen );
}
//-----------------------------------------------------------------------------
// Purpose: Get the base path for a default config's content sources (handling steam's paths)
//-----------------------------------------------------------------------------
void CGameConfigManager::GetRootContentDirectory( char *out, size_t outLen, const char *rootDir )
{
// Steam install is different
if ( IsSDKDeployment() )
{
Q_snprintf( out, outLen, "%s\\sdk_content", rootDir );
}
else
{
Q_snprintf( out, outLen, "%s\\content", rootDir );
}
}
// Default game configuration template
const char szDefaultConfigText[] =
"\"%gamename%\"\
{\
\"GameDir\" \"%gamedir%\"\
\"Hammer\"\
{\
\"TextureFormat\" \"5\"\
\"MapFormat\" \"4\"\
\"DefaultTextureScale\" \"0.250000\"\
\"DefaultLightmapScale\" \"16\"\
\"DefaultSolidEntity\" \"func_detail\"\
\"DefaultPointEntity\" \"%defaultpointentity%\"\
\"GameExeDir\" \"%gameexe%\"\
\"MapDir\" \"%gamemaps%\"\
\"CordonTexture\" \"tools\\toolsskybox\"\
\"MaterialExcludeCount\" \"0\"\
\"GameExe\" \"%gameEXE%\"\
\"BSP\" \"%bspdir%\"\
\"Vis\" \"%visdir%\"\
\"Light\" \"%lightdir%\"\
}}";
// NOTE: This function could use some re-write, it can't handle non-retail paths well
//-----------------------------------------------------------------------------
// Purpose: Add a templated default configuration with proper paths
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CGameConfigManager::AddDefaultConfig( const defaultConfigInfo_t &info, KeyValues *out, const char *rootDirectory, const char *gameExeDir )
{
// NOTE: Freed by head keyvalue
KeyValues *newConfig = new KeyValues( info.gameName );
// Set this up to autodelete until we know we're actually going to use it
KeyValues::AutoDelete autodelete_key( newConfig );
if ( newConfig->LoadFromBuffer( "defaultcfg.txt", szDefaultConfigText ) == false )
return false;
newConfig->SetName( info.gameName );
// Game's root directory (with special steam name handling)
char rootGameDir[MAX_PATH];
GetRootGameDirectory( rootGameDir, sizeof( rootGameDir ), rootDirectory, info.steamPath );
// Game's content directory
char contentRootDir[MAX_PATH];
GetRootContentDirectory( contentRootDir, sizeof( contentRootDir ), rootDirectory );
char szPath[MAX_PATH];
// Game directory
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", rootGameDir, info.gameDir );
newConfig->SetString( "GameDir", szPath );
// Create the Hammer portion of this block
KeyValues *hammerBlock = newConfig->FindKey( "Hammer" );
if ( hammerBlock == NULL )
return false;
hammerBlock->SetString( "GameExeDir", gameExeDir );
// Fill in the proper default point entity
hammerBlock->SetString( "DefaultPointEntity", info.defaultPointEntity );
// Fill in the default VMF directory
char contentMapDir[MAX_PATH];
Q_snprintf( contentMapDir, sizeof( contentMapDir ), "%s\\maps", contentRootDir );
hammerBlock->SetString( "MapDir", contentMapDir );
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s\\maps", rootGameDir, info.gameDir );
hammerBlock->SetString( "BSPDir", szPath );
// Fill in the game executable
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", gameExeDir, info.exeName );
hammerBlock->SetString( "GameEXE", szPath );
//Fill in game FGDs
if ( info.FGD[0] != '\0' )
{
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), info.FGD );
hammerBlock->SetString( "GameData0", szPath );
}
// Fill in the tools path
Q_snprintf( szPath, sizeof( szPath ), "%s\\vbsp.exe", GetBaseDirectory() );
hammerBlock->SetString( "BSP", szPath );
Q_snprintf( szPath, sizeof( szPath ), "%s\\vvis.exe", GetBaseDirectory() );
hammerBlock->SetString( "Vis", szPath );
Q_snprintf( szPath, sizeof( szPath ), "%s\\vrad.exe", GetBaseDirectory() );
hammerBlock->SetString( "Light", szPath );
// Get our insertion point
KeyValues *insertSpot = out->GetFirstTrueSubKey();
// detach the autodelete pointer
autodelete_key.Assign(NULL);
// Set this as the sub key if there's nothing already there
if ( insertSpot == NULL )
{
out->AddSubKey( newConfig );
}
else
{
// Find the last subkey
while ( insertSpot->GetNextTrueSubKey() )
{
insertSpot = insertSpot->GetNextTrueSubKey();
}
// Become a peer to it
insertSpot->SetNextKey( newConfig );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Determines whether the requested appID is installed on this computer
// Input : nAppID - ID to verify
// Output : Returns true if installed, false if not.
//-----------------------------------------------------------------------------
bool CGameConfigManager::IsAppSubscribed( int nAppID )
{
bool bIsSubscribed = false;
if ( g_pFullFileSystem != NULL && g_pFullFileSystem->IsSteam() )
{
if ( steamapicontext->SteamApps() )
{
// See if specified app is installed
bIsSubscribed = steamapicontext->SteamApps()->BIsSubscribedApp( nAppID );
}
}
else
{
// If we aren't running FileSystem Steam then we must be doing internal development. Give everything.
bIsSubscribed = true;
}
return bIsSubscribed;
}
//-----------------------------------------------------------------------------
// Purpose: Create default configurations for all Valve retail applications
//-----------------------------------------------------------------------------
bool CGameConfigManager::CreateAllDefaultConfigs( void )
{
bool bRetVal = true;
// Start our new block
KeyValues *configBlock = new KeyValues( "Configs" );
KeyValues *gameBlock = configBlock->CreateNewKey();
gameBlock->SetName( "Games" );
GetDefaultGameBlock( gameBlock );
bRetVal = !gameBlock->IsEmpty();
// Make a full path name
char szPath[MAX_PATH];
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME );
CUtlBuffer buffer;
configBlock->RecursiveSaveToFile( buffer, 0 );
SaveUtlBufferToFile( buffer, szPath );
configBlock->deleteThis();
m_LoadStatus = LOADSTATUS_CREATED;
return bRetVal;
}
//-----------------------------------------------------------------------------
// Purpose: Load game information from an INI file
//-----------------------------------------------------------------------------
bool CGameConfigManager::ConvertGameConfigsINI( void )
{
const char *iniFilePath = GetIniFilePath();
// Load our INI file
int nNumConfigs = GetPrivateProfileInt( "Configs", "NumConfigs", 0, iniFilePath );
if ( nNumConfigs <= 0 )
return false;
// Build a new keyvalue file
KeyValues *headBlock = new KeyValues( "Configs" );
// Create the block for games
KeyValues *gamesBlock = headBlock->CreateNewKey( );
gamesBlock->SetName( "Games" );
int i;
int nStrlen;
char szSectionName[MAX_PATH];
char textBuffer[MAX_PATH];
// Parse all the configs
for ( int nConfig = 0; nConfig < nNumConfigs; nConfig++ )
{
// Each came configuration is stored in a different section, named "GameConfig0..GameConfigN".
// If the "Name" key exists in this section, try to load the configuration from this section.
sprintf(szSectionName, "GameConfig%d", nConfig);
int nCount = GetPrivateProfileString(szSectionName, "Name", "", textBuffer, sizeof(textBuffer), iniFilePath);
if (nCount > 0)
{
// Make a new section
KeyValues *subGame = gamesBlock->CreateNewKey();
subGame->SetName( textBuffer );
GetPrivateProfileString( szSectionName, "ModDir", "", textBuffer, sizeof(textBuffer), iniFilePath);
// Add the mod dir
subGame->SetString( "GameDir", textBuffer );
// Start a block for Hammer settings
KeyValues *hammerBlock = subGame->CreateNewKey();
hammerBlock->SetName( "Hammer" );
i = 0;
// Get all FGDs
do
{
char szGameData[MAX_PATH];
sprintf( szGameData, "GameData%d", i );
nStrlen = GetPrivateProfileString( szSectionName, szGameData, "", textBuffer, sizeof(textBuffer), iniFilePath );
if ( nStrlen > 0 )
{
hammerBlock->SetString( szGameData, textBuffer );
i++;
}
} while ( nStrlen > 0 );
hammerBlock->SetInt( "TextureFormat", GetPrivateProfileInt( szSectionName, "TextureFormat", 5 /*FIXME: tfVMT*/, iniFilePath ) );
hammerBlock->SetInt( "MapFormat", GetPrivateProfileInt( szSectionName, "MapFormat", 4 /*FIXME: mfHalfLife2*/, iniFilePath ) );
// Default texture scale
GetPrivateProfileString( szSectionName, "DefaultTextureScale", "1", textBuffer, sizeof(textBuffer), iniFilePath );
float defaultTextureScale = (float) atof( textBuffer );
if ( defaultTextureScale == 0 )
{
defaultTextureScale = 1.0f;
}
hammerBlock->SetFloat( "DefaultTextureScale", defaultTextureScale );
hammerBlock->SetInt( "DefaultLightmapScale", GetPrivateProfileInt( szSectionName, "DefaultLightmapScale", 16 /*FIXME: DEFAULT_LIGHTMAP_SCALE*/, iniFilePath ) );
GetPrivateProfileString( szSectionName, "GameExe", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "GameExe", textBuffer );
GetPrivateProfileString( szSectionName, "DefaultSolidEntity", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "DefaultSolidEntity", textBuffer );
GetPrivateProfileString( szSectionName, "DefaultPointEntity", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "DefaultPointEntity", textBuffer );
GetPrivateProfileString( szSectionName, "BSP", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "BSP", textBuffer );
GetPrivateProfileString( szSectionName, "Vis", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "Vis", textBuffer );
GetPrivateProfileString( szSectionName, "Light", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "Light", textBuffer );
GetPrivateProfileString( szSectionName, "GameExeDir", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "GameExeDir", textBuffer );
GetPrivateProfileString( szSectionName, "MapDir", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "MapDir", textBuffer );
GetPrivateProfileString( szSectionName, "BSPDir", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "BSPDir", textBuffer );
GetPrivateProfileString( szSectionName, "CordonTexture", "", textBuffer, sizeof(textBuffer), iniFilePath );
hammerBlock->SetString( "CordonTexture", textBuffer );
GetPrivateProfileString( szSectionName, "MaterialExcludeCount", "0", textBuffer, sizeof(textBuffer), iniFilePath );
int materialExcludeCount = atoi( textBuffer );
hammerBlock->SetInt( "MaterialExcludeCount", materialExcludeCount );
char excludeDir[MAX_PATH];
// Write out all excluded directories
for( i = 0; i < materialExcludeCount; i++ )
{
sprintf( &excludeDir[0], "-MaterialExcludeDir%d", i );
GetPrivateProfileString( szSectionName, excludeDir, "", textBuffer, sizeof( textBuffer ), iniFilePath );
hammerBlock->SetString( excludeDir, textBuffer );
}
}
}
// Make a full path name
char szPath[MAX_PATH];
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME );
CUtlBuffer buffer;
headBlock->RecursiveSaveToFile( buffer, 0 );
SaveUtlBufferToFile( buffer, szPath );
// Rename the old INI file
char newFilePath[MAX_PATH];
Q_snprintf( newFilePath, sizeof( newFilePath ), "%s.OLD", iniFilePath );
rename( iniFilePath, newFilePath );
// Notify that we were converted
m_LoadStatus = LOADSTATUS_CONVERTED;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Write out a game configuration file
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CGameConfigManager::SaveConfigs( const char *baseDir )
{
if ( !IsLoaded() )
return false;
// Build our default directory
if ( baseDir != NULL && baseDir[0] != NULL )
{
SetBaseDirectory( baseDir );
}
// Make a full path name
char szPath[MAX_PATH];
Q_strncpy( szPath, GetBaseDirectory(), sizeof(szPath) );
Q_AppendSlash( szPath, sizeof(szPath) );
Q_strncat( szPath, GAME_CONFIG_FILENAME, sizeof( szPath ), COPY_ALL_CHARACTERS );
CUtlBuffer buffer;
m_pData->RecursiveSaveToFile( buffer, 0 );
return SaveUtlBufferToFile( buffer, szPath );
}
//-----------------------------------------------------------------------------
// Purpose: Find the directory our .exe is based out of
//-----------------------------------------------------------------------------
const char *CGameConfigManager::GetBaseDirectory( void )
{
return m_szBaseDirectory;
}
//-----------------------------------------------------------------------------
// Purpose: Find the root directory
//-----------------------------------------------------------------------------
const char *CGameConfigManager::GetRootDirectory( void )
{
static char path[MAX_PATH] = {0};
if ( path[0] == 0 )
{
Q_strncpy( path, GetBaseDirectory(), sizeof( path ) );
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the 'bin' directory
Q_StripTrailingSlash( path );
if ( g_pFullFileSystem && g_pFullFileSystem->IsSteam() )
{
Q_StripLastDir( path, sizeof( path ) ); // // Get rid of the 'orangebox' directory
Q_StripTrailingSlash( path );
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the 'bin' directory
Q_StripTrailingSlash( path );
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the 'sourcesdk' directory
Q_StripTrailingSlash( path );
}
}
return path;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the game configuation block
//-----------------------------------------------------------------------------
KeyValues *CGameConfigManager::GetGameBlock( void )
{
if ( !IsLoaded() )
return NULL;
return ( m_pData->FindKey( TOKEN_GAMES ) );
}
//-----------------------------------------------------------------------------
// Purpose: Returns a piece of the game configuation block of the given name
// Input : *keyName - name of the block to return
//-----------------------------------------------------------------------------
KeyValues *CGameConfigManager::GetGameSubBlock( const char *keyName )
{
if ( !IsLoaded() )
return NULL;
KeyValues *pGameBlock = GetGameBlock();
if ( pGameBlock == NULL )
return NULL;
// Return the data
KeyValues *pSubBlock = pGameBlock->FindKey( keyName );
return pSubBlock;
}
//-----------------------------------------------------------------------------
// Purpose: Get the gamecfg.ini file for conversion
//-----------------------------------------------------------------------------
const char *CGameConfigManager::GetIniFilePath( void )
{
static char iniFilePath[MAX_PATH] = {0};
if ( iniFilePath[0] == 0 )
{
Q_strncpy( iniFilePath, GetBaseDirectory(), sizeof( iniFilePath ) );
Q_strncat( iniFilePath, "\\gamecfg.ini", sizeof( iniFilePath ), COPY_ALL_CHARACTERS );
}
return iniFilePath;
}
//-----------------------------------------------------------------------------
// Purpose: Deletes the current config and recreates it with default values
//-----------------------------------------------------------------------------
bool CGameConfigManager::ResetConfigs( const char *baseDir /*= NULL*/ )
{
// Build our default directory
if ( baseDir != NULL && baseDir[0] != NULL )
{
SetBaseDirectory( baseDir );
}
// Make a full path name
char szPath[MAX_PATH];
Q_snprintf( szPath, sizeof( szPath ), "%s\\%s", GetBaseDirectory(), GAME_CONFIG_FILENAME );
// Delete the file
if ( unlink( szPath ) )
return false;
// Load the file again (causes defaults to be created)
if ( LoadConfigsInternal( baseDir, false ) == false )
return false;
// Save it out
return SaveConfigs( baseDir );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameConfigManager::SetBaseDirectory( const char *pDirectory )
{
// Clear it
if ( pDirectory == NULL || pDirectory[0] == '\0' )
{
m_szBaseDirectory[0] = '\0';
return;
}
// Copy it
Q_strncpy( m_szBaseDirectory, pDirectory, sizeof( m_szBaseDirectory ) );
Q_StripTrailingSlash( m_szBaseDirectory );
}
//-----------------------------------------------------------------------------
// Purpose: Create a block of keyvalues containing our default configurations
// Output : A block of keyvalues
//-----------------------------------------------------------------------------
bool CGameConfigManager::GetDefaultGameBlock( KeyValues *pIn )
{
CUtlVector<defaultConfigInfo_t> defaultConfigs;
// Add HL2 games to list
if ( m_eSDKEpoch == SDK_EPOCH_HL2 || m_eSDKEpoch == SDK_EPOCH_EP1 )
{
defaultConfigs.AddToTail( HL2Info );
defaultConfigs.AddToTail( CStrikeInfo );
defaultConfigs.AddToTail( HL2DMInfo );
}
// Add EP1 game to list
if ( m_eSDKEpoch == SDK_EPOCH_EP1 )
{
defaultConfigs.AddToTail( Episode1Info );
}
// Add EP2 games to list
if ( m_eSDKEpoch == SDK_EPOCH_EP2 )
{
defaultConfigs.AddToTail( Episode2Info );
}
if ( m_eSDKEpoch == SDK_EPOCH_PORTAL2 )
{
defaultConfigs.AddToTail( Portal2Info );
}
// CSS 1.5
if ( m_eSDKEpoch == SDK_EPOCH_CSS15 )
{
defaultConfigs.AddToTail( CStrike15Info );
}
if ( pIn == NULL )
return false;
char szPath[MAX_PATH];
// Add all default configs
int nNumConfigs = defaultConfigs.Count();
for ( int i = 0; i < nNumConfigs; i++ )
{
// If it's installed, add it
if ( IsAppSubscribed( defaultConfigs[i].steamAppID ) )
{
GetRootGameDirectory( szPath, sizeof( szPath ), GetRootDirectory(), defaultConfigs[i].steamPath );
AddDefaultConfig( defaultConfigs[i], pIn, GetRootDirectory(), szPath );
}
}
return true;
}

135
common/ConfigManager.h Normal file
View File

@ -0,0 +1,135 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CONFIGMANAGER_H
#define CONFIGMANAGER_H
#ifdef _WIN32
#pragma once
#endif
#include "keyvalues.h"
#include "utlvector.h"
#include "filesystem_init.h"
// See filesystem_init for the vconfig registry values.
#define TOKEN_GAMES "Games"
#define TOKEN_GAME_DIRECTORY "GameDir"
#define TOKEN_TOOLS "Tools"
// STEAM CLOUD FLAGS
#define STEAMREMOTESTORAGE_CLOUD_CONFIG (1<<0)
#define STEAMREMOTESTORAGE_CLOUD_ALL 0x7fff // all bits set, so any new items added will be on by default
struct defaultConfigInfo_t
{
char gameName[MAX_PATH];
char gameDir[MAX_PATH];
char FGD[MAX_PATH];
char steamPath[MAX_PATH];
char defaultPointEntity[MAX_PATH];
char exeName[MAX_PATH];
int steamAppID;
};
enum eSDKEpochs
{
SDK_EPOCH_HL2 = 1,
SDK_EPOCH_EP1 = 2,
SDK_EPOCH_EP2 = 3,
SDK_EPOCH_PORTAL2 = 4,
SDK_EPOCH_CSS15 = 5,
};
extern defaultConfigInfo_t *gDefaultConfigs[];
class CGameConfigManager
{
public:
enum loadStatus_t
{
LOADSTATUS_NONE = 0, // Configs were loaded with no error
LOADSTATUS_CONVERTED, // GameConfig.txt did not exist and was created by converting GameCfg.INI
LOADSTATUS_CREATED, // GameCfg.INI was not found, the system created the default configuration based on found GameInfo.txt resources
LOADSTATUS_ERROR, // File was not loaded and was unable to perform the above fail-safe procedures
};
CGameConfigManager( void );
CGameConfigManager( const char *fileName );
~CGameConfigManager( void );
bool LoadConfigs( const char *baseDir = NULL );
bool SaveConfigs( const char *baseDir = NULL );
bool ResetConfigs( const char *baseDir = NULL );
int GetNumConfigs( void );
KeyValues *GetGameBlock( void );
KeyValues *GetGameSubBlock( const char *keyName );
bool GetDefaultGameBlock( KeyValues *pIn );
bool IsLoaded( void ) const { return m_pData != NULL; }
bool WasConvertedOnLoad( void ) const { return m_LoadStatus == LOADSTATUS_CONVERTED; }
bool WasCreatedOnLoad( void ) const { return m_LoadStatus == LOADSTATUS_CREATED; }
bool AddDefaultConfig( const defaultConfigInfo_t &info, KeyValues *out, const char *rootDirectory, const char *gameExeDir );
void SetBaseDirectory( const char *pDirectory );
void GetRootGameDirectory( char *out, size_t outLen, const char *rootDir, const char *steamDir );
const char *GetRootDirectory( void );
void SetSDKEpoch( eSDKEpochs epoch ) { m_eSDKEpoch = epoch; };
static bool IsSDKDeployment()
{
static bool bRetVal = false;
static bool bInitialized = false;
if ( g_pFullFileSystem && !bInitialized )
{
char szBaseDirectory[MAX_PATH];
// Check to see whether 'steamapps/common' is part of the path to this EXE
g_pFullFileSystem->GetCurrentDirectory( szBaseDirectory, sizeof( szBaseDirectory ) );
V_FixSlashes( szBaseDirectory, '/' );
bRetVal = ( V_stristr( szBaseDirectory, "steamapps/common" ) != NULL );
bInitialized = true;
}
return ( bRetVal );
};
private:
void GetRootContentDirectory( char *out, size_t outLen, const char *rootDir );
const char *GetBaseDirectory( void );
const char *GetIniFilePath( void );
bool LoadConfigsInternal( const char *baseDir, bool bRecursiveCall );
void UpdateConfigsInternal( void );
void VersionConfig( void );
bool IsConfigCurrent( void );
bool ConvertGameConfigsINI( void );
bool CreateAllDefaultConfigs( void );
bool IsAppSubscribed( int nAppID );
loadStatus_t m_LoadStatus; // Holds various state about what occured while loading
KeyValues *m_pData; // Data as read from configuration file
char m_szBaseDirectory[MAX_PATH]; // Default directory
eSDKEpochs m_eSDKEpoch; // Holds the "working version" of the SDK for times when we need to create an older set of game configurations.
// This is required now that the SDK is deploying the tools for both the latest and previous versions of the engine.
};
#endif // CONFIGMANAGER_H

94
common/FindSteamServers.h Normal file
View File

@ -0,0 +1,94 @@
//*********** (C) Copyright 2003 Valve Corporation All rights reserved. ***********
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//*****************************************************************************
//
// Contents:
//
//
//
// Authors: Taylor Sherman
//
// Target restrictions:
//
// Tool restrictions:
//
// Things to do:
//
//
//
//*****************************************************************************
#ifndef INCLUDED_STEAM_FINDSTEAMSERVERS_H
#define INCLUDED_STEAM_FINDSTEAMSERVERS_H
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
#ifdef STEAM_FINDSERVERS_STATIC_LIB
#define STEAM_FSS_CALL
#define STEAM_FSS_API
#else
#ifndef STEAM_API
#ifdef STEAM_EXPORTS
#define STEAM_API __declspec(dllexport)
#else
#define STEAM_API __declspec(dllimport)
#endif
#endif
#ifndef STEAM_CALL
#define STEAM_CALL __cdecl
#endif
#define STEAM_FSS_CALL STEAM_CALL
#define STEAM_FSS_API STEAM_API
#endif
#include <limits.h>
#include "SteamCommon.h"
/******************************************************************************
**
** Types
**
******************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
enum
{
eSteamFindSteamServersLibraryError = -1,
eSteamFindSteamServersLibraryBusy = -2
};
// returns number of IP addresses returned by the GDS for this server type
// negative return means error
STEAM_FSS_API int STEAM_FSS_CALL SteamFindServersNumServers(ESteamServerType eServerType);
// Get nth ipaddr:port for this server type
// buffer needs to be 22 chars long: aaa.bbb.ccc.ddd:12345 plus null
//
// returns 0 if succsessful, negative is error
STEAM_FSS_API int STEAM_FSS_CALL SteamFindServersIterateServer(ESteamServerType eServerType, unsigned int nServer, char *szIpAddrPort, int szIpAddrPortLen);
STEAM_FSS_API const char * STEAM_FSS_CALL SteamFindServersGetErrorString();
#ifdef __cplusplus
}
#endif
#endif /* #ifndef INCLUDED_STEAM2_USERID_STRUCTS */

View File

@ -0,0 +1,44 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef IGAMECONSOLE_H
#define IGAMECONSOLE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
//-----------------------------------------------------------------------------
// Purpose: interface to game/dev console
//-----------------------------------------------------------------------------
abstract_class IGameConsole : public IBaseInterface
{
public:
// activates the console, makes it visible and brings it to the foreground
virtual void Activate() = 0;
virtual void Initialize() = 0;
// hides the console
virtual void Hide() = 0;
// clears the console
virtual void Clear() = 0;
// return true if the console has focus
virtual bool IsConsoleVisible() = 0;
virtual void SetParent( int parent ) = 0;
// hides and deletes panel
virtual void Shutdown( void ) = 0;
};
#define GAMECONSOLE_INTERFACE_VERSION "GameConsole004"
#endif // IGAMECONSOLE_H

141
common/GameUI/IGameUI.h Normal file
View File

@ -0,0 +1,141 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IGAMEUI_H
#define IGAMEUI_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include "vgui/IPanel.h"
#if !defined( _X360 )
#include "xbox/xboxstubs.h"
#endif
class CCommand;
// reasons why the user can't connect to a game server
enum ESteamLoginFailure
{
STEAMLOGINFAILURE_NONE,
STEAMLOGINFAILURE_BADTICKET,
STEAMLOGINFAILURE_NOSTEAMLOGIN,
STEAMLOGINFAILURE_VACBANNED,
STEAMLOGINFAILURE_LOGGED_IN_ELSEWHERE
};
enum ESystemNotify
{
SYSTEMNOTIFY_STORAGEDEVICES_CHANGED,
SYSTEMNOTIFY_USER_SIGNEDIN,
SYSTEMNOTIFY_USER_SIGNEDOUT,
SYSTEMNOTIFY_XLIVE_LOGON_ESTABLISHED, // we are logged into live service
SYSTEMNOTIFY_XLIVE_LOGON_CLOSED, // no longer logged into live - either from natural (signed out) or unnatural (e.g. severed net connection) causes
SYSTEMNOTIFY_XUIOPENING,
SYSTEMNOTIFY_XUICLOSED,
SYSTEMNOTIFY_INVITE_SHUTDOWN, // Cross-game invite is causing us to shutdown
SYSTEMNOTIFY_MUTECHANGED, // Player changed mute settings
SYSTEMNOTIFY_INPUTDEVICESCHANGED, // Input device has changed (used for controller disconnection)
SYSTEMNOTIFY_PROFILE_UNAVAILABLE, // Profile failed to read or write
};
// these are used to show the modal message box on different slots
enum ECommandMsgBoxSlot
{
CMB_SLOT_FULL_SCREEN = -1,
CMB_SLOT_PLAYER_0,
CMB_SLOT_PLAYER_1,
};
//-----------------------------------------------------------------------------
// Purpose: contains all the functions that the GameUI dll exports
//-----------------------------------------------------------------------------
abstract_class IGameUI
{
public:
// initialization/shutdown
virtual void Initialize( CreateInterfaceFn appFactory ) = 0;
virtual void PostInit() = 0;
// connect to other interfaces at the same level (gameui.dll/server.dll/client.dll)
virtual void Connect( CreateInterfaceFn gameFactory ) = 0;
virtual void Start() = 0;
virtual void Shutdown() = 0;
virtual void RunFrame() = 0;
// notifications
virtual void OnGameUIActivated() = 0;
virtual void OnGameUIHidden() = 0;
// OLD: Use OnConnectToServer2
virtual void OLD_OnConnectToServer(const char *game, int IP, int port) = 0;
virtual void OnDisconnectFromServer_OLD( uint8 eSteamLoginFailure, const char *username ) = 0;
virtual void OnLevelLoadingStarted( const char *levelName, bool bShowProgressDialog ) = 0;
virtual void OnLevelLoadingFinished(bool bError, const char *failureReason, const char *extendedReason) = 0;
virtual void StartLoadingScreenForCommand( const char* command ) = 0;
virtual void StartLoadingScreenForKeyValues( KeyValues* keyValues ) = 0;
// level loading progress, returns true if the screen needs updating
virtual bool UpdateProgressBar(float progress, const char *statusText, bool showDialog = true ) = 0;
// Shows progress desc, returns previous setting... (used with custom progress bars )
virtual bool SetShowProgressText( bool show ) = 0;
virtual bool UpdateSecondaryProgressBar(float progress, const wchar_t *desc ) = 0;
// !!!!!!!!!members added after "GameUI011" initial release!!!!!!!!!!!!!!!!!!!
// Allows the level loading progress to show map-specific info
virtual void SetProgressLevelName( const char *levelName ) = 0;
// Xbox 360
virtual void ShowMessageDialog( const uint nType, vgui::Panel *pOwner ) = 0;
virtual void ShowMessageDialog( const char* messageID, const char* titleID ) = 0;
virtual void CreateCommandMsgBox( const char* pszTitle, const char* pszMessage, bool showOk = true, bool showCancel = false, const char* okCommand = NULL, const char* cancelCommand = NULL, const char* closedCommand = NULL, const char* pszLegend = NULL ) = 0;
virtual void CreateCommandMsgBoxInSlot( ECommandMsgBoxSlot slot, const char* pszTitle, const char* pszMessage, bool showOk = true, bool showCancel = false, const char* okCommand = NULL, const char* cancelCommand = NULL, const char* closedCommand = NULL, const char* pszLegend = NULL ) = 0;
// inserts specified panel as background for level load dialog
virtual void SetLoadingBackgroundDialog( vgui::VPANEL panel ) = 0;
virtual void OnConnectToServer2(const char *game, int IP, int connectionPort, int queryPort) = 0;
virtual void SetProgressOnStart() = 0;
virtual void OnDisconnectFromServer( uint8 eSteamLoginFailure ) = 0;
/*
virtual void OnConfirmQuit( void ) = 0;
virtual bool IsMainMenuVisible( void ) = 0;
// Client DLL is providing us with a panel that it wants to replace the main menu with
virtual void SetMainMenuOverride( vgui::VPANEL panel ) = 0;
// Client DLL is telling us that a main menu command was issued, probably from its custom main menu panel
virtual void SendMainMenuCommand( const char *pszCommand ) = 0;
*/
virtual void NeedConnectionProblemWaitScreen() = 0;
virtual void ShowPasswordUI( char const *pchCurrentPW ) = 0;
#if defined( _X360 ) && defined( _DEMO )
virtual void OnDemoTimeout( void ) = 0;
#endif
virtual bool LoadingProgressWantsIsolatedRender( bool bContextValid ) = 0;
virtual bool IsPlayingFullScreenVideo() = 0;
virtual bool IsTransitionEffectEnabled() = 0;
virtual bool IsInLevel() = 0;
virtual void RestoreTopLevelMenu() = 0;
};
#define GAMEUI_INTERFACE_VERSION "GameUI011"
#endif // IGAMEUI_H

View File

@ -0,0 +1,247 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include <stdio.h>
// dgoodenough - malloc.h doesn't exist on PS3
// PS3_BUILDFIX
#if !defined( _PS3 )
#include <malloc.h>
#endif
#include "ObjectList.h"
#include "tier1/strtools.h"
//#include "port.h"
//#include "mem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ObjectList::ObjectList()
{
head = tail = current = NULL;
number = 0;
}
ObjectList::~ObjectList()
{
Clear( false );
}
bool ObjectList::AddHead(void * newObject)
{
// create new element
element_t * newElement = (element_t *) calloc(1, sizeof(element_t));
if (newElement == NULL )
return false; // out of memory
// insert element
newElement->object = newObject;
if (head)
{
newElement->next = head;
head->prev = newElement;
};
head = newElement;
// if list was empty set new tail
if (tail==NULL) tail = head;
number++;
return true;
}
void * ObjectList::RemoveHead()
{
void * retObj;
// check head is present
if (head)
{
retObj = head->object;
element_t * newHead = head->next;
if (newHead) newHead->prev = NULL;
// if only one element is in list also update tail
// if we remove this prev element
if (tail==head) tail = NULL;
free(head);
head = newHead;
number--;
} else
retObj = NULL;
return retObj;
}
bool ObjectList::AddTail(void * newObject)
{
element_t * newElement = (element_t *) calloc(1, sizeof(element_t));
if (newElement == NULL)
return false; // out of memory;
newElement->object = newObject;
if (tail)
{
newElement->prev = tail;
tail->next = newElement;
}
tail = newElement;
// if list was empty set new head
if (head==NULL) head = tail;
number++;
return true;
}
void * ObjectList::RemoveTail()
{
void * retObj;
// check tail is present
if (tail)
{
retObj = tail->object;
element_t * newTail = tail->prev;
if (newTail) newTail->next = NULL;
// if only one element is in list also update tail
// if we remove this prev element
if (head==tail) head = NULL;
free(tail);
tail = newTail;
number--;
} else
retObj = NULL;
return retObj;
}
bool ObjectList::IsEmpty()
{
return ( head == NULL );
}
int ObjectList::CountElements()
{
return number;
}
bool ObjectList::Contains(void * object)
{
element_t * e = head;
while(e && e->object!=object) { e = e->next;}
if ( e )
{
current = e;
return true;
}
else
{
return false;
}
}
void ObjectList::Clear( bool freeElementsMemory )
{
element_t * ne;
element_t * e = head;
while(e)
{
ne = e->next;
if ( freeElementsMemory && e->object )
free( e->object );
free(e);
e = ne;
}
head = tail = current = NULL;
number = 0;
}
bool ObjectList::Remove( void * object )
{
element_t * e = head;
while(e && e->object!=object) { e = e->next;}
if (e!=NULL)
{
if (e->prev) e->prev->next = e->next;
if (e->next) e->next->prev = e->prev;
if (head==e) head = e->next;
if (tail==e) tail = e->prev;
if (current == e) current= e->next;
free(e);
number--;
}
return (e!=NULL);
}
void ObjectList::Init()
{
head = tail = current = NULL;
number = 0;
}
void * ObjectList::GetFirst()
{
if (head)
{
current = head->next;
return head->object;
}
else
{
current = NULL;
return NULL;
};
}
void * ObjectList::GetNext()
{
void * retObj = NULL;
if (current)
{
retObj = current->object;
current = current->next;
}
return retObj;
}
bool ObjectList::Add(void *newObject)
{
return AddTail( newObject );
}

View File

@ -0,0 +1,58 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// ObjectList.h: interface for the ObjectList class.
//
//////////////////////////////////////////////////////////////////////
#ifndef OBJECTLIST_H
#define OBJECTLIST_H
#pragma once
#include "IObjectContainer.h" // Added by ClassView
class ObjectList : public IObjectContainer
{
public:
void Init();
bool Add( void * newObject );
void * GetFirst();
void * GetNext();
ObjectList();
virtual ~ObjectList();
void Clear( bool freeElementsMemory );
int CountElements();
void * RemoveTail();
void * RemoveHead();
bool AddTail(void * newObject);
bool AddHead(void * newObject);
bool Remove(void * object);
bool Contains(void * object);
bool IsEmpty();
typedef struct element_s {
element_s * prev; // pointer to the last element or NULL
element_s * next; // pointer to the next elemnet or NULL
void * object; // the element's object
} element_t;
protected:
element_t * head; // first element in list
element_t * tail; // last element in list
element_t * current; // current element in list
int number;
};
#endif // !defined

129
common/GameUI/Random.cpp Normal file
View File

@ -0,0 +1,129 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Basic random number generator
//
// $NoKeywords: $
//===========================================================================//
#include <time.h>
#include "Random.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define IA 16807
#define IM 2147483647
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
static long idum = 0;
void SeedRandomNumberGenerator(long lSeed)
{
if (lSeed)
{
idum = lSeed;
}
else
{
idum = -time(NULL);
}
if (1000 < idum)
{
idum = -idum;
}
else if (-1000 < idum)
{
idum -= 22261048;
}
}
long ran1(void)
{
int j;
long k;
static long iy=0;
static long iv[NTAB];
if (idum <= 0 || !iy)
{
if (-(idum) < 1) idum=1;
else idum = -(idum);
for (j=NTAB+7;j>=0;j--)
{
k=(idum)/IQ;
idum=IA*(idum-k*IQ)-IR*k;
if (idum < 0) idum += IM;
if (j < NTAB) iv[j] = idum;
}
iy=iv[0];
}
k=(idum)/IQ;
idum=IA*(idum-k*IQ)-IR*k;
if (idum < 0) idum += IM;
j=iy/NDIV;
iy=iv[j];
iv[j] = idum;
return iy;
}
// fran1 -- return a random floating-point number on the interval [0,1)
//
#define AM (1.0/IM)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
float fran1(void)
{
float temp = (float)AM*ran1();
if (temp > RNMX) return (float)RNMX;
else return temp;
}
float RandomFloat( float flLow, float flHigh )
{
if (idum == 0)
{
SeedRandomNumberGenerator(0);
}
float fl = fran1(); // float in [0,1)
return (fl * (flHigh-flLow)) + flLow; // float in [low,high)
}
long RandomLong( long lLow, long lHigh )
{
if (idum == 0)
{
SeedRandomNumberGenerator(0);
}
unsigned long maxAcceptable;
unsigned long x = lHigh-lLow+1;
unsigned long n;
if (x <= 0 || MAX_RANDOM_RANGE < x-1)
{
return lLow;
}
// The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE]
// to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
// the uniform distribution unfavorably. Even for a worst case x, the loop is
// guaranteed to be taken no more than half the time, so for that worst case x,
// the average number of times through the loop is 2. For cases where x is
// much smaller than MAX_RANDOM_RANGE, the average number of times through the
// loop is very close to 1.
//
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
do
{
n = ran1();
} while (n > maxAcceptable);
return lLow + (n % x);
}

30
common/GameUI/Random.h Normal file
View File

@ -0,0 +1,30 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Generalized 32-bit random number generator
// Range is 0x00000000 - 0x7FFFFFFF
//
// $NoKeywords: $
//=============================================================================//
#ifndef RANDOM_H
#define RANDOM_H
#ifdef _WIN32
#pragma once
#endif
// the random number seeding is automatic
#define MAX_RANDOM_RANGE 0x7FFFFFFFUL
// restarts random generator
// setting lSeed to 0 causes the current time to be used as the seed
// random number generator will automatically seed itself on first use with current time if this is not called
extern void SeedRandomNumberGenerator(long lSeed = 0);
// returns a random integer of range [low, high]
extern long RandomLong( long lLow, long lHigh );
// returns a random float of range [low, high)
extern float RandomFloat( float flLow, float flHigh );
#endif // RANDOM_H

43
common/IAdminServer.h Normal file
View File

@ -0,0 +1,43 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IADMINSERVER_H
#define IADMINSERVER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
// handle to a game window
typedef unsigned int ManageServerUIHandle_t;
class IManageServer;
//-----------------------------------------------------------------------------
// Purpose: Interface to server administration functions
//-----------------------------------------------------------------------------
abstract_class IAdminServer : public IBaseInterface
{
public:
// opens a manage server dialog for a local server
virtual ManageServerUIHandle_t OpenManageServerDialog(const char *serverName, const char *gameDir) = 0;
// opens a manage server dialog to a remote server
virtual ManageServerUIHandle_t OpenManageServerDialog(unsigned int gameIP, unsigned int gamePort, const char *password) = 0;
// forces the game info dialog closed
virtual void CloseManageServerDialog(ManageServerUIHandle_t gameDialog) = 0;
// Gets a handle to the interface
virtual IManageServer *GetManageServerInterface(ManageServerUIHandle_t handle) = 0;
};
#define ADMINSERVER_INTERFACE_VERSION "AdminServer002"
#endif // IAdminServer_H

View File

@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef IFILESYSTEMOPENDIALOG_H
#define IFILESYSTEMOPENDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#define FILESYSTEMOPENDIALOG_VERSION "FileSystemOpenDlg003"
class IFileSystem;
abstract_class IFileSystemOpenDialog
{
public:
// You must call this first to set the hwnd.
virtual void Init( CreateInterfaceFn factory, void *parentHwnd ) = 0;
// Call this to free the dialog.
virtual void Release() = 0;
// Use these to configure the dialog.
virtual void AddFileMask( const char *pMask ) = 0;
virtual void SetInitialDir( const char *pDir, const char *pPathID = NULL ) = 0;
virtual void SetFilterMdlAndJpgFiles( bool bFilter ) = 0;
virtual void GetFilename( char *pOut, int outLen ) const = 0; // Get the filename they chose.
// Call this to make the dialog itself. Returns true if they clicked OK and false
// if they canceled it.
virtual bool DoModal() = 0;
// This uses the standard windows file open dialog.
virtual bool DoModal_WindowsDialog() = 0;
// Mark the dialog as allowing us to multi-select
virtual void AllowMultiSelect( bool bAllow ) = 0;
// Request the length of the buffer sufficient enough to hold the entire filename result
virtual int GetFilenameBufferSize() const = 0;
};
#endif // IFILESYSTEMOPENDIALOG_H

34
common/IManageServer.h Normal file
View File

@ -0,0 +1,34 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IMANAGESERVER_H
#define IMANAGESERVER_H
#ifdef _WIN32
#pragma once
#endif
#include <interface.h>
//-----------------------------------------------------------------------------
// Purpose: basic callback interface for the manage server list, to update status text et al
//-----------------------------------------------------------------------------
abstract_class IManageServer : public IBaseInterface
{
public:
// activates the manage page
virtual void ShowPage() = 0;
// sets whether or not the server is remote
virtual void SetAsRemoteServer(bool remote) = 0;
// prints text to the console
virtual void AddToConsole(const char *msg) = 0;
};
#define IMANAGESERVER_INTERFACE_VERSION "IManageServer002"
#endif // IMANAGESERVER_H

32
common/IObjectContainer.h Normal file
View File

@ -0,0 +1,32 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: IObjectContainer.h: interface for the ObjectContainer class.
//
// $NoKeywords: $
//=============================================================================//
#ifndef IOBJECTCONTAINER_H
#define IOBJECTCONTAINER_H
#pragma once
class IObjectContainer
{
public:
virtual ~IObjectContainer() {};
virtual void Init() = 0;
virtual bool Add(void * newObject) = 0;
virtual bool Remove(void * object) = 0;
virtual void Clear(bool freeElementsMemory) = 0;
virtual void * GetFirst() = 0;
virtual void * GetNext() = 0;
virtual int CountElements() = 0;;
virtual bool Contains(void * object) = 0;
virtual bool IsEmpty() = 0;
};
#endif // !defined IOBJECTCONTAINER_H

81
common/IRunGameEngine.h Normal file
View File

@ -0,0 +1,81 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IRUNGAMEENGINE_H
#define IRUNGAMEENGINE_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#ifdef GetUserName
#undef GetUserName
#endif
//-----------------------------------------------------------------------------
// Purpose: Interface to running the game engine
//-----------------------------------------------------------------------------
abstract_class IRunGameEngine : public IBaseInterface
{
public:
// Returns true if the engine is running, false otherwise.
virtual bool IsRunning() = 0;
// Adds text to the engine command buffer. Only works if IsRunning()
// returns true on success, false on failure
virtual bool AddTextCommand(const char *text) = 0;
// runs the engine with the specified command line parameters. Only works if !IsRunning()
// returns true on success, false on failure
virtual bool RunEngine(const char *gameDir, const char *commandLineParams) = 0;
// returns true if the player is currently connected to a game server
virtual bool IsInGame() = 0;
// gets information about the server the engine is currently connected to
// returns true on success, false on failure
virtual bool GetGameInfo(char *infoBuffer, int bufferSize) = 0;
// tells the engine our userID
virtual void SetTrackerUserID(int trackerID, const char *trackerName) = 0;
// this next section could probably moved to another interface
// iterates users
// returns the number of user
virtual int GetPlayerCount() = 0;
// returns a playerID for a player
// playerIndex is in the range [0, GetPlayerCount)
virtual unsigned int GetPlayerFriendsID(int playerIndex) = 0;
// gets the in-game name of another user, returns NULL if that user doesn't exists
virtual const char *GetPlayerName(int friendsID) = 0;
// gets the friends name of a player
virtual const char *GetPlayerFriendsName(int friendsID) = 0;
// returns the engine build number and mod version string for server versioning
virtual unsigned int GetEngineBuildNumber() = 0;
virtual const char *GetProductVersionString() = 0;
// new interface to RunEngine (done so we don't have to roll the interface version)
virtual bool RunEngine2(const char *gameDir, const char *commandLineParams, bool isSourceGame) = 0;
enum ERunResult
{
k_ERunResultOkay = 0,
k_ERunResultModNotInstalled = 1,
k_ERunResultAppNotFound = 2,
k_ERunResultNotInitialized = 3,
};
virtual ERunResult RunEngine( int iAppID, const char *gameDir, const char *commandLineParams ) = 0;
};
#define RUNGAMEENGINE_INTERFACE_VERSION "RunGameEngine005"
#endif // IRUNGAMEENGINE_H

View File

@ -0,0 +1,33 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IVGUIMODULELOADER_H
#define IVGUIMODULELOADER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
//-----------------------------------------------------------------------------
// Purpose: interface to accessing all loaded modules
//-----------------------------------------------------------------------------
abstract_class IVGuiModuleLoader : public IBaseInterface
{
public:
virtual int GetModuleCount() = 0;
virtual const char *GetModuleLabel(int moduleIndex) = 0;
virtual CreateInterfaceFn GetModuleFactory(int moduleIndex) = 0;
virtual bool ActivateModule(int moduleIndex) = 0;
virtual bool ActivateModule(const char *moduleName) = 0;
virtual void SetPlatformToRestart() = 0;
};
#define VGUIMODULELOADER_INTERFACE_VERSION "VGuiModuleLoader003"
#endif // IVGUIMODULELOADER_H

64
common/IVguiModule.h Normal file
View File

@ -0,0 +1,64 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IVGUIMODULE_H
#define IVGUIMODULE_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include <vgui/vgui.h>
//-----------------------------------------------------------------------------
// Purpose: Standard interface to loading vgui modules
//-----------------------------------------------------------------------------
abstract_class IVGuiModule : public IBaseInterface
{
public:
// called first to setup the module with the vgui
// returns true on success, false on failure
virtual bool Initialize(CreateInterfaceFn *vguiFactories, int factoryCount) = 0;
// called after all the modules have been initialized
// modules should use this time to link to all the other module interfaces
virtual bool PostInitialize(CreateInterfaceFn *modules, int factoryCount) = 0;
// called when the module is selected from the menu or otherwise activated
virtual bool Activate() = 0;
// returns true if the module is successfully initialized and available
virtual bool IsValid() = 0;
// requests that the UI is temporarily disabled and all data files saved
virtual void Deactivate() = 0;
// restart from a Deactivate()
virtual void Reactivate() = 0;
// called when the module is about to be shutdown
virtual void Shutdown() = 0;
// returns a handle to the main module panel
virtual vgui::VPANEL GetPanel() = 0;
// sets the parent of the main module panel
virtual void SetParent(vgui::VPANEL parent) = 0;
// messages sent through through the panel returned by GetPanel():
//
// "ConnectedToGame" "ip" "port" "gamedir"
// "DisconnectedFromGame"
// "ActiveGameName" "name"
// "LoadingStarted" "type" "name"
// "LoadingFinished" "type" "name"
};
#define VGUIMODULE_INTERFACE_VERSION "VGuiModule002"
#endif // IVGUIMODULE_H

View File

@ -0,0 +1,45 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ISERVERBROWSER_H
#define ISERVERBROWSER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
//-----------------------------------------------------------------------------
// Purpose: Interface to server browser module
//-----------------------------------------------------------------------------
abstract_class IServerBrowser
{
public:
// activates the server browser window, brings it to the foreground
virtual bool Activate() = 0;
// joins a game directly
virtual bool JoinGame( uint32 unGameIP, uint16 usGamePort ) = 0;
// joins a specified game - game info dialog will only be opened if the server is fully or passworded
virtual bool JoinGame( uint64 ulSteamIDFriend ) = 0;
// opens a game info dialog to watch the specified server; associated with the friend 'userName'
virtual bool OpenGameInfoDialog( uint64 ulSteamIDFriend ) = 0;
// forces the game info dialog closed
virtual void CloseGameInfoDialog( uint64 ulSteamIDFriend ) = 0;
// closes all the game info dialogs
virtual void CloseAllGameInfoDialogs() = 0;
};
#define SERVERBROWSER_INTERFACE_VERSION "ServerBrowser003"
#endif // ISERVERBROWSER_H

92
common/SourceAppInfo.cpp Normal file
View File

@ -0,0 +1,92 @@
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
//
// Purpose: languages definition
//
//=============================================================================
#include "SourceAppInfo.h"
#include "tier0/dbg.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
struct SourceAppInfo_t
{
char *m_pchFullName;
char *m_pchModName;
int m_nSteamAppId;
ESourceApp m_ESourceApp;
};
static SourceAppInfo_t s_SteamAppInfo[] =
{
{ "Source SDK Base", "sourcetest", 215, k_App_SDK_BASE },
{ "Half-Life 2", "hl2", 220, k_App_HL2 } ,
{ "Counter-Strike: Source", "cstrike", 240, k_App_CSS } ,
{ "Day of Defeat: Source", "dod", 300, k_App_DODS } ,
{ "Half-Life 2: Deathmatch", "hl2mp", 320, k_App_HL2MP } ,
{ "Half-Life 2: Lost Coast", "lostcoast", 340, k_App_LOST_COAST } ,
{ "Half-Life Deathmatch: Source", "hl1mp", 360, k_App_HL1DM } ,
{ "Half-Life 2: Episode One", "episodic", 380, k_App_HL2_EP1 },
{ "Portal", "portal", 400, k_App_PORTAL } ,
{ "Half-Life 2: Episode Two", "ep2", 420, k_App_HL2_EP2 } ,
{ "Team Fortress 2", "tf", 440, k_App_TF2 } ,
#ifdef _DEMO
{ "Left 4 Dead Demo", "left4dead", 530, k_App_L4D } ,
#else
{ "Left 4 Dead", "left4dead", 500, k_App_L4D } ,
#endif
{ "Portal 2", "portal2", 620, k_App_PORTAL2 } ,
{ "Counter-Strike: Global Offensive Dev", "csgo", 710, k_App_CSS15_DEV } ,
{ "Counter-Strike: Global Offensive", "csgo", 730, k_App_CSS15 } ,
};
//-----------------------------------------------------------------------------
// Purpose: return the short string name used for this language by SteamUI
//-----------------------------------------------------------------------------
const char *GetAppFullName( ESourceApp eSourceApp )
{
Assert( Q_ARRAYSIZE(s_SteamAppInfo) == k_App_MAX );
if ( s_SteamAppInfo[ eSourceApp ].m_ESourceApp == eSourceApp )
{
return s_SteamAppInfo[ eSourceApp ].m_pchFullName;
}
Assert( !"enum ESourceApp order mismatched from AppInfo_t s_SteamAppInfo, fix it!" );
return s_SteamAppInfo[0].m_pchFullName;
}
//-----------------------------------------------------------------------------
// Purpose: return the short string name used for this language by SteamUI
//-----------------------------------------------------------------------------
const char *GetAppModName( ESourceApp eSourceApp )
{
Assert( Q_ARRAYSIZE(s_SteamAppInfo) >= k_App_MAX ); // the last entry is duplicated
if ( s_SteamAppInfo[ eSourceApp ].m_ESourceApp == eSourceApp )
{
return s_SteamAppInfo[ eSourceApp ].m_pchModName;
}
Assert( !"enum ESourceApp order mismatched from AppInfo_t s_SteamAppInfo, fix it!" );
return s_SteamAppInfo[0].m_pchModName;
}
//-----------------------------------------------------------------------------
// Purpose: return the short string name used for this language by SteamUI
//-----------------------------------------------------------------------------
const int GetAppSteamAppId( ESourceApp eSourceApp )
{
Assert( Q_ARRAYSIZE( s_SteamAppInfo ) >= k_App_MAX ); // the last entry is duplicated
if ( s_SteamAppInfo[ eSourceApp ].m_ESourceApp == eSourceApp )
{
return s_SteamAppInfo[ eSourceApp ].m_nSteamAppId;
}
Assert( !"enum ESourceApp order mismatched from AppInfo_t s_SteamAppInfo, fix it!" );
return s_SteamAppInfo[0].m_nSteamAppId;
}

31
common/SourceAppInfo.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef SOURCE_APP_INFO_H
#define SOURCE_APP_INFO_H
#ifdef _WIN32
#pragma once
#endif
enum ESourceApp
{
k_App_SDK_BASE = 0,
k_App_HL2,
k_App_CSS,
k_App_DODS,
k_App_HL2MP,
k_App_LOST_COAST,
k_App_HL1DM,
k_App_HL2_EP1,
k_App_PORTAL,
k_App_HL2_EP2,
k_App_TF2,
k_App_L4D,
k_App_PORTAL2,
k_App_CSS15_DEV,
k_App_CSS15,
k_App_MAX
};
const int GetAppSteamAppId( ESourceApp eSourceApp );
const char *GetAppModName( ESourceApp eSourceApp );
const char *GetAppFullName( ESourceApp eSourceApp );
#endif

218
common/Steam.h Normal file
View File

@ -0,0 +1,218 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/**
** Contents:
**
** This file provides the public interface to the Steam service. This
** interface is described in the SDK documentation.
**
******************************************************************************/
#ifndef INCLUDED_STEAM_H
#define INCLUDED_STEAM_H
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
#ifndef INCLUDED_STEAM2_USERID_STRUCTS
#include "SteamCommon.h"
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/******************************************************************************
**
** Exported function prototypes
**
******************************************************************************/
/*
** Engine control
**
** It is the responsibility of the Steam Bootstrapper (Steam.exe) to start
** and stop the Steam Engine at the appropriate times.
**
** However, to properly handle some operating-system messages, the UI may need
** to call a Shutdown. For instance, WM_ENDSESSION will terminate the process after
** being handled -- so we should do as much cleanup as possible first.
*/
STEAM_API int STEAM_CALL SteamStartEngine(TSteamError *pError);
STEAM_API int STEAM_CALL SteamShutdownEngine(TSteamError *pError);
/*
** Initialization and misc
*/
STEAM_API int STEAM_CALL SteamStartup( unsigned int uUsingMask, TSteamError *pError );
STEAM_API int STEAM_CALL SteamCleanup( TSteamError *pError );
STEAM_API unsigned int STEAM_CALL SteamNumAppsRunning( TSteamError *pError );
STEAM_API void STEAM_CALL SteamClearError( TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetVersion( char *szVersion, unsigned int uVersionBufSize );
/*
** Offline status
*/
STEAM_API int STEAM_CALL SteamGetOfflineStatus( TSteamOfflineStatus *pStatus, TSteamError *pError );
STEAM_API int STEAM_CALL SteamChangeOfflineStatus( TSteamOfflineStatus *pStatus, TSteamError *pError );
/*
** Asynchrounous call handling
*/
STEAM_API int STEAM_CALL SteamProcessCall( SteamCallHandle_t handle, TSteamProgress *pProgress, TSteamError *pError );
STEAM_API int STEAM_CALL SteamAbortCall( SteamCallHandle_t handle, TSteamError *pError );
STEAM_API int STEAM_CALL SteamBlockingCall( SteamCallHandle_t handle, unsigned int uiProcessTickMS, TSteamError *pError );
STEAM_API int STEAM_CALL SteamSetMaxStallCount( unsigned int uNumStalls, TSteamError *pError );
/*
** Filesystem
*/
STEAM_API int STEAM_CALL SteamMountAppFilesystem( TSteamError *pError );
STEAM_API int STEAM_CALL SteamUnmountAppFilesystem( TSteamError *pError );
STEAM_API SteamHandle_t STEAM_CALL SteamMountFilesystem( unsigned int uAppId, const char *szMountPath, TSteamError *pError );
STEAM_API int STEAM_CALL SteamUnmountFilesystem( SteamHandle_t hFs, TSteamError *pError );
STEAM_API int STEAM_CALL SteamStat( const char *cszName, TSteamElemInfo *pInfo, TSteamError *pError );
STEAM_API int STEAM_CALL SteamSetvBuf( SteamHandle_t hFile, void* pBuf, ESteamBufferMethod eMethod, unsigned int uBytes, TSteamError *pError );
STEAM_API int STEAM_CALL SteamFlushFile( SteamHandle_t hFile, TSteamError *pError );
STEAM_API SteamHandle_t STEAM_CALL SteamOpenFile( const char *cszName, const char *cszMode, TSteamError *pError );
STEAM_API SteamHandle_t STEAM_CALL SteamOpenFileEx( const char *cszName, const char *cszMode, unsigned int *puFileSize, TSteamError *pError );
STEAM_API SteamHandle_t STEAM_CALL SteamOpenTmpFile( TSteamError *pError );
STEAM_API int STEAM_CALL SteamCloseFile( SteamHandle_t hFile, TSteamError *pError );
STEAM_API unsigned int STEAM_CALL SteamReadFile( void *pBuf, unsigned int uSize, unsigned int uCount, SteamHandle_t hFile, TSteamError *pError );
STEAM_API unsigned int STEAM_CALL SteamWriteFile( const void *pBuf, unsigned int uSize, unsigned int uCount, SteamHandle_t hFile, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetc( SteamHandle_t hFile, TSteamError *pError );
STEAM_API int STEAM_CALL SteamPutc( int cChar, SteamHandle_t hFile, TSteamError *pError );
STEAM_API int STEAM_CALL SteamPrintFile( SteamHandle_t hFile, TSteamError *pError, const char *cszFormat, ... );
STEAM_API int STEAM_CALL SteamSeekFile( SteamHandle_t hFile, long lOffset, ESteamSeekMethod, TSteamError *pError );
STEAM_API long STEAM_CALL SteamTellFile( SteamHandle_t hFile, TSteamError *pError );
STEAM_API long STEAM_CALL SteamSizeFile( SteamHandle_t hFile, TSteamError *pError );
STEAM_API SteamHandle_t STEAM_CALL SteamFindFirst( const char *cszPattern, ESteamFindFilter eFilter, TSteamElemInfo *pFindInfo, TSteamError *pError );
STEAM_API int STEAM_CALL SteamFindNext( SteamHandle_t hDirectory, TSteamElemInfo *pFindInfo, TSteamError *pError );
STEAM_API int STEAM_CALL SteamFindClose( SteamHandle_t hDirectory, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetLocalFileCopy( const char *cszName, TSteamError *pError );
STEAM_API int STEAM_CALL SteamIsFileImmediatelyAvailable( const char *cszName, TSteamError *pError );
STEAM_API int STEAM_CALL SteamHintResourceNeed( const char *cszMasterList, int bForgetEverything, TSteamError *pError );
STEAM_API int STEAM_CALL SteamForgetAllHints( TSteamError *pError );
STEAM_API int STEAM_CALL SteamPauseCachePreloading( TSteamError *pError );
STEAM_API int STEAM_CALL SteamResumeCachePreloading( TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamWaitForResources( const char *cszMasterList, TSteamError *pError );
/*
** Logging
*/
STEAM_API SteamHandle_t STEAM_CALL SteamCreateLogContext( const char *cszName );
STEAM_API int STEAM_CALL SteamLog( SteamHandle_t hContext, const char *cszMsg );
STEAM_API void STEAM_CALL SteamLogResourceLoadStarted( const char *cszMsg );
STEAM_API void STEAM_CALL SteamLogResourceLoadFinished( const char *cszMsg );
/*
** Account
*/
STEAM_API SteamCallHandle_t STEAM_CALL SteamCreateAccount( const char *cszUser, const char *cszEmailAddress, const char *cszPassphrase, const char *cszCreationKey, const char *cszPersonalQuestion, const char *cszAnswerToQuestion, int *pbCreated, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamIsAccountNameInUse( const char *cszAccountName, int *pbIsUsed, TSteamError *pError);
STEAM_API SteamCallHandle_t STEAM_CALL SteamGenerateSuggestedAccountNames( const char *cszAccountNameToSelectMasterAS, const char *cszGenerateNamesLikeAccountName, char *pSuggestedNamesBuf, unsigned int uBufSize, unsigned int *puNumSuggestedChars, TSteamError *pError);
STEAM_API SteamCallHandle_t STEAM_CALL SteamDeleteAccount( TSteamError *pError );
STEAM_API int STEAM_CALL SteamIsLoggedIn( int *pbIsLoggedIn, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamSetUser( const char *cszUser, int *pbUserSet, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetUser( char *szUser, unsigned int uBufSize, unsigned int *puUserChars, TSteamGlobalUserID *pOptionalReceiveUserID, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamLogin( const char *cszUser, const char *cszPassphrase, int bIsSecureComputer, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamLogout( TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamCreateCachePreloaders( TSteamError *pError );
STEAM_API int STEAM_CALL SteamIsSecureComputer( int *pbIsSecure, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRefreshLogin( const char *cszPassphrase, int bIsSecureComputer, TSteamError * pError );
STEAM_API int STEAM_CALL SteamVerifyPassword( const char *cszPassphrase, int *pbCorrect, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetUserType( unsigned int *puUserTypeFlags, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetAccountStatus( unsigned int *puAccountStatusFlags, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRefreshAccountInfo( TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamSubscribe( unsigned int uSubscriptionId, const TSteamSubscriptionBillingInfo *pSubscriptionBillingInfo, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamUnsubscribe( unsigned int uSubscriptionId, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetSubscriptionReceipt( unsigned int uSubscriptionId, TSteamSubscriptionReceipt *pSubscriptionReceipt, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamAckSubscriptionReceipt( unsigned int uSubscriptionId, TSteamError *pError );
STEAM_API int STEAM_CALL SteamIsSubscribed( unsigned int uSubscriptionId, int *pbIsSubscribed, int *pbIsSubscriptionPending, TSteamError *pError );
STEAM_API int STEAM_CALL SteamIsAppSubscribed( unsigned int uAppId, int *pbIsAppSubscribed, int *pbIsSubscriptionPending, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetSubscriptionStats( TSteamSubscriptionStats *pSubscriptionStats, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetSubscriptionIds( unsigned int *puIds, unsigned int uMaxIds, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateSubscription( unsigned int uId, TSteamSubscription *pSubscription, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateSubscriptionDiscount( unsigned int uSubscriptionId, unsigned int uDiscountIndex, TSteamSubscriptionDiscount *pDiscount, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateSubscriptionDiscountQualifier( unsigned int uSubscriptionId, unsigned int uDiscountIndex, unsigned int uQualifierIndex, TSteamDiscountQualifier *pDiscountQualifier, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetAppStats( TSteamAppStats *pAppStats, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetAppIds( unsigned int *puIds, unsigned int uMaxIds, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateApp( unsigned int uId, TSteamApp *pApp, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateAppLaunchOption( unsigned int uAppId, unsigned int uLaunchOptionIndex, TSteamAppLaunchOption *pLaunchOption, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateAppIcon( unsigned int uAppId, unsigned int uIconIndex, unsigned char *pIconData, unsigned int uIconDataBufSize, unsigned int *puSizeOfIconData, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateAppVersion( unsigned int uAppId, unsigned int uVersionIndex, TSteamAppVersion *pAppVersion, TSteamError *pError );
STEAM_API int STEAM_CALL SteamEnumerateAppDependency( unsigned int uAppId, unsigned int uIndex, TSteamAppDependencyInfo *pDependencyInfo, TSteamError *pError );
STEAM_API int STEAM_CALL SteamInsertAppDependency( unsigned int uAppId, unsigned int uIndex, TSteamAppDependencyInfo *pDependencyInfo, TSteamError *pError );
STEAM_API int STEAM_CALL SteamRemoveAppDependency( unsigned int uAppId, unsigned int uIndex, TSteamError *pError );
STEAM_API int STEAM_CALL SteamFindApp( const char *cszAppName, unsigned int *puAppId, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetAppDependencies( unsigned int uAppId, unsigned int *puCacheIds, unsigned int uMaxIds, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetAppUserDefinedInfo( unsigned int uAppId, const char *cszKey, char *szValueBuf, unsigned int uValueBufLen, unsigned int *puValueLen, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamWaitForAppReadyToLaunch( unsigned int uAppId, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamLaunchApp( unsigned int uAppId, unsigned int uLaunchOption, const char *cszArgs, TSteamError *pError );
STEAM_API int STEAM_CALL SteamIsCacheLoadingEnabled( unsigned int uAppId, int *pbIsLoading, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetCacheFilePath( unsigned int uCacheId, char *szPathBuf, unsigned int uBufSize, unsigned int *puPathChars, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamStartLoadingCache( unsigned int uAppId, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamStopLoadingCache( unsigned int uAppId, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamFlushCache( unsigned int uCacheId, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRepairOrDecryptCaches( unsigned int uAppId, int bForceValidation, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamLoadCacheFromDir( unsigned int uAppId, const char *szPath, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetCacheDefaultDirectory( char *szPath, TSteamError *pError );
STEAM_API int STEAM_CALL SteamSetCacheDefaultDirectory( const char *szPath, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetAppDir( unsigned int uAppId, char *szPath, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamMoveApp( unsigned int uAppId, const char *szPath, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamGetAppCacheSize( unsigned int uCacheId, unsigned int *pCacheSizeInMb, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamSetAppCacheSize( unsigned int uCacheId, unsigned int nCacheSizeInMb, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamSetAppVersion( unsigned int uAppId, unsigned int uAppVersionId, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamUninstall( TSteamError *pError );
STEAM_API int STEAM_CALL SteamSetNotificationCallback( SteamNotificationCallback_t pCallbackFunction, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamChangeForgottenPassword( const char *cszUser, const char *cszAnswerToQuestion, const char *cszEmailVerificationKey, const char *cszNewPassphrase, int *pbChanged, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRequestForgottenPasswordEmail( const char *cszUser, SteamPersonalQuestion_t ReceivePersonalQuestion, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRequestAccountsByEmailAddressEmail( const char *cszEmailAddress, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRequestAccountsByCdKeyEmail( const char *cszCdKey, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamGetNumAccountsWithEmailAddress( const char *cszEmailAddress, unsigned int *puNumAccounts, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamChangePassword( const char *cszCurrentPassphrase, const char *cszNewPassphrase, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamChangePersonalQA( const char *cszCurrentPassphrase, const char *cszNewPersonalQuestion, const char *cszNewAnswerToQuestion, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetCurrentEmailAddress( char *szEmailAddress, unsigned int uBufSize, unsigned int *puEmailChars, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamChangeEmailAddress( const char *cszNewEmailAddress, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamVerifyEmailAddress( const char *cszEmailVerificationKey, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamRequestEmailAddressVerificationEmail( TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamChangeAccountName( const char *cszCurrentPassphrase, const char *cszNewAccountName, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamUpdateAccountBillingInfo( const TSteamPaymentCardInfo *pPaymentCardInfo, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamUpdateSubscriptionBillingInfo( unsigned int uSubscriptionId, const TSteamSubscriptionBillingInfo *pSubscriptionBillingInfo, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetSponsorUrl( unsigned int uAppId, char *szUrl, unsigned int uBufSize, unsigned int *pUrlChars, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetContentServerInfo( unsigned int uAppId, unsigned int *puServerId, unsigned int *puServerIpAddress, TSteamError *pError );
STEAM_API SteamCallHandle_t STEAM_CALL SteamGetAppUpdateStats( unsigned int uAppOrCacheId, ESteamAppUpdateStatsQueryType eQueryType, TSteamUpdateStats *pUpdateStats, TSteamError *pError );
STEAM_API int STEAM_CALL SteamGetTotalUpdateStats( TSteamUpdateStats *pUpdateStats, TSteamError *pError );
/*
** User ID exported functions are in SteamUserIdValidation.h
*/
#ifdef __cplusplus
}
#endif
#endif /* #ifndef INCLUDED_STEAM_H */

198
common/SteamAppStartup.cpp Normal file
View File

@ -0,0 +1,198 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifdef _WIN32
#include "SteamAppStartup.h"
#define WIN32_LEAN_AND_MEAN
#include <assert.h>
#include <windows.h>
#include <process.h>
#include <direct.h>
#include <stdio.h>
#include <sys/stat.h>
#define STEAM_PARM "-steam"
void LaunchSelfViaSteam(const char *params);
bool FileExists(const char *fileName)
{
struct _stat statbuf;
return (_stat(fileName, &statbuf) == 0);
}
inline bool V_isspace(int c)
{
// The standard white-space characters are the following: space, tab, carriage-return, newline, vertical tab, and form-feed. In the C locale, V_isspace() returns true only for the standard white-space characters.
return c == ' ' || c == 9 /*horizontal tab*/ || c == '\r' || c == '\n' || c == 11 /*vertical tab*/ || c == '\f';
}
//-----------------------------------------------------------------------------
// Purpose: Launches steam if necessary
//-----------------------------------------------------------------------------
bool ShouldLaunchAppViaSteam(const char *lpCmdLine, const char *steamFilesystemDllName, const char *stdioFilesystemDllName)
{
// see if steam is on the command line
const char *steamStr = strstr(lpCmdLine, STEAM_PARM);
// check the character following it is a whitespace or null
if (steamStr)
{
const char *postChar = steamStr + strlen(STEAM_PARM);
if (*postChar == 0 || V_isspace(*postChar))
{
// we're running under steam already, let the app continue
return false;
}
}
// we're not running under steam, see which filesystems are available
if (FileExists(stdioFilesystemDllName))
{
// we're being run with a stdio filesystem, so we can continue without steam
return false;
}
// make sure we have a steam filesystem available
if (!FileExists(steamFilesystemDllName))
{
return false;
}
// we have the steam filesystem, and no stdio filesystem, so we must need to be run under steam
// launch steam
LaunchSelfViaSteam(lpCmdLine);
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Handles launching the game indirectly via steam
//-----------------------------------------------------------------------------
void LaunchSelfViaSteam(const char *params)
{
// calculate the details of our launch
char appPath[MAX_PATH];
::GetModuleFileName((HINSTANCE)GetModuleHandle(NULL), appPath, sizeof(appPath));
// strip out the exe name
char *slash = strrchr(appPath, '\\');
if (slash)
{
*slash = 0;
}
// save out our details to the registry
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey))
{
DWORD dwType = REG_SZ;
DWORD dwSize = static_cast<DWORD>( strlen(appPath) + 1 );
RegSetValueEx(hKey, "TempAppPath", NULL, dwType, (LPBYTE)appPath, dwSize);
dwSize = static_cast<DWORD>( strlen(params) + 1 );
RegSetValueEx(hKey, "TempAppCmdLine", NULL, dwType, (LPBYTE)params, dwSize);
// clear out the appID (since we don't know it yet)
dwType = REG_DWORD;
int appID = -1;
RegSetValueEx(hKey, "TempAppID", NULL, dwType, (LPBYTE)&appID, sizeof(appID));
RegCloseKey(hKey);
}
// search for an active steam instance
HWND hwnd = ::FindWindow("Valve_SteamIPC_Class", "Hidden Window");
if (hwnd)
{
::PostMessage(hwnd, WM_USER + 3, 0, 0);
}
else
{
// couldn't find steam, find and launch it
// first, search backwards through our current set of directories
char steamExe[MAX_PATH];
steamExe[0] = 0;
char dir[MAX_PATH];
if (::GetCurrentDirectoryA(sizeof(dir), dir))
{
char *slash = strrchr(dir, '\\');
while (slash)
{
// see if steam_dev.exe is in the directory first
slash[1] = 0;
strcat(slash, "steam_dev.exe");
FILE *f = fopen(dir, "rb");
if (f)
{
// found it
fclose(f);
strcpy(steamExe, dir);
break;
}
// see if steam.exe is in the directory
slash[1] = 0;
strcat(slash, "steam.exe");
f = fopen(dir, "rb");
if (f)
{
// found it
fclose(f);
strcpy(steamExe, dir);
break;
}
// kill the string at the slash
slash[0] = 0;
// move to the previous slash
slash = strrchr(dir, '\\');
}
}
if (!steamExe[0])
{
// still not found, use the one in the registry
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey))
{
DWORD dwType;
DWORD dwSize = sizeof(steamExe);
RegQueryValueEx( hKey, "SteamExe", NULL, &dwType, (LPBYTE)steamExe, &dwSize);
RegCloseKey( hKey );
}
}
if (!steamExe[0])
{
// still no path, error
::MessageBox(NULL, "Error running game: could not find steam.exe to launch", "Fatal Error", MB_OK | MB_ICONERROR);
return;
}
// fix any slashes
for (char *slash = steamExe; *slash; slash++)
{
if (*slash == '/')
{
*slash = '\\';
}
}
// change to the steam directory
strcpy(dir, steamExe);
char *delimiter = strrchr(dir, '\\');
if (delimiter)
{
*delimiter = 0;
_chdir(dir);
}
// exec steam.exe, in silent mode, with the launch app param
char *args[4] = { steamExe, "-silent", "-applaunch", NULL };
_spawnv(_P_NOWAIT, steamExe, args);
}
}
#endif // _WIN32

25
common/SteamAppStartup.h Normal file
View File

@ -0,0 +1,25 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: used by all .exe's that run under steam and out,
// so they can be launched indirectly by steam and launch steam themselves
//
//=============================================================================//
#ifndef STEAMAPPSTARTUP_H
#define STEAMAPPSTARTUP_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Call this first thing at startup
// Works out if the app is a steam app that is being ran outside of steam,
// and if so, launches steam and tells it to run us as a steam app
//
// if it returns true, then exit
// if it ruturns false, then continue with normal startup
//-----------------------------------------------------------------------------
bool ShouldLaunchAppViaSteam(const char *cmdLine, const char *steamFilesystemDllName, const char *stdioFilesystemDllName);
#endif // STEAMAPPSTARTUP_H

162
common/SteamBootStrapper.h Normal file
View File

@ -0,0 +1,162 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
//*********** (C) Copyright 2000 Valve, L.L.C. All rights reserved. ***********
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//*****************************************************************************
//
// Contents:
//
//
//
// Authors:
//
// Target restrictions:
//
// Tool restrictions:
//
// Things to do:
//
//
//
//*****************************************************************************
#ifndef INCLUDED_STEAM_BOOTSTRAPPER_H
#define INCLUDED_STEAM_BOOTSTRAPPER_H
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
//*****************************************************************************
//
// 'Local' build control section.
//
//*****************************************************************************
#if (BUILD_MODE == BUILD_MODE_RELEASE_NORMAL) || (BUILD_MODE == BUILD_MODE_RELEASE_TEST)
#elif BUILD_MODE == BUILD_MODE_DEBUG_NORMAL
#else
// 'Safe' default settings. This allows new build modes to be added to the
// project without requiring the manual updating of all 'local build control'
// sections in every module and header file.
#endif
//*****************************************************************************
//
// Include files required by this header.
//
// Note: Do NOT place any 'using' directives or declarations in header files -
// put them at the top of the source files that require them.
// Use fully-qualified names in header files.
//
//*****************************************************************************
//*****************************************************************************
//
// Exported constants and macros.
// - Wrap these definitions in a namespace whenever possible
//
//*****************************************************************************
namespace
{
// constant definitions here
}
#define szSteamBootStrapperIconIdEnvVar "__STEAM_BOOTSTRAPPER_ICON_ID__"
//*****************************************************************************
//
// Exported scalar type and enumerated type definitions.
// - Wrap these definitions in a namespace whenever possible
//
//*****************************************************************************
namespace
{
// scalar and enumerated type definitions here
}
//*****************************************************************************
//
// Exported class, structure, and complex type definitions.
// - Wrap these definitions in a namespace whenever possible
//
//*****************************************************************************
namespace
{
// class, structure, and complex type definitions here
}
//*****************************************************************************
//
// Exported function prototypes
// - Wrap these definitions in a namespace whenever possible
// - declared extern here, and defined without storage class in the source file.
//
//*****************************************************************************
namespace
{
// function prototypes here
}
//*****************************************************************************
//
// Exported variable and data declarations
// - Wrap these definitions in a namespace whenever possible
// - declared extern here, and defined without storage class in the source file.
//
//*****************************************************************************
namespace
{
// variable and data declarations here
}
//*****************************************************************************
//
// Inline function definitions.
//
//*****************************************************************************
#endif

703
common/SteamCommon.h Normal file
View File

@ -0,0 +1,703 @@
/************ (C) Copyright 2004 Valve Corporation, All rights reserved. ***********
**
** The copyright to the contents herein is the property of Valve Corporation.
** The contents may be used and/or copied only with the written permission of
** Valve, or in accordance with the terms and conditions stipulated in
** the agreement/contract under which the contents have been supplied.
**
*******************************************************************************
**
** Contents:
**
** Common types used in the Steam DLL interface.
**
** This file is distributed to Steam application developers.
**
**
**
*******************************************************************************/
#ifndef INCLUDED_STEAM2_USERID_STRUCTS
#define INCLUDED_STEAM2_USERID_STRUCTS
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/* Applications should not define STEAM_EXPORTS. */
#if defined ( _WIN32 )
#ifdef STEAM_EXPORTS
#define STEAM_API __declspec(dllexport)
#else
#define STEAM_API __declspec(dllimport)
#endif
#define STEAM_CALL __cdecl
#else
#define STEAM_API /* */
#define STEAM_CALL /* */
#endif
typedef void (STEAM_CALL *KeyValueIteratorCallback_t )(const char *Key, const char *Val, void *pvParam);
/******************************************************************************
**
** Exported macros and constants
**
******************************************************************************/
/* DEPRECATED -- these are ignored now, all API access is granted on SteamStartup */
#define STEAM_USING_FILESYSTEM (0x00000001)
#define STEAM_USING_LOGGING (0x00000002)
#define STEAM_USING_USERID (0x00000004)
#define STEAM_USING_ACCOUNT (0x00000008)
#define STEAM_USING_ALL (0x0000000f)
/* END DEPRECATED */
#define STEAM_MAX_PATH (255)
#define STEAM_QUESTION_MAXLEN (255)
#define STEAM_SALT_SIZE (8)
#define STEAM_PROGRESS_PERCENT_SCALE (0x00001000)
/* These are maximum significant string lengths, excluding nul-terminator. */
#define STEAM_CARD_NUMBER_SIZE (17)
#define STEAM_CARD_HOLDERNAME_SIZE (100)
#define STEAM_CARD_EXPYEAR_SIZE (4)
#define STEAM_CARD_EXPMONTH_SIZE (2)
#define STEAM_CARD_CVV2_SIZE (5)
#define STEAM_BILLING_ADDRESS1_SIZE (128)
#define STEAM_BILLING_ADDRESS2_SIZE (128)
#define STEAM_BILLING_CITY_SIZE (50)
#define STEAM_BILLING_ZIP_SIZE (16)
#define STEAM_BILLING_STATE_SIZE (32)
#define STEAM_BILLING_COUNTRY_SIZE (32)
#define STEAM_BILLING_PHONE_SIZE (20)
#define STEAM_BILLING_EMAIL_ADDRESS_SIZE (100)
#define STEAM_TYPE_OF_PROOF_OF_PURCHASE_SIZE (20)
#define STEAM_PROOF_OF_PURCHASE_TOKEN_SIZE (200)
#define STEAM_EXTERNAL_ACCOUNTNAME_SIZE (100)
#define STEAM_EXTERNAL_ACCOUNTPASSWORD_SIZE (80)
#define STEAM_BILLING_CONFIRMATION_CODE_SIZE (22)
#define STEAM_BILLING_CARD_APPROVAL_CODE_SIZE (100)
#define STEAM_BILLING_TRANS_DATE_SIZE (9) // mm/dd/yy
#define STEAM_BILLING_TRANS_TIME_SIZE (9) // hh:mm:ss
/******************************************************************************
**
** Scalar type and enumerated type definitions.
**
******************************************************************************/
typedef unsigned int SteamHandle_t;
typedef void * SteamUserIDTicketValidationHandle_t;
typedef unsigned int SteamCallHandle_t;
#if defined(_MSC_VER)
typedef unsigned __int64 SteamUnsigned64_t;
#else
typedef unsigned long long SteamUnsigned64_t;
#endif
typedef enum
{
eSteamSeekMethodSet = 0,
eSteamSeekMethodCur = 1,
eSteamSeekMethodEnd = 2
} ESteamSeekMethod;
typedef enum
{
eSteamBufferMethodFBF = 0,
eSteamBufferMethodNBF = 1
} ESteamBufferMethod;
typedef enum
{
eSteamErrorNone = 0,
eSteamErrorUnknown = 1,
eSteamErrorLibraryNotInitialized = 2,
eSteamErrorLibraryAlreadyInitialized = 3,
eSteamErrorConfig = 4,
eSteamErrorContentServerConnect = 5,
eSteamErrorBadHandle = 6,
eSteamErrorHandlesExhausted = 7,
eSteamErrorBadArg = 8,
eSteamErrorNotFound = 9,
eSteamErrorRead = 10,
eSteamErrorEOF = 11,
eSteamErrorSeek = 12,
eSteamErrorCannotWriteNonUserConfigFile = 13,
eSteamErrorCacheOpen = 14,
eSteamErrorCacheRead = 15,
eSteamErrorCacheCorrupted = 16,
eSteamErrorCacheWrite = 17,
eSteamErrorCacheSession = 18,
eSteamErrorCacheInternal = 19,
eSteamErrorCacheBadApp = 20,
eSteamErrorCacheVersion = 21,
eSteamErrorCacheBadFingerPrint = 22,
eSteamErrorNotFinishedProcessing = 23,
eSteamErrorNothingToDo = 24,
eSteamErrorCorruptEncryptedUserIDTicket = 25,
eSteamErrorSocketLibraryNotInitialized = 26,
eSteamErrorFailedToConnectToUserIDTicketValidationServer = 27,
eSteamErrorBadProtocolVersion = 28,
eSteamErrorReplayedUserIDTicketFromClient = 29,
eSteamErrorReceiveResultBufferTooSmall = 30,
eSteamErrorSendFailed = 31,
eSteamErrorReceiveFailed = 32,
eSteamErrorReplayedReplyFromUserIDTicketValidationServer = 33,
eSteamErrorBadSignatureFromUserIDTicketValidationServer = 34,
eSteamErrorValidationStalledSoAborted = 35,
eSteamErrorInvalidUserIDTicket = 36,
eSteamErrorClientLoginRateTooHigh = 37,
eSteamErrorClientWasNeverValidated = 38,
eSteamErrorInternalSendBufferTooSmall = 39,
eSteamErrorInternalReceiveBufferTooSmall = 40,
eSteamErrorUserTicketExpired = 41,
eSteamErrorCDKeyAlreadyInUseOnAnotherClient = 42,
eSteamErrorNotLoggedIn = 101,
eSteamErrorAlreadyExists = 102,
eSteamErrorAlreadySubscribed = 103,
eSteamErrorNotSubscribed = 104,
eSteamErrorAccessDenied = 105,
eSteamErrorFailedToCreateCacheFile = 106,
eSteamErrorCallStalledSoAborted = 107,
eSteamErrorEngineNotRunning = 108,
eSteamErrorEngineConnectionLost = 109,
eSteamErrorLoginFailed = 110,
eSteamErrorAccountPending = 111,
eSteamErrorCacheWasMissingRetry = 112,
eSteamErrorLocalTimeIncorrect = 113,
eSteamErrorCacheNeedsDecryption = 114,
eSteamErrorAccountDisabled = 115,
eSteamErrorCacheNeedsRepair = 116,
eSteamErrorRebootRequired = 117,
eSteamErrorNetwork = 200,
eSteamErrorOffline = 201
} ESteamError;
typedef enum
{
eNoDetailedErrorAvailable,
eStandardCerrno,
eWin32LastError,
eWinSockLastError,
eDetailedPlatformErrorCount
} EDetailedPlatformErrorType;
typedef enum /* Filter elements returned by SteamFind{First,Next} */
{
eSteamFindLocalOnly, /* limit search to local filesystem */
eSteamFindRemoteOnly, /* limit search to remote repository */
eSteamFindAll /* do not limit search (duplicates allowed) */
} ESteamFindFilter;
/******************************************************************************
**
** Exported structure and complex type definitions.
**
******************************************************************************/
typedef struct
{
ESteamError eSteamError;
EDetailedPlatformErrorType eDetailedErrorType;
int nDetailedErrorCode;
char szDesc[STEAM_MAX_PATH];
} TSteamError;
typedef struct
{
int bIsDir; /* If non-zero, element is a directory; if zero, element is a file */
unsigned int uSizeOrCount; /* If element is a file, this contains size of file in bytes */
int bIsLocal; /* If non-zero, reported item is a standalone element on local filesystem */
char cszName[STEAM_MAX_PATH]; /* Base element name (no path) */
long lLastAccessTime; /* Seconds since 1/1/1970 (like time_t) when element was last accessed */
long lLastModificationTime; /* Seconds since 1/1/1970 (like time_t) when element was last modified */
long lCreationTime; /* Seconds since 1/1/1970 (like time_t) when element was created */
} TSteamElemInfo;
typedef struct
{
unsigned int uNumSubscriptions;
unsigned int uMaxNameChars;
unsigned int uMaxApps;
} TSteamSubscriptionStats;
typedef struct
{
unsigned int uNumApps;
unsigned int uMaxNameChars;
unsigned int uMaxInstallDirNameChars;
unsigned int uMaxVersionLabelChars;
unsigned int uMaxLaunchOptions;
unsigned int uMaxLaunchOptionDescChars;
unsigned int uMaxLaunchOptionCmdLineChars;
unsigned int uMaxNumIcons;
unsigned int uMaxIconSize;
unsigned int uMaxDependencies;
} TSteamAppStats;
typedef struct
{
char *szLabel;
unsigned int uMaxLabelChars;
unsigned int uVersionId;
int bIsNotAvailable;
} TSteamAppVersion;
typedef struct
{
char *szDesc;
unsigned int uMaxDescChars;
char *szCmdLine;
unsigned int uMaxCmdLineChars;
unsigned int uIndex;
unsigned int uIconIndex;
int bNoDesktopShortcut;
int bNoStartMenuShortcut;
int bIsLongRunningUnattended;
} TSteamAppLaunchOption;
typedef struct
{
char *szName;
unsigned int uMaxNameChars;
char *szLatestVersionLabel;
unsigned int uMaxLatestVersionLabelChars;
char *szCurrentVersionLabel;
unsigned int uMaxCurrentVersionLabelChars;
char *szInstallDirName;
unsigned int uMaxInstallDirNameChars;
unsigned int uId;
unsigned int uLatestVersionId;
unsigned int uCurrentVersionId;
unsigned int uMinCacheFileSizeMB;
unsigned int uMaxCacheFileSizeMB;
unsigned int uNumLaunchOptions;
unsigned int uNumIcons;
unsigned int uNumVersions;
unsigned int uNumDependencies;
} TSteamApp;
typedef enum
{
eNoCost = 0,
eBillOnceOnly = 1,
eBillMonthly = 2,
eProofOfPrepurchaseOnly = 3,
eGuestPass = 4,
eHardwarePromo = 5,
eNumBillingTypes,
} EBillingType;
typedef struct
{
char *szName;
unsigned int uMaxNameChars;
unsigned int *puAppIds;
unsigned int uMaxAppIds;
unsigned int uId;
unsigned int uNumApps;
EBillingType eBillingType;
unsigned int uCostInCents;
unsigned int uNumDiscounts;
int bIsPreorder;
int bRequiresShippingAddress;
unsigned int uDomesticShippingCostInCents;
unsigned int uInternationalShippingCostInCents;
bool bIsCyberCafeSubscription;
unsigned int uGameCode;
char szGameCodeDesc[STEAM_MAX_PATH];
bool bIsDisabled;
bool bRequiresCD;
unsigned int uTerritoryCode;
bool bIsSteam3Subscription;
} TSteamSubscription;
typedef struct
{
char szName[STEAM_MAX_PATH];
unsigned int uDiscountInCents;
unsigned int uNumQualifiers;
} TSteamSubscriptionDiscount;
typedef struct
{
char szName[STEAM_MAX_PATH];
unsigned int uRequiredSubscription;
int bIsDisqualifier;
} TSteamDiscountQualifier;
typedef struct TSteamProgress
{
int bValid; /* non-zero if call provides progress info */
unsigned int uPercentDone; /* 0 to 100 * STEAM_PROGRESS_PERCENT_SCALE if bValid */
char szProgress[STEAM_MAX_PATH]; /* additional progress info */
} TSteamProgress;
typedef enum
{
eSteamNotifyTicketsWillExpire,
eSteamNotifyAccountInfoChanged,
eSteamNotifyContentDescriptionChanged,
eSteamNotifyPleaseShutdown,
eSteamNotifyNewContentServer,
eSteamNotifySubscriptionStatusChanged,
eSteamNotifyContentServerConnectionLost,
eSteamNotifyCacheLoadingCompleted,
eSteamNotifyCacheNeedsDecryption,
eSteamNotifyCacheNeedsRepair
} ESteamNotificationCallbackEvent;
typedef void(*SteamNotificationCallback_t)(ESteamNotificationCallbackEvent eEvent, unsigned int nData);
typedef char SteamPersonalQuestion_t[ STEAM_QUESTION_MAXLEN + 1 ];
typedef struct
{
unsigned char uchSalt[STEAM_SALT_SIZE];
} SteamSalt_t;
typedef enum
{
eVisa = 1,
eMaster = 2,
eAmericanExpress = 3,
eDiscover = 4,
eDinnersClub = 5,
eJCB = 6
} ESteamPaymentCardType;
typedef struct
{
ESteamPaymentCardType eCardType;
char szCardNumber[ STEAM_CARD_NUMBER_SIZE +1 ];
char szCardHolderName[ STEAM_CARD_HOLDERNAME_SIZE + 1];
char szCardExpYear[ STEAM_CARD_EXPYEAR_SIZE + 1 ];
char szCardExpMonth[ STEAM_CARD_EXPMONTH_SIZE+ 1 ];
char szCardCVV2[ STEAM_CARD_CVV2_SIZE + 1 ];
char szBillingAddress1[ STEAM_BILLING_ADDRESS1_SIZE + 1 ];
char szBillingAddress2[ STEAM_BILLING_ADDRESS2_SIZE + 1 ];
char szBillingCity[ STEAM_BILLING_CITY_SIZE + 1 ];
char szBillingZip[ STEAM_BILLING_ZIP_SIZE + 1 ];
char szBillingState[ STEAM_BILLING_STATE_SIZE + 1 ];
char szBillingCountry[ STEAM_BILLING_COUNTRY_SIZE + 1 ];
char szBillingPhone[ STEAM_BILLING_PHONE_SIZE + 1 ];
char szBillingEmailAddress[ STEAM_BILLING_EMAIL_ADDRESS_SIZE + 1 ];
unsigned int uExpectedCostInCents;
unsigned int uExpectedTaxInCents;
/* If the TSteamSubscription says that shipping info is required, */
/* then the following fields must be filled out. */
/* If szShippingName is empty, then assumes so are the rest. */
char szShippingName[ STEAM_CARD_HOLDERNAME_SIZE + 1];
char szShippingAddress1[ STEAM_BILLING_ADDRESS1_SIZE + 1 ];
char szShippingAddress2[ STEAM_BILLING_ADDRESS2_SIZE + 1 ];
char szShippingCity[ STEAM_BILLING_CITY_SIZE + 1 ];
char szShippingZip[ STEAM_BILLING_ZIP_SIZE + 1 ];
char szShippingState[ STEAM_BILLING_STATE_SIZE + 1 ];
char szShippingCountry[ STEAM_BILLING_COUNTRY_SIZE + 1 ];
char szShippingPhone[ STEAM_BILLING_PHONE_SIZE + 1 ];
unsigned int uExpectedShippingCostInCents;
} TSteamPaymentCardInfo;
typedef struct
{
char szTypeOfProofOfPurchase[ STEAM_TYPE_OF_PROOF_OF_PURCHASE_SIZE + 1 ];
/* A ProofOfPurchase token is not necessarily a nul-terminated string; it may be binary data
(perhaps encrypted). Hence we need a length and an array of bytes. */
unsigned int uLengthOfBinaryProofOfPurchaseToken;
char cBinaryProofOfPurchaseToken[ STEAM_PROOF_OF_PURCHASE_TOKEN_SIZE + 1 ];
} TSteamPrepurchaseInfo;
typedef struct
{
char szAccountName[ STEAM_EXTERNAL_ACCOUNTNAME_SIZE + 1 ];
char szPassword[ STEAM_EXTERNAL_ACCOUNTPASSWORD_SIZE + 1 ];
} TSteamExternalBillingInfo;
typedef enum
{
ePaymentCardInfo = 1,
ePrepurchasedInfo = 2,
eAccountBillingInfo = 3,
eExternalBillingInfo = 4, /* indirect billing via ISP etc (not supported yet) */
ePaymentCardReceipt = 5,
ePrepurchaseReceipt = 6,
eEmptyReceipt = 7
} ESteamSubscriptionBillingInfoType;
typedef struct
{
ESteamSubscriptionBillingInfoType eBillingInfoType;
union {
TSteamPaymentCardInfo PaymentCardInfo;
TSteamPrepurchaseInfo PrepurchaseInfo;
TSteamExternalBillingInfo ExternalBillingInfo;
char bUseAccountBillingInfo;
};
} TSteamSubscriptionBillingInfo;
typedef enum
{
/* Subscribed */
eSteamSubscriptionOK = 0, /* Subscribed */
eSteamSubscriptionPending = 1, /* Awaiting transaction completion */
eSteamSubscriptionPreorder = 2, /* Is currently a pre-order */
eSteamSubscriptionPrepurchaseTransferred = 3, /* hop to this account */
/* Unusbscribed */
eSteamSubscriptionPrepurchaseInvalid = 4, /* Invalid cd-key */
eSteamSubscriptionPrepurchaseRejected = 5, /* hopped out / banned / etc */
eSteamSubscriptionPrepurchaseRevoked = 6, /* hop away from this account */
eSteamSubscriptionPaymentCardDeclined = 7, /* CC txn declined */
eSteamSubscriptionCancelledByUser = 8, /* Cancelled by client */
eSteamSubscriptionCancelledByVendor = 9, /* Cancelled by us */
eSteamSubscriptionPaymentCardUseLimit = 10, /* Card used too many times, potential fraud */
eSteamSubscriptionPaymentCardAlert = 11, /* Got a "pick up card" or the like from bank */
eSteamSubscriptionFailed = 12, /* Other Error in subscription data or transaction failed/lost */
eSteamSubscriptionPaymentCardAVSFailure = 13, /* Card failed Address Verification check */
eSteamSubscriptionPaymentCardInsufficientFunds = 14, /* Card failed due to insufficient funds */
eSteamSubscriptionRestrictedCountry = 15 /* The subscription is not available in the user's country */
} ESteamSubscriptionStatus;
typedef struct
{
ESteamPaymentCardType eCardType;
char szCardLastFourDigits[ 4 + 1 ];
char szCardHolderName[ STEAM_CARD_HOLDERNAME_SIZE + 1];
char szBillingAddress1[ STEAM_BILLING_ADDRESS1_SIZE + 1 ];
char szBillingAddress2[ STEAM_BILLING_ADDRESS2_SIZE + 1 ];
char szBillingCity[ STEAM_BILLING_CITY_SIZE + 1 ];
char szBillingZip[ STEAM_BILLING_ZIP_SIZE + 1 ];
char szBillingState[ STEAM_BILLING_STATE_SIZE + 1 ];
char szBillingCountry[ STEAM_BILLING_COUNTRY_SIZE + 1 ];
// The following are only available after the subscription leaves "pending" status
char szCardApprovalCode[ STEAM_BILLING_CARD_APPROVAL_CODE_SIZE + 1];
char szTransDate[ STEAM_BILLING_TRANS_DATE_SIZE + 1]; /* mm/dd/yy */
char szTransTime[ STEAM_BILLING_TRANS_TIME_SIZE + 1]; /* hh:mm:ss */
unsigned int uPriceWithoutTax;
unsigned int uTaxAmount;
unsigned int uShippingCost;
} TSteamPaymentCardReceiptInfo;
typedef struct
{
char szTypeOfProofOfPurchase[ STEAM_TYPE_OF_PROOF_OF_PURCHASE_SIZE + 1 ];
} TSteamPrepurchaseReceiptInfo;
typedef struct
{
ESteamSubscriptionStatus eStatus;
ESteamSubscriptionStatus ePreviousStatus;
ESteamSubscriptionBillingInfoType eReceiptInfoType;
char szConfirmationCode[ STEAM_BILLING_CONFIRMATION_CODE_SIZE + 1];
union {
TSteamPaymentCardReceiptInfo PaymentCardReceiptInfo;
TSteamPrepurchaseReceiptInfo PrepurchaseReceiptInfo;
};
} TSteamSubscriptionReceipt;
typedef enum
{
ePhysicalBytesReceivedThisSession = 1,
eAppReadyToLaunchStatus = 2,
eAppPreloadStatus = 3,
eAppEntireDepot = 4,
eCacheBytesPresent = 5
} ESteamAppUpdateStatsQueryType;
typedef struct
{
SteamUnsigned64_t uBytesTotal;
SteamUnsigned64_t uBytesPresent;
} TSteamUpdateStats;
typedef enum
{
eSteamUserAdministrator = 0x00000001, /* May subscribe, unsubscribe, etc */
eSteamUserDeveloper = 0x00000002, /* Steam or App developer */
eSteamUserCyberCafe = 0x00000004 /* CyberCafe, school, etc -- UI should ask for password */
/* before allowing logout, unsubscribe, etc */
} ESteamUserTypeFlags;
typedef enum
{
eSteamAccountStatusDefault = 0x00000000,
eSteamAccountStatusEmailVerified = 0x00000001,
/* Note: Mask value 0x2 is reserved for future use. (Some, but not all, public accounts already have this set.) */
eSteamAccountDisabled = 0x00000004
} ESteamAccountStatusBitFields ;
typedef enum
{
eSteamBootstrapperError = -1,
eSteamBootstrapperDontCheckForUpdate = 0,
eSteamBootstrapperCheckForUpdateAndRerun = 7
} ESteamBootStrapperClientAppResult;
typedef enum
{
eSteamOnline = 0,
eSteamOffline = 1,
eSteamNoAuthMode = 2,
eSteamBillingOffline = 3
} eSteamOfflineStatus;
typedef struct
{
int eOfflineNow;
int eOfflineNextSession;
} TSteamOfflineStatus;
typedef struct
{
unsigned int uAppId;
int bIsSystemDefined;
char szMountPath[STEAM_MAX_PATH];
} TSteamAppDependencyInfo;
typedef enum
{
eSteamOpenFileRegular = 0x0,
eSteamOpenFileIgnoreLocal = 0x1,
eSteamOpenFileChecksumReads = 0x2
} ESteamOpenFileFlags;
typedef enum
{
eSteamValveCDKeyValidationServer = 0,
eSteamHalfLifeMasterServer = 1,
eSteamFriendsServer = 2,
eSteamCSERServer = 3,
eSteamHalfLife2MasterServer = 4,
eSteamRDKFMasterServer = 5,
eMaxServerTypes = 6
} ESteamServerType;
/******************************************************************************
**
** More exported constants
**
******************************************************************************/
#ifdef __cplusplus
const SteamHandle_t STEAM_INVALID_HANDLE = 0;
const SteamCallHandle_t STEAM_INVALID_CALL_HANDLE = 0;
const SteamUserIDTicketValidationHandle_t STEAM_INACTIVE_USERIDTICKET_VALIDATION_HANDLE = 0;
const unsigned int STEAM_USE_LATEST_VERSION = 0xFFFFFFFF;
#else
#define STEAM_INVALID_HANDLE ((SteamHandle_t)(0))
#define STEAM_INVALID_CALL_HANDLE ((SteamCallHandle_t)(0))
#define STEAM_INACTIVE_USERIDTICKET_VALIDATION_HANDLE ((SteamUserIDTicketValidationHandle_t)(0))
#define STEAM_USE_LATEST_VERSION (0xFFFFFFFFu);
#endif
/******************************************************************************
** Each Steam instance (licensed Steam Service Provider) has a unique SteamInstanceID_t.
**
** Each Steam instance as its own DB of users.
** Each user in the DB has a unique SteamLocalUserID_t (a serial number, with possible
** rare gaps in the sequence).
**
******************************************************************************/
typedef unsigned short SteamInstanceID_t; // MUST be 16 bits
#if defined ( _WIN32 )
typedef unsigned __int64 SteamLocalUserID_t; // MUST be 64 bits
#else
typedef unsigned long long SteamLocalUserID_t; // MUST be 64 bits
#endif
/******************************************************************************
**
** Applications need to be able to authenticate Steam users from ANY instance.
** So a SteamIDTicket contains SteamGlobalUserID, which is a unique combination of
** instance and user id.
**
** SteamLocalUserID is an unsigned 64-bit integer.
** For platforms without 64-bit int support, we provide access via a union that splits it into
** high and low unsigned 32-bit ints. Such platforms will only need to compare LocalUserIDs
** for equivalence anyway - not perform arithmetic with them.
**
********************************************************************************/
typedef struct
{
unsigned int Low32bits;
unsigned int High32bits;
} TSteamSplitLocalUserID;
typedef struct
{
SteamInstanceID_t m_SteamInstanceID;
union
{
SteamLocalUserID_t As64bits;
TSteamSplitLocalUserID Split;
} m_SteamLocalUserID;
} TSteamGlobalUserID;
#ifdef __cplusplus
}
#endif
#endif

226
common/SteamInterface.h Normal file
View File

@ -0,0 +1,226 @@
/************ (C) Copyright 2004 Valve Corporation, All rights reserved. ***********
**
** The copyright to the contents herein is the property of Valve Corporation.
** The contents may be used and/or copied only with the written permission of
** Valve, or in accordance with the terms and conditions stipulated in
** the agreement/contract under which the contents have been supplied.
**
*******************************************************************************
**
** Contents:
**
** This file provides an obfuscated interface to the Steam service. This
** interface is described in the SDK documentation.
**
******************************************************************************/
#ifndef INCLUDED_STEAM_INTERFACE_H
#define INCLUDED_STEAM_INTERFACE_H
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
#ifndef INCLUDED_STEAM2_USERID_STRUCTS
#include "SteamCommon.h"
#endif
// IAppSystem interface. Returns an IAppSystem implementation; use QueryInterface on
// that to get the ISteamInterface (same as the older _f function).
#define STEAMDLL_APPSYSTEM_VERSION "SteamDLLAppsystem001"
// extern "C" STEAM_API void * STEAM_CALL CreateInterface( const char *pName, int *pReturncode );
// create interface
#define STEAM_INTERFACE_VERSION "Steam006"
extern "C" STEAM_API void * STEAM_CALL _f(const char *szInterfaceVersionRequested);
// current abstract interface
class ISteamInterface
{
public:
virtual ~ISteamInterface() {};
virtual SteamCallHandle_t ChangePassword( const char *cszCurrentPassphrase, const char *cszNewPassphrase, TSteamError *pError ) = 0;
virtual int GetCurrentEmailAddress( char *szEmailAddress, unsigned int uBufSize, unsigned int *puEmailChars, TSteamError *pError ) = 0;
virtual SteamCallHandle_t ChangePersonalQA( const char *cszCurrentPassphrase, const char *cszNewPersonalQuestion, const char *cszNewAnswerToQuestion, TSteamError *pError ) = 0;
virtual SteamCallHandle_t ChangeEmailAddress( const char *cszNewEmailAddress, TSteamError *pError ) = 0;
virtual SteamCallHandle_t VerifyEmailAddress( const char *cszEmailVerificationKey, TSteamError *pError ) = 0;
virtual SteamCallHandle_t RequestEmailAddressVerificationEmail( TSteamError *pError ) = 0;
virtual SteamCallHandle_t ChangeAccountName( const char *cszCurrentPassphrase, const char *cszNewAccountName, TSteamError *pError ) = 0;
virtual int MountAppFilesystem( TSteamError *pError ) = 0;
virtual int UnmountAppFilesystem( TSteamError *pError ) = 0;
virtual SteamHandle_t MountFilesystem( unsigned int uAppId, const char *szMountPath, TSteamError *pError ) = 0;
virtual int UnmountFilesystem( SteamHandle_t hFs, TSteamError *pError ) = 0;
virtual int Stat( const char *cszName, TSteamElemInfo *pInfo, TSteamError *pError ) = 0;
virtual int SetvBuf( SteamHandle_t hFile, void* pBuf, ESteamBufferMethod eMethod, unsigned int uBytes, TSteamError *pError ) = 0;
virtual int FlushFile( SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual SteamHandle_t OpenFile( const char *cszName, const char *cszMode, TSteamError *pError ) = 0;
virtual SteamHandle_t OpenFileEx( const char *cszName, const char *cszMode, int nFlags, unsigned int *puFileSize, int *pbLocal, TSteamError *pError ) = 0;
virtual SteamHandle_t OpenTmpFile( TSteamError *pError ) = 0;
virtual void ClearError( TSteamError *pError ) = 0;
virtual int GetVersion( char *szVersion, unsigned int uVersionBufSize ) = 0;
virtual int GetOfflineStatus( TSteamOfflineStatus *pStatus, TSteamError *pError ) = 0;
virtual int ChangeOfflineStatus( TSteamOfflineStatus *pStatus, TSteamError *pError ) = 0;
virtual int ProcessCall( SteamCallHandle_t handle, TSteamProgress *pProgress, TSteamError *pError ) = 0;
virtual int AbortCall( SteamCallHandle_t handle, TSteamError *pError ) = 0;
virtual int BlockingCall( SteamCallHandle_t handle, unsigned int uiProcessTickMS, TSteamError *pError ) = 0;
virtual int SetMaxStallCount( unsigned int uNumStalls, TSteamError *pError ) = 0;
virtual int CloseFile( SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual unsigned int ReadFile( void *pBuf, unsigned int uSize, unsigned int uCount, SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual unsigned int WriteFile( const void *pBuf, unsigned int uSize, unsigned int uCount, SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual int Getc( SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual int Putc( int cChar, SteamHandle_t hFile, TSteamError *pError ) = 0;
//virtual int PrintFile( SteamHandle_t hFile, TSteamError *pError, const char *cszFormat, ... ) = 0;
virtual int SeekFile( SteamHandle_t hFile, long lOffset, ESteamSeekMethod, TSteamError *pError ) = 0;
virtual long TellFile( SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual long SizeFile( SteamHandle_t hFile, TSteamError *pError ) = 0;
virtual SteamHandle_t FindFirst( const char *cszPattern, ESteamFindFilter eFilter, TSteamElemInfo *pFindInfo, TSteamError *pError ) = 0;
virtual int FindNext( SteamHandle_t hDirectory, TSteamElemInfo *pFindInfo, TSteamError *pError ) = 0;
#if !defined( _X360 ) // X360TBD: Macro defined in winbase.h
virtual int FindClose( SteamHandle_t hDirectory, TSteamError *pError ) = 0;
#endif
virtual int GetLocalFileCopy( const char *cszName, TSteamError *pError ) = 0;
virtual int IsFileImmediatelyAvailable( const char *cszName, TSteamError *pError ) = 0;
virtual int HintResourceNeed( const char *cszMasterList, int bForgetEverything, TSteamError *pError ) = 0;
virtual int ForgetAllHints( TSteamError *pError ) = 0;
virtual int PauseCachePreloading( TSteamError *pError ) = 0;
virtual int ResumeCachePreloading( TSteamError *pError ) = 0;
virtual SteamCallHandle_t WaitForResources( const char *cszMasterList, TSteamError *pError ) = 0;
virtual int StartEngine(TSteamError *pError) = 0;
virtual int ShutdownEngine(TSteamError *pError) = 0;
virtual int Startup( unsigned int uUsingMask, TSteamError *pError ) = 0;
virtual int Cleanup( TSteamError *pError ) = 0;
virtual unsigned int NumAppsRunning( TSteamError *pError ) = 0;
virtual SteamCallHandle_t CreateAccount( const char *cszUser, const char *cszEmailAddress, const char *cszPassphrase, const char *cszCreationKey, const char *cszPersonalQuestion, const char *cszAnswerToQuestion, int *pbCreated, TSteamError *pError ) = 0;
virtual SteamCallHandle_t GenerateSuggestedAccountNames( const char *cszAccountNameToSelectMasterAS, const char *cszGenerateNamesLikeAccountName, char *pSuggestedNamesBuf, unsigned int uBufSize, unsigned int *puNumSuggestedChars, TSteamError *pError) = 0;
virtual int IsLoggedIn( int *pbIsLoggedIn, TSteamError *pError ) = 0;
virtual SteamCallHandle_t Logout( TSteamError *pError ) = 0;
virtual int IsSecureComputer( int *pbIsSecure, TSteamError *pError ) = 0;
virtual SteamHandle_t CreateLogContext( const char *cszName ) = 0;
virtual int Log( SteamHandle_t hContext, const char *cszMsg ) = 0;
virtual void LogResourceLoadStarted( const char *cszMsg ) = 0;
virtual void LogResourceLoadFinished( const char *cszMsg ) = 0;
virtual SteamCallHandle_t RefreshLogin( const char *cszPassphrase, int bIsSecureComputer, TSteamError * pError ) = 0;
virtual int VerifyPassword( const char *cszPassphrase, int *pbCorrect, TSteamError *pError ) = 0;
virtual int GetUserType( unsigned int *puUserTypeFlags, TSteamError *pError ) = 0;
virtual int GetAppStats( TSteamAppStats *pAppStats, TSteamError *pError ) = 0;
virtual SteamCallHandle_t IsAccountNameInUse( const char *cszAccountName, int *pbIsUsed, TSteamError *pError) = 0;
virtual int GetAppIds( unsigned int *puIds, unsigned int uMaxIds, TSteamError *pError ) = 0;
virtual int GetSubscriptionStats( TSteamSubscriptionStats *pSubscriptionStats, TSteamError *pError ) = 0;
virtual SteamCallHandle_t RefreshAccountInfo( int bContentDescriptionOnly, TSteamError *pError ) = 0;
virtual SteamCallHandle_t Subscribe( unsigned int uSubscriptionId, const TSteamSubscriptionBillingInfo *pSubscriptionBillingInfo, TSteamError *pError ) = 0;
virtual SteamCallHandle_t Unsubscribe( unsigned int uSubscriptionId, TSteamError *pError ) = 0;
virtual int GetSubscriptionReceipt( unsigned int uSubscriptionId, TSteamSubscriptionReceipt *pSubscriptionReceipt, TSteamError *pError ) = 0;
virtual int GetAccountStatus( unsigned int *puAccountStatusFlags, TSteamError *pError ) = 0;
virtual SteamCallHandle_t SetUser( const char *cszUser, int *pbUserSet, TSteamError *pError ) = 0;
virtual int GetUser( char *szUser, unsigned int uBufSize, unsigned int *puUserChars, TSteamGlobalUserID *pOptionalReceiveUserID, TSteamError *pError ) = 0;
virtual SteamCallHandle_t Login( const char *cszUser, const char *cszPassphrase, int bIsSecureComputer, TSteamError *pError ) = 0;
virtual SteamCallHandle_t AckSubscriptionReceipt( unsigned int uSubscriptionId, TSteamError *pError ) = 0;
virtual int IsAppSubscribed( unsigned int uAppId, int *pbIsAppSubscribed, int *pbIsSubscriptionPending, TSteamError *pError ) = 0;
virtual int GetSubscriptionIds( unsigned int *puIds, unsigned int uMaxIds, TSteamError *pError ) = 0;
virtual int EnumerateSubscription( unsigned int uId, TSteamSubscription *pSubscription, TSteamError *pError ) = 0;
virtual int EnumerateSubscriptionDiscount( unsigned int uSubscriptionId, unsigned int uDiscountIndex, TSteamSubscriptionDiscount *pDiscount, TSteamError *pError ) = 0;
virtual int EnumerateSubscriptionDiscountQualifier( unsigned int uSubscriptionId, unsigned int uDiscountIndex, unsigned int uQualifierIndex, TSteamDiscountQualifier *pDiscountQualifier, TSteamError *pError ) = 0;
virtual int EnumerateApp( unsigned int uId, TSteamApp *pApp, TSteamError *pError ) = 0;
virtual int EnumerateAppLaunchOption( unsigned int uAppId, unsigned int uLaunchOptionIndex, TSteamAppLaunchOption *pLaunchOption, TSteamError *pError ) = 0;
virtual SteamCallHandle_t DeleteAccount( TSteamError *pError ) = 0;
virtual int EnumerateAppIcon( unsigned int uAppId, unsigned int uIconIndex, unsigned char *pIconData, unsigned int uIconDataBufSize, unsigned int *puSizeOfIconData, TSteamError *pError ) = 0;
virtual SteamCallHandle_t LaunchApp( unsigned int uAppId, unsigned int uLaunchOption, const char *cszArgs, TSteamError *pError ) = 0;
virtual int GetCacheFilePath( unsigned int uCacheId, char *szPathBuf, unsigned int uBufSize, unsigned int *puPathChars, TSteamError *pError ) = 0;
virtual int EnumerateAppVersion( unsigned int uAppId, unsigned int uVersionIndex, TSteamAppVersion *pAppVersion, TSteamError *pError ) = 0;
virtual int EnumerateAppDependency( unsigned int uAppId, unsigned int uIndex, TSteamAppDependencyInfo *pDependencyInfo, TSteamError *pError ) = 0;
virtual SteamCallHandle_t StartLoadingCache( unsigned int uAppId, TSteamError *pError ) = 0;
virtual int InsertAppDependency( unsigned int uAppId, unsigned int uIndex, TSteamAppDependencyInfo *pDependencyInfo, TSteamError *pError ) = 0;
virtual int RemoveAppDependency( unsigned int uAppId, unsigned int uIndex, TSteamError *pError ) = 0;
virtual int FindApp( const char *cszAppName, unsigned int *puAppId, TSteamError *pError ) = 0;
virtual int GetAppDependencies( unsigned int uAppId, unsigned int *puCacheIds, unsigned int uMaxIds, TSteamError *pError ) = 0;
virtual int IsSubscribed( unsigned int uSubscriptionId, int *pbIsSubscribed, int *pbIsSubscriptionPending, TSteamError *pError ) = 0;
virtual int GetAppUserDefinedInfo( unsigned int uAppId, const char *cszKey, char *szValueBuf, unsigned int uValueBufLen, unsigned int *puValueLen, TSteamError *pError ) = 0;
virtual SteamCallHandle_t WaitForAppReadyToLaunch( unsigned int uAppId, TSteamError *pError ) = 0;
virtual int IsCacheLoadingEnabled( unsigned int uAppId, int *pbIsLoading, TSteamError *pError ) = 0;
virtual SteamCallHandle_t StopLoadingCache( unsigned int uAppId, TSteamError *pError ) = 0;
virtual ESteamError GetEncryptedUserIDTicket
(
const void * pEncryptionKey,
unsigned int uKeyLength,
void * pOutputBuffer,
unsigned int uSizeOfOutputBuffer,
unsigned int * pReceiveSizeOfEncryptedTicket,
TSteamError * pReceiveErrorCode
) = 0;
virtual SteamCallHandle_t FlushCache( unsigned int uCacheId, TSteamError *pError ) = 0;
virtual SteamCallHandle_t RepairOrDecryptCaches( unsigned int uAppId, int bForceValidation, TSteamError *pError ) = 0;
virtual SteamCallHandle_t LoadCacheFromDir( unsigned int uAppId, const char *szPath, TSteamError *pError ) = 0;
virtual int GetCacheDefaultDirectory( char *szPath, TSteamError *pError ) = 0;
virtual int SetCacheDefaultDirectory( const char *szPath, TSteamError *pError ) = 0;
virtual int GetAppDir( unsigned int uAppId, char *szPath, TSteamError *pError ) = 0;
virtual SteamCallHandle_t MoveApp( unsigned int uAppId, const char *szPath, TSteamError *pError ) = 0;
virtual SteamCallHandle_t GetAppCacheSize( unsigned int uCacheId, unsigned int *pCacheSizeInMb, TSteamError *pError ) = 0;
virtual SteamCallHandle_t SetAppCacheSize( unsigned int uCacheId, unsigned int nCacheSizeInMb, TSteamError *pError ) = 0;
virtual SteamCallHandle_t SetAppVersion( unsigned int uAppId, unsigned int uAppVersionId, TSteamError *pError ) = 0;
virtual SteamCallHandle_t Uninstall( TSteamError *pError ) = 0;
virtual int SetNotificationCallback( SteamNotificationCallback_t pCallbackFunction, TSteamError *pError ) = 0;
virtual SteamCallHandle_t ChangeForgottenPassword( const char *cszUser, const char *cszAnswerToQuestion, const char *cszEmailVerificationKey, const char *cszNewPassphrase, int *pbChanged, TSteamError *pError ) = 0;
virtual SteamCallHandle_t RequestForgottenPasswordEmail( const char *cszUser, SteamPersonalQuestion_t ReceivePersonalQuestion, TSteamError *pError ) = 0;
virtual SteamCallHandle_t RequestAccountsByEmailAddressEmail( const char *cszEmailAddress, TSteamError *pError ) = 0;
virtual SteamCallHandle_t RequestAccountsByCdKeyEmail( const char *cszCdKey, TSteamError *pError ) = 0;
virtual SteamCallHandle_t GetNumAccountsWithEmailAddress( const char *cszEmailAddress, unsigned int *puNumAccounts, TSteamError *pError ) = 0;
virtual SteamCallHandle_t UpdateAccountBillingInfo( const TSteamPaymentCardInfo *pPaymentCardInfo, TSteamError *pError ) = 0;
virtual SteamCallHandle_t UpdateSubscriptionBillingInfo( unsigned int uSubscriptionId, const TSteamSubscriptionBillingInfo *pSubscriptionBillingInfo, TSteamError *pError ) = 0;
virtual int GetSponsorUrl( unsigned int uAppId, char *szUrl, unsigned int uBufSize, unsigned int *pUrlChars, TSteamError *pError ) = 0;
virtual int GetContentServerInfo( unsigned int uAppId, unsigned int *puServerId, unsigned int *puServerIpAddress, TSteamError *pError ) = 0;
virtual SteamCallHandle_t GetAppUpdateStats( unsigned int uAppOrCacheId, ESteamAppUpdateStatsQueryType eQueryType, TSteamUpdateStats *pUpdateStats, TSteamError *pError ) = 0;
virtual int GetTotalUpdateStats( TSteamUpdateStats *pUpdateStats, TSteamError *pError ) = 0;
virtual SteamCallHandle_t CreateCachePreloaders( TSteamError *pError ) = 0;
virtual void Win32SetMiniDumpComment( const char *comment ) = 0;
virtual void Win32SetMiniDumpSourceControlId( unsigned int SourcecontrolID ) = 0;
virtual void Win32SetMiniDumpEnableFullMemory() = 0;
virtual void Win32WriteMiniDump( const char * szErrorOrAssertType, const char * szDescriptionOrAssertName, const char * szAssertExpr, const char * szAssertFilename, unsigned int uAssertLineNumber ) = 0;
virtual int GetCurrentAppId( unsigned int *puAppId, TSteamError *pError ) = 0;
virtual int GetAppPurchaseCountry( unsigned int uAppId, char *szCountry, unsigned int uBufSize, int * pPurchaseTime, TSteamError *pError ) = 0;
virtual int GetLocalClientVersion( unsigned int *puBootstrapperVersion, unsigned int *puClientVersion, TSteamError *pError ) = 0;
virtual int IsFileNeededByCache( unsigned int uCacheId, const char *pchFileName, unsigned int uFileSize, TSteamError *pError ) = 0;
virtual int LoadFileToCache( unsigned int uCacheId, const char *pchFileName, const void *pubDataChunk, unsigned int cubDataChunk, unsigned int cubDataOffset, TSteamError *pError ) = 0;
virtual int GetCacheDecryptionKey( unsigned int uCacheId, char *pchKeyBuffer, unsigned int cubBuff, unsigned int *pcubKey, TSteamError *pError ) = 0;
virtual int GetSubscriptionExtendedInfo( unsigned int uSubscriptionId, const char *cszKey, char *szValueBuf, unsigned int uValueBufLen, unsigned *puValueLen, TSteamError *pError ) = 0;
virtual int GetSubscriptionPurchaseCountry( unsigned int uSubscriptionId, char *szCountry, unsigned int uBufSize, int * pPurchaseTime, TSteamError *pError ) = 0;
virtual int GetAppUserDefinedRecord( unsigned int uAppid, KeyValueIteratorCallback_t pIterationCallback, void *pvParam, TSteamError *pError ) = 0;
virtual int FindServersNumServers(ESteamServerType eServerType) = 0;
// Get nth ipaddr:port for this server type
// buffer needs to be 22 chars long: aaa.bbb.ccc.ddd:12345 plus null
//
// returns 0 if succsessful, negative is error
virtual int FindServersIterateServer(ESteamServerType eServerType, unsigned int nServer, char *szIpAddrPort, int szIpAddrPortLen) = 0;
virtual const char * FindServersGetErrorString() = 0;
};
#endif

View File

@ -0,0 +1,118 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*******************************************************************************
**
** Contents:
**
** This file provides the public interface to the Steam service. This
** interface is described in the SDK documentation.
**
******************************************************************************/
#ifndef INCLUDED_STEAMUSERIDVALIDATION_H
#define INCLUDED_STEAMUSERIDVALIDATION_H
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
#ifndef INCLUDED_STEAM2_USERID_STRUCTS
#include "SteamCommon.h"
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/*
** User ID
*/
/* Client calls this (see also ValidateNewValveCDKeyClient.h if appropriate) */
STEAM_API ESteamError STEAM_CALL SteamGetEncryptedUserIDTicket
(
const void * pEncryptionKeyReceivedFromAppServer,
unsigned int uEncryptionKeyLength,
void * pOutputBuffer,
unsigned int uSizeOfOutputBuffer,
unsigned int * pReceiveSizeOfEncryptedTicket,
TSteamError * pReceiveErrorCode
);
/* Game/Application server calls these */
STEAM_API ESteamError STEAM_CALL SteamInitializeUserIDTicketValidator
(
const char * pszOptionalPublicEncryptionKeyFilename,
const char * pszOptionalPrivateDecryptionKeyFilename,
unsigned int ClientClockSkewToleranceInSeconds,
unsigned int ServerClockSkewToleranceInSeconds,
unsigned int MaxNumLoginsWithinClientClockSkewTolerancePerClient,
unsigned int HintPeakSimultaneousValidations,
unsigned int AbortValidationAfterStallingForNProcessSteps
);
STEAM_API ESteamError STEAM_CALL SteamShutdownUserIDTicketValidator();
STEAM_API const char * STEAM_CALL SteamGetEncryptionKeyToSendToNewClient
(
unsigned int * pReceiveSizeOfEncryptionKey
);
STEAM_API ESteamError STEAM_CALL SteamStartValidatingUserIDTicket
(
void * pEncryptedUserIDTicketFromClient,
unsigned int uSizeOfEncryptedUserIDTicketFromClient,
unsigned int ObservedClientIPAddr,
SteamUserIDTicketValidationHandle_t * pReceiveHandle
);
STEAM_API ESteamError STEAM_CALL SteamStartValidatingNewValveCDKey
(
void * pEncryptedNewValveCDKeyFromClient,
unsigned int uSizeOfEncryptedNewValveCDKeyFromClient,
unsigned int ObservedClientIPAddr,
struct sockaddr * pPrimaryValidateNewCDKeyServerSockAddr,
struct sockaddr * pSecondaryValidateNewCDKeyServerSockAddr,
SteamUserIDTicketValidationHandle_t * pReceiveHandle
);
STEAM_API ESteamError STEAM_CALL SteamProcessOngoingUserIDTicketValidation
(
SteamUserIDTicketValidationHandle_t Handle,
TSteamGlobalUserID * pReceiveValidSteamGlobalUserID,
unsigned int * pReceiveClientLocalIPAddr,
unsigned char * pOptionalReceiveProofOfAuthenticationToken,
size_t SizeOfOptionalAreaToReceiveProofOfAuthenticationToken,
size_t * pOptionalReceiveSizeOfProofOfAuthenticationToken
);
STEAM_API void STEAM_CALL SteamAbortOngoingUserIDTicketValidation
(
SteamUserIDTicketValidationHandle_t Handle
);
STEAM_API ESteamError STEAM_CALL SteamOptionalCleanUpAfterClientHasDisconnected
(
unsigned int ObservedClientIPAddr,
unsigned int ClientLocalIPAddr
);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef INCLUDED_STEAM2_USERID_STRUCTS */

View File

@ -0,0 +1,64 @@
/************ (C) Copyright 2002 Valve, L.L.C. All rights reserved. ***********
**
** The copyright to the contents herein is the property of Valve, L.L.C.
** The contents may be used and/or copied only with the written permission of
** Valve, L.L.C., or in accordance with the terms and conditions stipulated in
** the agreement/contract under which the contents have been supplied.
**
*******************************************************************************
**
** Contents:
**
** This file provides the public interface to the Steam service. This
** interface is described in the SDK documentation.
**
******************************************************************************/
#ifndef INCLUDED_STEAMWRITEMINIDUMP_H
#define INCLUDED_STEAMWRITEMINIDUMP_H
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif
#ifndef INCLUDED_STEAM2_USERID_STRUCTS
#include "SteamCommon.h"
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef _WIN32
/*
** Write minidump using result of GetExceptionInformation() in an __except block
*/
STEAM_API void STEAM_CALL SteamWriteMiniDumpUsingExceptionInfo
(
unsigned int uStructuredExceptionCode,
struct _EXCEPTION_POINTERS * pExceptionInfo
);
STEAM_API void STEAM_CALL SteamWriteMiniDumpUsingExceptionInfoWithBuildId
(
unsigned int uStructuredExceptionCode,
struct _EXCEPTION_POINTERS * pExceptionInfo,
unsigned int uBuildID
);
STEAM_API void STEAM_CALL SteamWriteMiniDumpSetComment
(
const char *cszComment
);
#endif // _WIN32
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,48 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "engine/iblackbox.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IBlackBox *blackboxrecorder;
void BlackBox_Record( const char *type, PRINTF_FORMAT_STRING const char *pFormat, ... )
{
static ConVarRef blackbox( "blackbox" );
if ( IsX360() )
return;
if ( !blackbox.IsValid() || !blackbox.GetBool() )
return;
int type_num;
for ( type_num = 0; type_num < blackboxrecorder->GetTypeCount(); type_num++ )
{
if ( !V_strcasecmp( blackboxrecorder->GetTypeName( type_num ), type ) )
break;
}
if ( type_num >= blackboxrecorder->GetTypeCount() )
{
Msg( "Invalid blackbox type: %s\n", type );
return;
}
char szMessage[1024];
va_list marker;
va_start( marker, pFormat);
Q_vsnprintf( szMessage, sizeof( szMessage ), pFormat, marker);
va_end( marker );
//Msg( "Record: %s: %s\n", type, szMessage );
blackboxrecorder->Record( type_num, szMessage );
}

Some files were not shown because too many files have changed in this diff Show More