initial
This commit is contained in:
parent
f234f23848
commit
f12416cffd
319
.gitignore
vendored
319
.gitignore
vendored
@ -1,34 +1,301 @@
|
|||||||
# ---> C++
|
#Ignore my HL2 Install Directory
|
||||||
# Prerequisites
|
/HL2_base/
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
#Ignore the sapi folder.
|
||||||
*.slo
|
src/utils/sapi51/
|
||||||
*.lo
|
|
||||||
*.o
|
#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
|
*.obj
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
# Chutzpah Test files
|
||||||
*.so
|
_Chutzpah*
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Fortran module files
|
# Visual C++ cache files
|
||||||
*.mod
|
ipch/
|
||||||
*.smod
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
# Compiled Static libraries
|
# Visual Studio profiler
|
||||||
*.lai
|
*.psess
|
||||||
*.la
|
*.vsp
|
||||||
*.a
|
*.vspx
|
||||||
*.lib
|
*.sap
|
||||||
|
|
||||||
# Executables
|
# TFS 2012 Local Workspace
|
||||||
*.exe
|
$tf/
|
||||||
*.out
|
|
||||||
*.app
|
# 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
|
||||||
|
|
||||||
|
5
CSGO NEEDS MAY 18 2017 FILES BEFORE HYDRA.txt
Normal file
5
CSGO NEEDS MAY 18 2017 FILES BEFORE HYDRA.txt
Normal 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
2
CreateSolution.bat
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
devtools\bin\vpc.exe /csgo +csgo_partner /mksln csgo_partner.sln
|
||||||
|
pause
|
982
appframework/AppSystemGroup.cpp
Normal file
982
appframework/AppSystemGroup.cpp
Normal 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;
|
||||||
|
}
|
119
appframework/VguiMatSysApp.cpp
Normal file
119
appframework/VguiMatSysApp.cpp
Normal 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
235
appframework/WinApp.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
40
appframework/_vpc_/manifest_appframework/win32/manifest.txt
Normal file
40
appframework/_vpc_/manifest_appframework/win32/manifest.txt
Normal 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:
|
||||||
|
|
61
appframework/appframework.vpc
Normal file
61
appframework/appframework.vpc
Normal 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]
|
||||||
|
}
|
||||||
|
}
|
13
appframework/appframework.vpc.vpc_cache
Normal file
13
appframework/appframework.vpc.vpc_cache
Normal 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
3828
appframework/cocoamgr.mm
Normal file
File diff suppressed because it is too large
Load Diff
630
appframework/glmdisplaydb_linuxwin.inl
Normal file
630
appframework/glmdisplaydb_linuxwin.inl
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
1583
appframework/glmrendererinfo_osx.mm
Normal file
1583
appframework/glmrendererinfo_osx.mm
Normal file
File diff suppressed because it is too large
Load Diff
410
appframework/materialsystem2app.cpp
Normal file
410
appframework/materialsystem2app.cpp
Normal 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
267
appframework/matsysapp.cpp
Normal 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
180
appframework/posixapp.cpp
Normal 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
2137
appframework/sdlmgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
appframework/vguimaterialsystem2app.cpp
Normal file
120
appframework/vguimaterialsystem2app.cpp
Normal 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
1
appframework/vsi.nul
Normal file
@ -0,0 +1 @@
|
|||||||
|
IMPORTANT: Do not remove the custom build step for this file
|
28
avi/_vpc_/manifest_valve_avi/win32/manifest.txt
Normal file
28
avi/_vpc_/manifest_valve_avi/win32/manifest.txt
Normal 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
1184
avi/avi.cpp
Normal file
File diff suppressed because it is too large
Load Diff
30
avi/avi.h
Normal file
30
avi/avi.h
Normal 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
662
avi/avi_osx.cpp
Normal 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
1938
avi/bink.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1133
avi/quicktime.cpp
Normal file
1133
avi/quicktime.cpp
Normal file
File diff suppressed because it is too large
Load Diff
274
avi/quicktime.h
Normal file
274
avi/quicktime.h
Normal 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
74
avi/valve_avi.vpc
Normal 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]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
13
avi/valve_avi.vpc.vpc_cache
Normal file
13
avi/valve_avi.vpc.vpc_cache
Normal 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
277
bitmap/ImageByteSwap.cpp
Normal 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
|
||||||
|
}
|
||||||
|
}
|
100
bitmap/_vpc_/manifest_bitmap/win32/manifest.txt
Normal file
100
bitmap/_vpc_/manifest_bitmap/win32/manifest.txt
Normal 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:
|
||||||
|
|
16
bitmap/_vpc_/manifest_bitmap_byteswap/win32/manifest.txt
Normal file
16
bitmap/_vpc_/manifest_bitmap_byteswap/win32/manifest.txt
Normal 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
778
bitmap/bitmap.cpp
Normal 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
63
bitmap/bitmap.vpc
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
13
bitmap/bitmap.vpc.vpc_cache
Normal file
13
bitmap/bitmap.vpc.vpc_cache
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
"vpc_cache"
|
||||||
|
{
|
||||||
|
"CacheVersion" "1"
|
||||||
|
"win32"
|
||||||
|
{
|
||||||
|
"CRCFile" "bitmap.vcxproj.vpc_crc"
|
||||||
|
"OutputFiles"
|
||||||
|
{
|
||||||
|
"0" "bitmap.vcxproj"
|
||||||
|
"1" "bitmap.vcxproj.filters"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
bitmap/bitmap_byteswap.vpc
Normal file
47
bitmap/bitmap_byteswap.vpc
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
13
bitmap/bitmap_byteswap.vpc.vpc_cache
Normal file
13
bitmap/bitmap_byteswap.vpc.vpc_cache
Normal 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
2495
bitmap/colorconversion.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1618
bitmap/floatbitmap.cpp
Normal file
1618
bitmap/floatbitmap.cpp
Normal file
File diff suppressed because it is too large
Load Diff
151
bitmap/floatbitmap2.cpp
Normal file
151
bitmap/floatbitmap2.cpp
Normal 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
118
bitmap/floatbitmap3.cpp
Normal 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
354
bitmap/floatbitmap4.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
105
bitmap/floatbitmap_bilateralfilter.cpp
Normal file
105
bitmap/floatbitmap_bilateralfilter.cpp
Normal 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
179
bitmap/floatcubemap.cpp
Normal 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
651
bitmap/imageformat.cpp
Normal 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
571
bitmap/psd.cpp
Normal 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
477
bitmap/psheet.cpp
Normal 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
902
bitmap/resample.cpp
Normal 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
274
bitmap/texturepacker.cpp
Normal 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
1023
bitmap/tgaloader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
496
bitmap/tgawriter.cpp
Normal file
496
bitmap/tgawriter.cpp
Normal 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
2
bitmap/vsi.nul
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
SN Visual Studio Integration
|
||||||
|
IMPORTANT: Do not remove the custom build step for this file
|
40
bonesetup/_vpc_/manifest_bonesetup/win32/manifest.txt
Normal file
40
bonesetup/_vpc_/manifest_bonesetup/win32/manifest.txt
Normal 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:
|
||||||
|
|
898
bonesetup/bone_constraints.cpp
Normal file
898
bonesetup/bone_constraints.cpp
Normal 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
1681
bonesetup/bone_decode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1850
bonesetup/bone_decode_PS3.cpp
Normal file
1850
bonesetup/bone_decode_PS3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2226
bonesetup/bone_ik.cpp
Normal file
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
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
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
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
3745
bonesetup/bone_utils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
91
bonesetup/bone_utils.h
Normal file
91
bonesetup/bone_utils.h
Normal 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
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
359
bonesetup/bone_utils_PS3.h
Normal 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
47
bonesetup/bonesetup.vpc
Normal 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]
|
||||||
|
}
|
||||||
|
}
|
13
bonesetup/bonesetup.vpc.vpc_cache
Normal file
13
bonesetup/bonesetup.vpc.vpc_cache
Normal 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
2
bonesetup/vsi.nul
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
SN Visual Studio Integration
|
||||||
|
IMPORTANT: Do not remove the custom build step for this 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:
|
||||||
|
|
46
choreoobjects/choreoobjects.vpc
Normal file
46
choreoobjects/choreoobjects.vpc
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
13
choreoobjects/choreoobjects.vpc.vpc_cache
Normal file
13
choreoobjects/choreoobjects.vpc.vpc_cache
Normal 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
2
choreoobjects/vsi.nul
Normal 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
907
common/CegClient.h
Normal 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_
|
46
common/CegClientWrapper.cpp
Normal file
46
common/CegClientWrapper.cpp
Normal 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
301
common/CegClientWrapper.h
Normal 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
977
common/ConfigManager.cpp
Normal 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
135
common/ConfigManager.h
Normal 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
94
common/FindSteamServers.h
Normal 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 */
|
44
common/GameUI/IGameConsole.h
Normal file
44
common/GameUI/IGameConsole.h
Normal 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
141
common/GameUI/IGameUI.h
Normal 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
|
247
common/GameUI/ObjectList.cpp
Normal file
247
common/GameUI/ObjectList.cpp
Normal 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 );
|
||||||
|
}
|
||||||
|
|
58
common/GameUI/ObjectList.h
Normal file
58
common/GameUI/ObjectList.h
Normal 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
129
common/GameUI/Random.cpp
Normal 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
30
common/GameUI/Random.h
Normal 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
43
common/IAdminServer.h
Normal 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
|
51
common/IFileSystemOpenDialog.h
Normal file
51
common/IFileSystemOpenDialog.h
Normal 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
34
common/IManageServer.h
Normal 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
32
common/IObjectContainer.h
Normal 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
81
common/IRunGameEngine.h
Normal 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
|
33
common/IVGuiModuleLoader.h
Normal file
33
common/IVGuiModuleLoader.h
Normal 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
64
common/IVguiModule.h
Normal 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
|
45
common/ServerBrowser/IServerBrowser.h
Normal file
45
common/ServerBrowser/IServerBrowser.h
Normal 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
92
common/SourceAppInfo.cpp
Normal 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
31
common/SourceAppInfo.h
Normal 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
218
common/Steam.h
Normal 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
198
common/SteamAppStartup.cpp
Normal 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
25
common/SteamAppStartup.h
Normal 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
162
common/SteamBootStrapper.h
Normal 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
703
common/SteamCommon.h
Normal 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
226
common/SteamInterface.h
Normal 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
|
118
common/SteamUserIDValidation.h
Normal file
118
common/SteamUserIDValidation.h
Normal 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 */
|
64
common/SteamWriteMiniDump.h
Normal file
64
common/SteamWriteMiniDump.h
Normal 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
|
48
common/blackbox_helper.cpp
Normal file
48
common/blackbox_helper.cpp
Normal 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
Loading…
x
Reference in New Issue
Block a user