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