diff --git a/AMBuildScript b/AMBuildScript new file mode 100644 index 00000000..bdbb7d10 --- /dev/null +++ b/AMBuildScript @@ -0,0 +1,161 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys, shutil +from ambuild2 import util + +def ResolveEnvPath(env, folder=None): + if env in os.environ: + path = os.environ[env] + if os.path.isdir(path): + return path + return None + + if folder: + head = os.getcwd() + oldhead = None + while head != None and head != oldhead: + path = os.path.join(head, folder) + if os.path.isdir(path): + return path + oldhead = head + head, tail = os.path.split(head) + + return None + +def Normalize(path): + return os.path.abspath(os.path.normpath(path)) + +class SDKConfig(object): + def __init__(self): + self.libs = [] + self.targets = [] + self.target_archs = set() + + if builder.options.targets: + target_archs = builder.options.targets.split(',') + else: + target_archs = ['x86', 'x86_64'] + + for arch in target_archs: + try: + cxx = builder.DetectCxx(target_arch = arch) + self.target_archs.add(cxx.target.arch) + except Exception as e: + if builder.options.targets: + raise + print('Skipping target {}: {}'.format(arch, e)) + continue + self.targets.append(cxx) + + if not self.targets: + raise Exception('No suitable C/C++ compiler was found.') + + @property + def tag(self): + if builder.options.debug == '1': + return 'Debug' + return 'Release' + + def configure_cxx(self, cxx): + if cxx.like('gcc'): + self.configure_gcc(cxx) + elif cxx.family == 'msvc': + self.configure_msvc(cxx) + + # Optimization + if builder.options.opt == '1': + cxx.defines += ['NDEBUG'] + + # Debugging + if builder.options.debug == '1': + cxx.defines += ['DEBUG', '_DEBUG'] + + if cxx.target.arch == 'x86_64': + cxx.defines += ['X64BITS', 'PLATFORM_64BITS'] + + # Platform-specifics + if cxx.target.platform == 'linux': + self.configure_linux(cxx) + elif cxx.target.platform == 'windows': + self.configure_windows(cxx) + + def configure_gcc(self, cxx): + cxx.cflags += [ + '-Wall', + '-Werror', + '-Wno-overloaded-virtual', + '-msse', + '-fPIC' + ] + + cxx.defines += [ + 'COMPILER_GCC' + ] + + cxx.cxxflags += [ + '-std=c++17' + ] + + if builder.options.opt == '1': + cxx.cflags += ['-O3'] + return + + def configure_msvc(self, cxx): + cxx.defines += ['COMPILER_MSVC'] + if cxx.target.arch == 'x86': + cxx.defines += ['COMPILER_MSVC32'] + elif cxx.target.arch == 'x86_64': + cxx.defines += ['COMPILER_MSVC64'] + + cxx.cxxflags += [ + '/std:c++17', + '/WX' + ] + + if builder.options.opt == '1': + cxx.cflags += ['/Ox', '/Zo'] + cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + + return + + def configure_linux(self, cxx): + cxx.defines += ['_LINUX', 'LINUX', 'POSIX', 'GNUC'] + + # Set of defines required by the HL2SDK + cxx.defines += [ + '_finite=finite', 'stricmp=strcasecmp', + '_stricmp=strcasecmp', '_strnicmp=strncasecmp', + 'strnicmp=strncasecmp', '_vsnprintf=vsnprintf', + '_alloca=alloca', 'strcmpi=strcasecmp', + 'NO_MALLOC_OVERRIDE' + ] + return + + def configure_windows(self, cxx): + cxx.defines += ['_WINDOWS'] + if cxx.target.arch == 'x86': + cxx.defines += ['WIN32'] + elif cxx.target.arch == 'x86_64': + cxx.defines += ['WIN64'] + return + + def configure(self): + for cxx in self.targets: + self.configure_cxx(cxx) + + def ConfigureLibrary(self, project, compiler, context, prefix = ''): + name = prefix + project.name + if compiler.target.platform == 'linux' and compiler.target.arch == 'x86': + name += '_i486' + binary = project.Configure(compiler, name, '{0} - {1}'.format(self.tag, compiler.target.arch)) + binary.compiler.cxxincludes += [ + os.path.join(context.currentSourcePath) + ] + return binary + +HL2SDK = SDKConfig() +HL2SDK.configure() + +BuildScripts = ['mathlib/AMBuilder', 'tier1/AMBuilder', 'PackageScript'] +# Turn off the 'lib' prefix for all platform, we will add it if we need to +util.StaticLibPrefix = '' +builder.Build(BuildScripts, { 'HL2SDK': HL2SDK }) \ No newline at end of file diff --git a/PackageScript b/PackageScript new file mode 100644 index 00000000..aad4aca3 --- /dev/null +++ b/PackageScript @@ -0,0 +1,56 @@ +# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: +import os + +# This is where the files will be output to +# package is the default +builder.SetBuildFolder('lib') + + +folder_list = [] + +for task in HL2SDK.libs: + if task.target.platform == 'windows': + folder_list += ['public', 'public/win64'] + break + +for task in HL2SDK.libs: + if task.target.platform == 'linux': + folder_list += ['linux', 'linux64'] + break + +# Create the distribution folder hierarchy. +folder_map = {} +for folder in folder_list: + norm_folder = os.path.normpath(folder) + folder_map[folder] = builder.AddFolder(norm_folder) + +# Do all straight-up file copies from the source tree. +def CopyFiles(src, dest, files): + if not dest: + dest = src + dest_entry = folder_map[dest] + for source_file in files: + source_path = os.path.join(builder.sourcePath, src, source_file) + builder.AddCopy(source_path, dest_entry) +def CopyFile(src, dest): + dest_entry = folder_map[dest] + source_path = os.path.join(builder.sourcePath, src) + builder.AddCopy(source_path, dest_entry) +def CopyDirContent(src, dest): + dest_entry = folder_map[dest] + for item in os.scandir(os.path.join(builder.sourcePath, src)): + if item.is_file(): + builder.AddCopy(item.path, dest_entry) + +# Copy binaries. +for task in HL2SDK.libs: + if task.target.platform == 'linux': + if task.target.arch == 'x86_64': + builder.AddCopy(task.binary, folder_map['linux64']) + else: + builder.AddCopy(task.binary, folder_map['linux']) + elif task.target.platform == 'windows': + if task.target.arch == 'x86_64': + builder.AddCopy(task.binary, folder_map['public/win64']) + else: + builder.AddCopy(task.binary, folder_map['public']) \ No newline at end of file diff --git a/configure.py b/configure.py new file mode 100644 index 00000000..ad589bc4 --- /dev/null +++ b/configure.py @@ -0,0 +1,11 @@ +import sys +from ambuild2 import run + +parser = run.BuildParser(sourcePath = sys.path[0], api='2.2') +parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug', + help='Enable debugging symbols') +parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', + help='Enable optimization') +parser.options.add_argument('--targets', type=str, dest='targets', default=None, + help="Override the target architecture (use commas to separate multiple targets).") +parser.Configure() \ No newline at end of file diff --git a/game/client/cdll_util.cpp b/game/client/cdll_util.cpp index 8f2f26e9..922e1549 100644 --- a/game/client/cdll_util.cpp +++ b/game/client/cdll_util.cpp @@ -943,7 +943,7 @@ static unsigned char ComputeDistanceFade( C_BaseEntity *pEntity, float flMinDist if( flMinDist > flMaxDist ) { - V_swap( flMinDist, flMaxDist ); + ::V_swap( flMinDist, flMaxDist ); } // If a negative value is provided for the min fade distance, then base it off the max. @@ -1192,4 +1192,4 @@ int UTIL_GetMapKeyCount( const char *pszCustomKey ) } return iCount; -} \ No newline at end of file +} diff --git a/game/client/clientleafsystem.cpp b/game/client/clientleafsystem.cpp index bbb46383..a5408342 100644 --- a/game/client/clientleafsystem.cpp +++ b/game/client/clientleafsystem.cpp @@ -1722,8 +1722,8 @@ void CClientLeafSystem::SortEntities( const Vector &vecRenderOrigin, const Vecto { if( dists[i] > dists[i+stepSize] ) { - V_swap( pEntities[i], pEntities[i+stepSize] ); - V_swap( dists[i], dists[i+stepSize] ); + ::V_swap( pEntities[i], pEntities[i+stepSize] ); + ::V_swap( dists[i], dists[i+stepSize] ); if( i == 0 ) { diff --git a/game/client/clientshadowmgr.cpp b/game/client/clientshadowmgr.cpp index 48927a25..88ba6aed 100644 --- a/game/client/clientshadowmgr.cpp +++ b/game/client/clientshadowmgr.cpp @@ -1138,7 +1138,7 @@ void CVisibleShadowList::PrioritySort() flLargestArea = m_ShadowsInView[nIndex].m_flArea; } } - V_swap( m_PriorityIndex[i], m_PriorityIndex[nLargestInd] ); + ::V_swap( m_PriorityIndex[i], m_PriorityIndex[nLargestInd] ); } } diff --git a/game/client/detailobjectsystem.cpp b/game/client/detailobjectsystem.cpp index 31a012f9..3ce9fcfa 100644 --- a/game/client/detailobjectsystem.cpp +++ b/game/client/detailobjectsystem.cpp @@ -1613,7 +1613,7 @@ void CDetailObjectSystem::UnserializeDetailSprites( CUtlBuffer& buf ) buf.Get( &m_DetailSpriteDict[i], sizeof(DetailSpriteDictLump_t) ); int flipi = m_DetailSpriteDictFlipped.AddToTail(); m_DetailSpriteDictFlipped[flipi] = m_DetailSpriteDict[i]; - V_swap( m_DetailSpriteDictFlipped[flipi].m_TexUL.x, m_DetailSpriteDictFlipped[flipi].m_TexLR.x ); + ::V_swap( m_DetailSpriteDictFlipped[flipi].m_TexUL.x, m_DetailSpriteDictFlipped[flipi].m_TexLR.x ); } } diff --git a/game/server/filters.cpp b/game/server/filters.cpp index 09ee23bc..49cd70b8 100644 --- a/game/server/filters.cpp +++ b/game/server/filters.cpp @@ -536,7 +536,7 @@ bool CFilterEnemy::PassesProximityFilter( CBaseEntity *pCaller, CBaseEntity *pEn float flSmallerRadius = m_flRadius; if ( flSmallerRadius > flLargerRadius ) { - V_swap( flLargerRadius, flSmallerRadius ); + ::V_swap( flLargerRadius, flSmallerRadius ); } float flDist; diff --git a/game/server/hltvdirector.cpp b/game/server/hltvdirector.cpp index 42b02f91..5e4c6d41 100644 --- a/game/server/hltvdirector.cpp +++ b/game/server/hltvdirector.cpp @@ -562,7 +562,7 @@ void CHLTVDirector::CreateShotFromEvent( CGameEvent *event ) // if we show ineye view, show it more likely from killer if ( RandomFloat(0,1) > (bInEye?0.3f:0.7f) ) { - V_swap( attacker, victim ); + ::V_swap( attacker, victim ); } // hurting a victim is shown as chase more often diff --git a/game/server/physconstraint.cpp b/game/server/physconstraint.cpp index 7b24bc58..27154f01 100644 --- a/game/server/physconstraint.cpp +++ b/game/server/physconstraint.cpp @@ -1280,7 +1280,7 @@ IPhysicsConstraint *CPhysSlideConstraint::CreateConstraint( IPhysicsConstraintGr sliding.limitMax = DotProduct( axisDirection, m_axisEnd ); if ( sliding.limitMax < sliding.limitMin ) { - V_swap( sliding.limitMin, sliding.limitMax ); + ::V_swap( sliding.limitMin, sliding.limitMax ); } // expand limits to make initial position of the attached object valid diff --git a/game/server/props.cpp b/game/server/props.cpp index 9726f433..97ca020f 100644 --- a/game/server/props.cpp +++ b/game/server/props.cpp @@ -4789,7 +4789,7 @@ void CPropDoorRotating::Spawn() // that the model already be set. if ( IsHingeOnLeft() ) { - V_swap( m_angRotationOpenForward, m_angRotationOpenBack ); + ::V_swap( m_angRotationOpenForward, m_angRotationOpenBack ); } // Figure out our volumes of movement as this door opens diff --git a/game/server/scratchpad_gamedll_helpers.cpp b/game/server/scratchpad_gamedll_helpers.cpp index 26916ccf..c42874ff 100644 --- a/game/server/scratchpad_gamedll_helpers.cpp +++ b/game/server/scratchpad_gamedll_helpers.cpp @@ -15,7 +15,7 @@ void ScratchPad_DrawWorldToScratchPad( IScratchPad3D *pPad, - unsigned long flags ) + uint32_t flags ) { pPad->SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Wireframe ); @@ -52,7 +52,7 @@ void ScratchPad_DrawWorldToScratchPad( void ScratchPad_DrawEntityToScratchPad( IScratchPad3D *pPad, - unsigned long flags, + uint32_t flags, CBaseEntity *pEnt, const Vector &vColor ) { diff --git a/game/server/scratchpad_gamedll_helpers.h b/game/server/scratchpad_gamedll_helpers.h index 651fea50..f45e09eb 100644 --- a/game/server/scratchpad_gamedll_helpers.h +++ b/game/server/scratchpad_gamedll_helpers.h @@ -27,12 +27,12 @@ class IScratchPad3D; // flags is a combination of the SPDRAWWORLD_ flags. void ScratchPad_DrawWorldToScratchPad( IScratchPad3D *pPad, - unsigned long flags ); + uint32_t flags ); // Draw a specific entity into the scratch pad. void ScratchPad_DrawEntityToScratchPad( IScratchPad3D *pPad, - unsigned long flags, + uint32_t flags, CBaseEntity *pEnt, const Vector &vColor ); diff --git a/game/shared/basecombatweapon_shared.h b/game/shared/basecombatweapon_shared.h index 2ec40350..58e9209b 100644 --- a/game/shared/basecombatweapon_shared.h +++ b/game/shared/basecombatweapon_shared.h @@ -86,7 +86,7 @@ class Color; namespace vgui2 { - typedef unsigned long HFont; + typedef uint32_t HFont; } // ----------------------------------------- diff --git a/game/shared/choreoactor.cpp b/game/shared/choreoactor.cpp index 22be6261..e6c99d98 100644 --- a/game/shared/choreoactor.cpp +++ b/game/shared/choreoactor.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -45,7 +45,7 @@ CChoreoActor& CChoreoActor::operator=( const CChoreoActor& src ) Q_strncpy( m_szName, src.m_szName, sizeof( m_szName ) ); Q_strncpy( m_szFacePoserModelName, src.m_szFacePoserModelName, sizeof( m_szFacePoserModelName ) ); - for ( int i = 0; i < src.m_Channels.Size(); i++ ) + for ( int i = 0; i < src.m_Channels.Count(); i++ ) { CChoreoChannel *c = src.m_Channels[ i ]; CChoreoChannel *newChannel = new CChoreoChannel(); @@ -92,7 +92,7 @@ const char *CChoreoActor::GetName( void ) //----------------------------------------------------------------------------- int CChoreoActor::GetNumChannels( void ) { - return m_Channels.Size(); + return m_Channels.Count(); } //----------------------------------------------------------------------------- @@ -102,7 +102,7 @@ int CChoreoActor::GetNumChannels( void ) //----------------------------------------------------------------------------- CChoreoChannel *CChoreoActor::GetChannel( int channel ) { - if ( channel < 0 || channel >= m_Channels.Size() ) + if ( channel < 0 || channel >= m_Channels.Count() ) { return NULL; } @@ -161,7 +161,7 @@ void CChoreoActor::SwapChannels( int c1, int c2 ) //----------------------------------------------------------------------------- int CChoreoActor::FindChannelIndex( CChoreoChannel *channel ) { - for ( int i = 0; i < m_Channels.Size(); i++ ) + for ( int i = 0; i < m_Channels.Count(); i++ ) { if ( channel == m_Channels[ i ] ) { diff --git a/game/shared/choreochannel.cpp b/game/shared/choreochannel.cpp index b6b3ea44..d6bf4e4f 100644 --- a/game/shared/choreochannel.cpp +++ b/game/shared/choreochannel.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -45,7 +45,7 @@ CChoreoChannel& CChoreoChannel::operator=( const CChoreoChannel& src ) { m_bActive = src.m_bActive; Q_strncpy( m_szName, src.m_szName, sizeof( m_szName ) ); - for ( int i = 0; i < src.m_Events.Size(); i++ ) + for ( int i = 0; i < src.m_Events.Count(); i++ ) { CChoreoEvent *e = src.m_Events[ i ]; CChoreoEvent *newEvent = new CChoreoEvent( e->GetScene() ); @@ -83,7 +83,7 @@ const char *CChoreoChannel::GetName( void ) //----------------------------------------------------------------------------- int CChoreoChannel::GetNumEvents( void ) { - return m_Events.Size(); + return m_Events.Count(); } //----------------------------------------------------------------------------- @@ -93,7 +93,7 @@ int CChoreoChannel::GetNumEvents( void ) //----------------------------------------------------------------------------- CChoreoEvent *CChoreoChannel::GetEvent( int event ) { - if ( event < 0 || event >= m_Events.Size() ) + if ( event < 0 || event >= m_Events.Count() ) { return NULL; } @@ -138,7 +138,7 @@ void CChoreoChannel::RemoveAllEvents() //----------------------------------------------------------------------------- int CChoreoChannel::FindEventIndex( CChoreoEvent *event ) { - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { if ( event == m_Events[ i ] ) { diff --git a/game/shared/choreoevent.cpp b/game/shared/choreoevent.cpp index f95a3ecc..70d51507 100644 --- a/game/shared/choreoevent.cpp +++ b/game/shared/choreoevent.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -432,7 +432,7 @@ CFlexAnimationTrack::CFlexAnimationTrack( const CFlexAnimationTrack* src ) for ( int t = 0; t < 2; t++ ) { m_Samples[ t ].Purge(); - for ( int i = 0 ;i < src->m_Samples[ t ].Size(); i++ ) + for ( int i = 0 ;i < src->m_Samples[ t ].Count(); i++ ) { CExpressionSample s = src->m_Samples[ t ][ i ]; m_Samples[ t ].AddToTail( s ); @@ -527,7 +527,7 @@ int CFlexAnimationTrack::GetNumSamples( int type /*=0*/ ) { Assert( type == 0 || type == 1 ); - return m_Samples[ type ].Size(); + return m_Samples[ type ].Count(); } //----------------------------------------------------------------------------- @@ -931,9 +931,9 @@ void CFlexAnimationTrack::Resort( int type /*=0*/ ) { Assert( type == 0 || type == 1 ); - for ( int i = 0; i < m_Samples[ type ].Size(); i++ ) + for ( int i = 0; i < m_Samples[ type ].Count(); i++ ) { - for ( int j = i + 1; j < m_Samples[ type ].Size(); j++ ) + for ( int j = i + 1; j < m_Samples[ type ].Count(); j++ ) { CExpressionSample src = m_Samples[ type ][ i ]; CExpressionSample dest = m_Samples[ type ][ j ]; @@ -1116,7 +1116,7 @@ void CFlexAnimationTrack::RemoveOutOfRangeSamples( int type ) Assert( m_pEvent->HasEndTime() ); float duration = m_pEvent->GetDuration(); - int c = m_Samples[ type ].Size(); + int c = m_Samples[ type ].Count(); for ( int i = c-1; i >= 0; i-- ) { CExpressionSample src = m_Samples[ type ][ i ]; @@ -1217,14 +1217,14 @@ CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src ) } int i; - for ( i = 0; i < src.m_RelativeTags.Size(); i++ ) + for ( i = 0; i < src.m_RelativeTags.Count(); i++ ) { CEventRelativeTag newtag( src.m_RelativeTags[ i ] ); newtag.SetOwner( this ); m_RelativeTags.AddToTail( newtag ); } - for ( i = 0; i < src.m_TimingTags.Size(); i++ ) + for ( i = 0; i < src.m_TimingTags.Count(); i++ ) { CFlexTimingTag newtag( src.m_TimingTags[ i ] ); newtag.SetOwner( this ); @@ -1232,7 +1232,7 @@ CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src ) } for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) { - for ( i = 0; i < src.m_AbsoluteTags[ t ].Size(); i++ ) + for ( i = 0; i < src.m_AbsoluteTags[ t ].Count(); i++ ) { CEventAbsoluteTag newtag( src.m_AbsoluteTags[ t ][ i ] ); newtag.SetOwner( this ); @@ -1242,7 +1242,7 @@ CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src ) RemoveAllTracks(); - for ( i = 0 ; i < src.m_FlexAnimationTracks.Size(); i++ ) + for ( i = 0 ; i < src.m_FlexAnimationTracks.Count(); i++ ) { CFlexAnimationTrack *newtrack = new CFlexAnimationTrack( src.m_FlexAnimationTracks[ i ] ); newtrack->SetEvent( this ); @@ -2382,7 +2382,7 @@ void CChoreoEvent::ClearAllRelativeTags( void ) //----------------------------------------------------------------------------- int CChoreoEvent::GetNumRelativeTags( void ) { - return m_RelativeTags.Size(); + return m_RelativeTags.Count(); } //----------------------------------------------------------------------------- @@ -2392,7 +2392,7 @@ int CChoreoEvent::GetNumRelativeTags( void ) //----------------------------------------------------------------------------- CEventRelativeTag *CChoreoEvent::GetRelativeTag( int tagnum ) { - Assert( tagnum >= 0 && tagnum < m_RelativeTags.Size() ); + Assert( tagnum >= 0 && tagnum < m_RelativeTags.Count() ); return &m_RelativeTags[ tagnum ]; } @@ -2413,7 +2413,7 @@ void CChoreoEvent::AddRelativeTag( const char *tagname, float percentage ) //----------------------------------------------------------------------------- void CChoreoEvent::RemoveRelativeTag( const char *tagname ) { - for ( int i = 0; i < m_RelativeTags.Size(); i++ ) + for ( int i = 0; i < m_RelativeTags.Count(); i++ ) { CEventRelativeTag *prt = &m_RelativeTags[ i ]; if ( !prt ) @@ -2434,7 +2434,7 @@ void CChoreoEvent::RemoveRelativeTag( const char *tagname ) //----------------------------------------------------------------------------- CEventRelativeTag * CChoreoEvent::FindRelativeTag( const char *tagname ) { - for ( int i = 0; i < m_RelativeTags.Size(); i++ ) + for ( int i = 0; i < m_RelativeTags.Count(); i++ ) { CEventRelativeTag *prt = &m_RelativeTags[ i ]; if ( !prt ) @@ -2517,7 +2517,7 @@ void CChoreoEvent::ClearAllTimingTags( void ) //----------------------------------------------------------------------------- int CChoreoEvent::GetNumTimingTags( void ) { - return m_TimingTags.Size(); + return m_TimingTags.Count(); } //----------------------------------------------------------------------------- @@ -2527,7 +2527,7 @@ int CChoreoEvent::GetNumTimingTags( void ) //----------------------------------------------------------------------------- CFlexTimingTag *CChoreoEvent::GetTimingTag( int tagnum ) { - Assert( tagnum >= 0 && tagnum < m_TimingTags.Size() ); + Assert( tagnum >= 0 && tagnum < m_TimingTags.Count() ); return &m_TimingTags[ tagnum ]; } @@ -2545,9 +2545,9 @@ void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool loc CFlexTimingTag temp( (CChoreoEvent *)0x1, "", 0.0f, false ); // ugly bubble sort - for ( int i = 0; i < m_TimingTags.Size(); i++ ) + for ( int i = 0; i < m_TimingTags.Count(); i++ ) { - for ( int j = i + 1; j < m_TimingTags.Size(); j++ ) + for ( int j = i + 1; j < m_TimingTags.Count(); j++ ) { CFlexTimingTag *t1 = &m_TimingTags[ i ]; CFlexTimingTag *t2 = &m_TimingTags[ j ]; @@ -2568,7 +2568,7 @@ void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool loc //----------------------------------------------------------------------------- void CChoreoEvent::RemoveTimingTag( const char *tagname ) { - for ( int i = 0; i < m_TimingTags.Size(); i++ ) + for ( int i = 0; i < m_TimingTags.Count(); i++ ) { CFlexTimingTag *ptt = &m_TimingTags[ i ]; if ( !ptt ) @@ -2589,7 +2589,7 @@ void CChoreoEvent::RemoveTimingTag( const char *tagname ) //----------------------------------------------------------------------------- CFlexTimingTag * CChoreoEvent::FindTimingTag( const char *tagname ) { - for ( int i = 0; i < m_TimingTags.Size(); i++ ) + for ( int i = 0; i < m_TimingTags.Count(); i++ ) { CFlexTimingTag *ptt = &m_TimingTags[ i ]; if ( !ptt ) @@ -2626,7 +2626,7 @@ void CChoreoEvent::OnEndTimeChanged( void ) //----------------------------------------------------------------------------- int CChoreoEvent::GetNumFlexAnimationTracks( void ) { - return m_FlexAnimationTracks.Size(); + return m_FlexAnimationTracks.Count(); } //----------------------------------------------------------------------------- @@ -2928,7 +2928,7 @@ void CChoreoEvent::ClearAllAbsoluteTags( AbsTagType type ) //----------------------------------------------------------------------------- int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type ) { - return m_AbsoluteTags[ type ].Size(); + return m_AbsoluteTags[ type ].Count(); } //----------------------------------------------------------------------------- @@ -2939,7 +2939,7 @@ int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type ) //----------------------------------------------------------------------------- CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum ) { - Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Size() ); + Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Count() ); return &m_AbsoluteTags[ type ][ tagnum ]; } @@ -2951,7 +2951,7 @@ CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum ) //----------------------------------------------------------------------------- CEventAbsoluteTag *CChoreoEvent::FindAbsoluteTag( AbsTagType type, const char *tagname ) { - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ ) { CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; if ( !ptag ) @@ -2980,9 +2980,9 @@ void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); // ugly bubble sort - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ ) { - for ( int j = i + 1; j < m_AbsoluteTags[ type ].Size(); j++ ) + for ( int j = i + 1; j < m_AbsoluteTags[ type ].Count(); j++ ) { CEventAbsoluteTag *t1 = &m_AbsoluteTags[ type ][ i ]; CEventAbsoluteTag *t2 = &m_AbsoluteTags[ type ][ j ]; @@ -3004,7 +3004,7 @@ void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t //----------------------------------------------------------------------------- void CChoreoEvent::RemoveAbsoluteTag( AbsTagType type, const char *tagname ) { - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ ) { CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; if ( !ptag ) @@ -3032,7 +3032,7 @@ bool CChoreoEvent::VerifyTagOrder( ) // Sort tags CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); - for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Size(); i++ ) + for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Count(); i++ ) { CEventAbsoluteTag *ptag = &m_AbsoluteTags[ CChoreoEvent::ORIGINAL ][ i ]; if ( !ptag ) @@ -3044,7 +3044,7 @@ bool CChoreoEvent::VerifyTagOrder( ) continue; bInOrder = false; - for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Size(); j++ ) + for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Count(); j++ ) { CEventAbsoluteTag *t2 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ j ]; @@ -3529,9 +3529,9 @@ void CCurveData::Clear( void ) //----------------------------------------------------------------------------- void CCurveData::Resort( ICurveDataAccessor *data ) { - for ( int i = 0; i < m_Ramp.Size(); i++ ) + for ( int i = 0; i < m_Ramp.Count(); i++ ) { - for ( int j = i + 1; j < m_Ramp.Size(); j++ ) + for ( int j = i + 1; j < m_Ramp.Count(); j++ ) { CExpressionSample src = m_Ramp[ i ]; CExpressionSample dest = m_Ramp[ j ]; @@ -3688,7 +3688,7 @@ bool CChoreoEvent::PreventTagOverlap( void ) //----------------------------------------------------------------------------- CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type ) { - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ ) { CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; if ( !ptag ) @@ -3709,7 +3709,7 @@ CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type ) //----------------------------------------------------------------------------- CEventAbsoluteTag *CChoreoEvent::FindExitTag( AbsTagType type ) { - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ ) { CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; if ( !ptag ) diff --git a/game/shared/choreoscene.cpp b/game/shared/choreoscene.cpp index 060b1697..5f50c4eb 100644 --- a/game/shared/choreoscene.cpp +++ b/game/shared/choreoscene.cpp @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -102,7 +102,7 @@ void CChoreoScene::choreoprintf( int level, const char *fmt, ... ) } else { - printf( string ); + printf( "%s", string ); } Msg( "%s", string ); @@ -128,7 +128,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) // Delete existing int i; - for ( i = 0; i < m_Actors.Size(); i++ ) + for ( i = 0; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; Assert( a ); @@ -137,7 +137,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) m_Actors.RemoveAll(); - for ( i = 0; i < m_Events.Size(); i++ ) + for ( i = 0; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; Assert( e ); @@ -146,7 +146,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) m_Events.RemoveAll(); - for ( i = 0 ; i < m_Channels.Size(); i++ ) + for ( i = 0 ; i < m_Channels.Count(); i++ ) { CChoreoChannel *c = m_Channels[ i ]; Assert( c ); @@ -172,7 +172,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) // Now copy the object tree // First copy the global events - for ( i = 0; i < src.m_Events.Size(); i++ ) + for ( i = 0; i < src.m_Events.Count(); i++ ) { CChoreoEvent *event = src.m_Events[ i ]; if ( event->GetActor() == NULL ) @@ -186,7 +186,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) } // Finally, push actors, channels, events onto global stacks - for ( i = 0; i < src.m_Actors.Size(); i++ ) + for ( i = 0; i < src.m_Actors.Count(); i++ ) { CChoreoActor *actor = src.m_Actors[ i ]; CChoreoActor *newActor = AllocActor(); @@ -264,7 +264,7 @@ void CChoreoScene::Init( IChoreoEventCallback *callback ) CChoreoScene::~CChoreoScene( void ) { int i; - for ( i = 0; i < m_Actors.Size(); i++ ) + for ( i = 0; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; Assert( a ); @@ -273,7 +273,7 @@ CChoreoScene::~CChoreoScene( void ) m_Actors.RemoveAll(); - for ( i = 0; i < m_Events.Size(); i++ ) + for ( i = 0; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; Assert( e ); @@ -282,7 +282,7 @@ CChoreoScene::~CChoreoScene( void ) m_Events.RemoveAll(); - for ( i = 0 ; i < m_Channels.Size(); i++ ) + for ( i = 0 ; i < m_Channels.Count(); i++ ) { CChoreoChannel *c = m_Channels[ i ]; Assert( c ); @@ -390,7 +390,7 @@ void CChoreoScene::Print( void ) // Look for events that don't have actor/channel set int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) + for ( i = 0 ; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetActor() ) @@ -399,7 +399,7 @@ void CChoreoScene::Print( void ) PrintEvent( 0, e ); } - for ( i = 0 ; i < m_Actors.Size(); i++ ) + for ( i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -478,7 +478,7 @@ CChoreoActor *CChoreoScene::AllocActor( void ) //----------------------------------------------------------------------------- CChoreoActor *CChoreoScene::FindActor( const char *name ) { - for ( int i = 0; i < m_Actors.Size(); i++ ) + for ( int i = 0; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -497,7 +497,7 @@ CChoreoActor *CChoreoScene::FindActor( const char *name ) //----------------------------------------------------------------------------- int CChoreoScene::GetNumEvents( void ) { - return m_Events.Size(); + return m_Events.Count(); } //----------------------------------------------------------------------------- @@ -507,7 +507,7 @@ int CChoreoScene::GetNumEvents( void ) //----------------------------------------------------------------------------- CChoreoEvent *CChoreoScene::GetEvent( int event ) { - if ( event < 0 || event >= m_Events.Size() ) + if ( event < 0 || event >= m_Events.Count() ) return NULL; return m_Events[ event ]; @@ -519,7 +519,7 @@ CChoreoEvent *CChoreoScene::GetEvent( int event ) //----------------------------------------------------------------------------- int CChoreoScene::GetNumActors( void ) { - return m_Actors.Size(); + return m_Actors.Count(); } //----------------------------------------------------------------------------- @@ -540,7 +540,7 @@ CChoreoActor *CChoreoScene::GetActor( int actor ) //----------------------------------------------------------------------------- int CChoreoScene::GetNumChannels( void ) { - return m_Channels.Size(); + return m_Channels.Count(); } //----------------------------------------------------------------------------- @@ -619,9 +619,9 @@ void CCurveData::Parse( ISceneTokenProcessor *tokenizer, ICurveDataAccessor *dat s->SetCurveType( curveType ); } - if ( samples.Size() >= 1 ) + if ( samples.Count() >= 1 ) { - for ( int i = 0; i < samples.Size(); i++ ) + for ( int i = 0; i < samples.Count(); i++ ) { CExpressionSample sample = samples[ i ]; @@ -840,7 +840,7 @@ void CChoreoScene::ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreo } } - if ( active || samples[ 0 ].Size() >= 1 ) + if ( active || samples[ 0 ].Count() >= 1 ) { // Add it in CFlexAnimationTrack *track = e->AddTrack( flexcontroller ); @@ -853,7 +853,7 @@ void CChoreoScene::ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreo for ( int t = 0; t < ( combo ? 2 : 1 ); t++ ) { - for ( int i = 0; i < samples[ t ].Size(); i++ ) + for ( int i = 0; i < samples[ t ].Count(); i++ ) { CExpressionSample *sample = &samples[ t ][ i ]; @@ -1527,7 +1527,7 @@ void CChoreoScene::InternalDetermineEventTypes() { m_bitvecHasEventOfType.ClearAll(); - for ( int i = 0 ; i < m_Actors.Size(); i++ ) + for ( int i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -1619,7 +1619,7 @@ void CChoreoScene::MarkForSaveAll( bool mark ) int i; // Mark global events - for ( i = 0 ; i < m_Events.Size(); i++ ) + for ( i = 0 ; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetActor() ) @@ -1629,7 +1629,7 @@ void CChoreoScene::MarkForSaveAll( bool mark ) } // Recursively mark everything else - for ( i = 0 ; i < m_Actors.Size(); i++ ) + for ( i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -1652,7 +1652,7 @@ bool CChoreoScene::ExportMarkedToFile( const char *filename ) // Look for events that don't have actor/channel set int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) + for ( i = 0 ; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetActor() ) @@ -1661,7 +1661,7 @@ bool CChoreoScene::ExportMarkedToFile( const char *filename ) FileSaveEvent( buf, 0, e ); } - for ( i = 0 ; i < m_Actors.Size(); i++ ) + for ( i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -1695,7 +1695,7 @@ bool CChoreoScene::SaveToFile( const char *filename ) // Look for events that don't have actor/channel set int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) + for ( i = 0 ; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetActor() ) @@ -1704,7 +1704,7 @@ bool CChoreoScene::SaveToFile( const char *filename ) FileSaveEvent( buf, 0, e ); } - for ( i = 0 ; i < m_Actors.Size(); i++ ) + for ( i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -2219,7 +2219,7 @@ float CChoreoScene::FindAdjustedStartTime( void ) CChoreoEvent *e; - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { e = m_Events[ i ]; @@ -2251,7 +2251,7 @@ float CChoreoScene::FindAdjustedEndTime( void ) CChoreoEvent *e; - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { e = m_Events[ i ]; @@ -2290,7 +2290,7 @@ void CChoreoScene::ResetSimulation( bool forward /*= true*/, float starttime /*= m_PauseEvents.RemoveAll(); // Put all items into the pending queue - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { e = m_Events[ i ]; e->ResetProcessing(); @@ -2317,7 +2317,7 @@ void CChoreoScene::ResetSimulation( bool forward /*= true*/, float starttime /*= // choreoprintf( 0, "Start time %f\n", m_flCurrentTime ); m_flLastActiveTime = 0.0f; - m_nActiveEvents = m_Events.Size(); + m_nActiveEvents = m_Events.Count(); m_flStartTime = starttime; m_flEndTime = endtime; @@ -2332,7 +2332,7 @@ bool CChoreoScene::CheckEventCompletion( void ) bool bAllCompleted = true; // check all items in the active pending queue - for ( int i = 0; i < m_ActiveResumeConditions.Size(); i++ ) + for ( int i = 0; i < m_ActiveResumeConditions.Count(); i++ ) { e = m_ActiveResumeConditions[ i ]; @@ -2378,7 +2378,7 @@ CChoreoEvent *CChoreoScene::FindPauseBetweenTimes( float starttime, float endtim CChoreoEvent *e; // Iterate through all events in the scene - for ( int i = 0; i < m_PauseEvents.Size(); i++ ) + for ( int i = 0; i < m_PauseEvents.Count(); i++ ) { e = m_PauseEvents[ i ]; if ( !e ) @@ -2648,7 +2648,7 @@ void CChoreoScene::Think( float curtime ) // Iterate through all events in the scene int i; - for ( i = 0; i < m_Events.Size(); i++ ) + for ( i = 0; i < m_Events.Count(); i++ ) { e = m_Events[ i ]; if ( !e ) @@ -2803,7 +2803,7 @@ void CChoreoScene::RemoveActor( CChoreoActor *actor ) //----------------------------------------------------------------------------- int CChoreoScene::FindActorIndex( CChoreoActor *actor ) { - for ( int i = 0; i < m_Actors.Size(); i++ ) + for ( int i = 0; i < m_Actors.Count(); i++ ) { if ( actor == m_Actors[ i ] ) { @@ -2882,7 +2882,7 @@ void CChoreoScene::DeleteReferencedObjects( CChoreoEvent *event ) //----------------------------------------------------------------------------- void CChoreoScene::DestroyActor( CChoreoActor *actor ) { - int size = m_Actors.Size(); + int size = m_Actors.Count(); for ( int i = size - 1; i >= 0; i-- ) { CChoreoActor *a = m_Actors[ i ]; @@ -2901,7 +2901,7 @@ void CChoreoScene::DestroyActor( CChoreoActor *actor ) //----------------------------------------------------------------------------- void CChoreoScene::DestroyChannel( CChoreoChannel *channel ) { - int size = m_Channels.Size(); + int size = m_Channels.Count(); for ( int i = size - 1; i >= 0; i-- ) { CChoreoChannel *c = m_Channels[ i ]; @@ -2920,7 +2920,7 @@ void CChoreoScene::DestroyChannel( CChoreoChannel *channel ) //----------------------------------------------------------------------------- void CChoreoScene::DestroyEvent( CChoreoEvent *event ) { - int size = m_Events.Size(); + int size = m_Events.Count(); for ( int i = size - 1; i >= 0; i-- ) { CChoreoEvent *e = m_Events[ i ]; @@ -2998,7 +2998,7 @@ void CChoreoScene::GetSceneTimes( float& start, float& end ) //----------------------------------------------------------------------------- void CChoreoScene::ReconcileTags( void ) { - for ( int i = 0 ; i < m_Actors.Size(); i++ ) + for ( int i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -3055,7 +3055,7 @@ void CChoreoScene::ReconcileTags( void ) //----------------------------------------------------------------------------- CChoreoEvent *CChoreoScene::FindTargetingEvent( const char *wavname, const char *name ) { - for ( int i = 0 ; i < m_Actors.Size(); i++ ) + for ( int i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -3097,7 +3097,7 @@ CChoreoEvent *CChoreoScene::FindTargetingEvent( const char *wavname, const char //----------------------------------------------------------------------------- CEventRelativeTag *CChoreoScene::FindTagByName( const char *wavname, const char *name ) { - for ( int i = 0 ; i < m_Actors.Size(); i++ ) + for ( int i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -3139,16 +3139,16 @@ CEventRelativeTag *CChoreoScene::FindTagByName( const char *wavname, const char //----------------------------------------------------------------------------- void CChoreoScene::ExportEvents( const char *filename, CUtlVector< CChoreoEvent * >& events ) { - if ( events.Size() <= 0 ) + if ( events.Count() <= 0 ) return; // Create a serialization buffer CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - FilePrintf( buf, 0, "// Choreo version 1: <%i> Exported Events\n", events.Size() ); + FilePrintf( buf, 0, "// Choreo version 1: <%i> Exported Events\n", events.Count() ); // Save out the selected events. int i; - for ( i = 0 ; i < events.Size(); i++ ) + for ( i = 0 ; i < events.Count(); i++ ) { CChoreoEvent *e = events[ i ]; if ( !e->GetActor() ) @@ -3275,7 +3275,7 @@ float CChoreoScene::SnapTime( float t ) //----------------------------------------------------------------------------- void CChoreoScene::ReconcileGestureTimes() { - for ( int i = 0 ; i < m_Actors.Size(); i++ ) + for ( int i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -3387,7 +3387,7 @@ bool CChoreoScene::Merge( CChoreoScene *other ) // Look for events that don't have actor/channel set int i; - for ( i = 0 ; i < other->m_Events.Size(); i++ ) + for ( i = 0 ; i < other->m_Events.Count(); i++ ) { CChoreoEvent *e = other->m_Events[ i ]; if ( e->GetActor() ) @@ -3401,7 +3401,7 @@ bool CChoreoScene::Merge( CChoreoScene *other ) ecount++; } - for ( i = 0 ; i < other->m_Actors.Size(); i++ ) + for ( i = 0 ; i < other->m_Actors.Count(); i++ ) { CChoreoActor *a = other->m_Actors[ i ]; @@ -3472,7 +3472,7 @@ bool CChoreoScene::Merge( CChoreoScene *other ) //----------------------------------------------------------------------------- void CChoreoScene::ReconcileCloseCaption() { - for ( int i = 0 ; i < m_Actors.Size(); i++ ) + for ( int i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) @@ -3507,7 +3507,7 @@ void CChoreoScene::SetFileName( char const *fn ) bool CChoreoScene::GetPlayingSoundName( char *pchBuff, int iBuffLength ) { - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetType() == CChoreoEvent::SPEAK && e->IsProcessing() ) @@ -3525,7 +3525,7 @@ bool CChoreoScene::GetPlayingSoundName( char *pchBuff, int iBuffLength ) //----------------------------------------------------------------------------- bool CChoreoScene::HasUnplayedSpeech() { - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetType() == CChoreoEvent::SPEAK ) @@ -3544,7 +3544,7 @@ bool CChoreoScene::HasUnplayedSpeech() //----------------------------------------------------------------------------- bool CChoreoScene::HasFlexAnimation() { - for ( int i = 0; i < m_Events.Size(); i++ ) + for ( int i = 0; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetType() == CChoreoEvent::FLEXANIMATION ) @@ -3631,7 +3631,7 @@ void CChoreoScene::SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersio // Look for events that don't have actor/channel set CUtlVector< CChoreoEvent * > eventList; int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) + for ( i = 0 ; i < m_Events.Count(); i++ ) { CChoreoEvent *e = m_Events[ i ]; if ( e->GetActor() ) @@ -3651,7 +3651,7 @@ void CChoreoScene::SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersio // Now serialize the actors themselves CUtlVector< CChoreoActor * > actorList; - for ( i = 0 ; i < m_Actors.Size(); i++ ) + for ( i = 0 ; i < m_Actors.Count(); i++ ) { CChoreoActor *a = m_Actors[ i ]; if ( !a ) diff --git a/game/shared/gamemovement.h b/game/shared/gamemovement.h index 73678f59..b45118ee 100644 --- a/game/shared/gamemovement.h +++ b/game/shared/gamemovement.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -42,9 +42,9 @@ public: virtual void StartTrackPredictionErrors( CBasePlayer *pPlayer ); virtual void FinishTrackPredictionErrors( CBasePlayer *pPlayer ); virtual void DiffPrint( char const *fmt, ... ); - virtual const Vector& GetPlayerMins( bool ducked ) const; - virtual const Vector& GetPlayerMaxs( bool ducked ) const; - virtual const Vector& GetPlayerViewOffset( bool ducked ) const; + virtual Vector GetPlayerMins( bool ducked ) const; + virtual Vector GetPlayerMaxs( bool ducked ) const; + virtual Vector GetPlayerViewOffset( bool ducked ) const; // For sanity checking getting stuck on CMoveData::SetAbsOrigin virtual void TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ); @@ -105,8 +105,8 @@ protected: // Implement this if you want to know when the player collides during OnPlayerMove virtual void OnTryPlayerMoveCollision( trace_t &tr ) {} - virtual const Vector& GetPlayerMins( void ) const; // uses local player - virtual const Vector& GetPlayerMaxs( void ) const; // uses local player + virtual Vector GetPlayerMins( void ) const; // uses local player + virtual Vector GetPlayerMaxs( void ) const; // uses local player typedef enum { diff --git a/game/shared/gamerules.cpp b/game/shared/gamerules.cpp index 29b47d2f..3817d526 100644 --- a/game/shared/gamerules.cpp +++ b/game/shared/gamerules.cpp @@ -637,7 +637,7 @@ bool CGameRules::ShouldCollide( int collisionGroup0, int collisionGroup1 ) if ( collisionGroup0 > collisionGroup1 ) { // swap so that lowest is always first - V_swap(collisionGroup0,collisionGroup1); + ::V_swap(collisionGroup0,collisionGroup1); } #ifndef HL2MP diff --git a/game/shared/takedamageinfo.cpp b/game/shared/takedamageinfo.cpp index 10eb8c9f..0ab19ccb 100644 --- a/game/shared/takedamageinfo.cpp +++ b/game/shared/takedamageinfo.cpp @@ -62,6 +62,8 @@ void CTakeDamageInfo::Init( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBa m_flDamageBonus = 0.f; m_bForceFriendlyFire = false; m_flDamageForForce = 0.f; + + m_eCritType = kCritType_None; } CTakeDamageInfo::CTakeDamageInfo() @@ -114,6 +116,18 @@ void CTakeDamageInfo::Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBas Init( pInflictor, pAttacker, pWeapon, damageForce, damagePosition, vecReported, flDamage, bitsDamageType, iKillType ); } +void CTakeDamageInfo::SetCritType( ECritType type ) +{ + if ( type == kCritType_None ) + { + m_eCritType = kCritType_None; + } + else if ( type > m_eCritType ) + { + m_eCritType = type; + } +} + //----------------------------------------------------------------------------- // Squirrel the damage value away as BaseDamage, which will later be used to // calculate damage force. diff --git a/game/shared/takedamageinfo.h b/game/shared/takedamageinfo.h index 6e0efa23..43b0c026 100644 --- a/game/shared/takedamageinfo.h +++ b/game/shared/takedamageinfo.h @@ -97,6 +97,14 @@ public: void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, float flDamage, int bitsDamageType, int iKillType = 0 ); void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType = 0, Vector *reportedPosition = NULL ); void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType = 0, Vector *reportedPosition = NULL ); + + enum ECritType + { + kCritType_None, + kCritType_MiniCrit, + kCritType_Crit, + }; + void SetCritType( ECritType type ); void AdjustPlayerDamageInflictedForSkillLevel(); void AdjustPlayerDamageTakenForSkillLevel(); @@ -132,6 +140,8 @@ protected: bool m_bForceFriendlyFire; // Ideally this would be a dmg type, but we can't add more float m_flDamageForForce; + + ECritType m_eCritType; DECLARE_SIMPLE_DATADESC(); }; diff --git a/game/shared/voice_gamemgr.cpp b/game/shared/voice_gamemgr.cpp index 9b12382f..c8f255e7 100644 --- a/game/shared/voice_gamemgr.cpp +++ b/game/shared/voice_gamemgr.cpp @@ -162,7 +162,7 @@ bool CVoiceGameMgr::ClientCommand( CBasePlayer *pPlayer, const CCommand &args ) { for(int i=1; i < args.ArgC(); i++) { - unsigned long mask = 0; + uint32_t mask = 0; sscanf( args[i], "%p", (void**)&mask); if( i <= VOICE_MAX_PLAYERS_DW ) diff --git a/game/shared/voice_status.cpp b/game/shared/voice_status.cpp index 5b27ce37..848458a0 100644 --- a/game/shared/voice_status.cpp +++ b/game/shared/voice_status.cpp @@ -349,11 +349,11 @@ void CVoiceStatus::UpdateServerState(bool bForce) Q_strncpy(str,"vban",sizeof(str)); bool bChange = false; - for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + for(uint32_t dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) { - unsigned long serverBanMask = 0; - unsigned long banMask = 0; - for(unsigned long i=0; i < 32; i++) + uint32_t serverBanMask = 0; + uint32_t banMask = 0; + for(uint32_t i=0; i < 32; i++) { int playerIndex = ( dw * 32 + i ); if ( playerIndex >= MAX_PLAYERS ) @@ -408,11 +408,11 @@ void CVoiceStatus::UpdateServerState(bool bForce) void CVoiceStatus::HandleVoiceMaskMsg(bf_read &msg) { - unsigned long dw; + uint32_t dw; for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) { - m_AudiblePlayers.SetDWord(dw, (unsigned long)msg.ReadLong()); - m_ServerBannedPlayers.SetDWord(dw, (unsigned long)msg.ReadLong()); + m_AudiblePlayers.SetDWord(dw, (uint32_t)msg.ReadLong()); + m_ServerBannedPlayers.SetDWord(dw, (uint32_t)msg.ReadLong()); if( voice_clientdebug.GetInt()) { diff --git a/lib/linux/libtier0_srv.so b/lib/linux/libtier0_srv.so index 8bcea085..dbd5a36b 100644 Binary files a/lib/linux/libtier0_srv.so and b/lib/linux/libtier0_srv.so differ diff --git a/lib/linux/libvstdlib_srv.so b/lib/linux/libvstdlib_srv.so index cb0fddae..6cececb0 100644 Binary files a/lib/linux/libvstdlib_srv.so and b/lib/linux/libvstdlib_srv.so differ diff --git a/lib/linux/mathlib_i486.a b/lib/linux/mathlib_i486.a index cbe62179..8f421f5c 100644 Binary files a/lib/linux/mathlib_i486.a and b/lib/linux/mathlib_i486.a differ diff --git a/lib/linux/tier1_i486.a b/lib/linux/tier1_i486.a index e64b124a..8e2f0b44 100644 Binary files a/lib/linux/tier1_i486.a and b/lib/linux/tier1_i486.a differ diff --git a/lib/linux64/libtier0_srv.so b/lib/linux64/libtier0_srv.so new file mode 100644 index 00000000..4be0797f Binary files /dev/null and b/lib/linux64/libtier0_srv.so differ diff --git a/lib/linux64/libvstdlib_srv.so b/lib/linux64/libvstdlib_srv.so new file mode 100644 index 00000000..ec1b75d5 Binary files /dev/null and b/lib/linux64/libvstdlib_srv.so differ diff --git a/lib/linux64/mathlib.a b/lib/linux64/mathlib.a new file mode 100644 index 00000000..3d257e88 Binary files /dev/null and b/lib/linux64/mathlib.a differ diff --git a/lib/linux64/tier1.a b/lib/linux64/tier1.a new file mode 100644 index 00000000..7b71ca3c Binary files /dev/null and b/lib/linux64/tier1.a differ diff --git a/lib/mac/tier1_i486.a b/lib/mac/tier1_i486.a index f4511ee8..45340ccc 100644 Binary files a/lib/mac/tier1_i486.a and b/lib/mac/tier1_i486.a differ diff --git a/lib/public/mathlib.lib b/lib/public/mathlib.lib index 453b4aff..1f8c080d 100644 Binary files a/lib/public/mathlib.lib and b/lib/public/mathlib.lib differ diff --git a/lib/public/tier0.lib b/lib/public/tier0.lib index c9801912..40f3b178 100644 Binary files a/lib/public/tier0.lib and b/lib/public/tier0.lib differ diff --git a/lib/public/tier1.lib b/lib/public/tier1.lib index 1f875845..9c67b9ed 100644 Binary files a/lib/public/tier1.lib and b/lib/public/tier1.lib differ diff --git a/lib/public/win64/mathlib.lib b/lib/public/win64/mathlib.lib new file mode 100644 index 00000000..a0243027 Binary files /dev/null and b/lib/public/win64/mathlib.lib differ diff --git a/lib/public/win64/tier0.lib b/lib/public/win64/tier0.lib new file mode 100644 index 00000000..2195d29e Binary files /dev/null and b/lib/public/win64/tier0.lib differ diff --git a/lib/public/win64/tier1.lib b/lib/public/win64/tier1.lib new file mode 100644 index 00000000..9adecee4 Binary files /dev/null and b/lib/public/win64/tier1.lib differ diff --git a/lib/public/win64/vstdlib.lib b/lib/public/win64/vstdlib.lib new file mode 100644 index 00000000..3cce3711 Binary files /dev/null and b/lib/public/win64/vstdlib.lib differ diff --git a/linux_sdk/Makefile b/linux_sdk/Makefile deleted file mode 100644 index ac5b553d..00000000 --- a/linux_sdk/Makefile +++ /dev/null @@ -1,175 +0,0 @@ -# -# SDK Makefile for x86 Linux -# -# - -OS := $(shell uname -s) - -############################################################################# -# Developer configurable items -############################################################################# - -# the name of the mod binary (_i486.so is appended to the end) -NAME = server - -# the location of the vcproj that builds the mod -MOD_PROJ = ../game/server/server_scratch-2005.vcproj -# the name of the mod configuration (typically _) -MOD_CONFIG = Server\(SDK\)_ReleaseWin32 - -# the directory the base binaries (tier0_i486.so, etc) are located -# this should point to your orange box subfolder of where you have srcds installed. -SRCDS_DIR = ~/srcds/orangebox - -# the path to your mods directory -# set this so that 'make install' or 'make installrelease' will copy your binary over automatically. -GAME_DIR = $(SRCDS_DIR)/scratchmod - -# compiler options (gcc 3.4.1 or above is required - 4.1.2+ recommended) -ifeq "$(OS)" "Darwin" -CC = /usr/bin/clang -CPLUS = /usr/bin/clang++ -CLINK = /usr/bin/clang -CPP_LIB = -else -CC = /usr/bin/gcc -CPLUS = /usr/bin/g++ -CLINK = /usr/bin/gcc -CPP_LIB = $(SRCDS_DIR)/bin/libstdc++.so.6 $(SRCDS_DIR)/bin/libgcc_s.so.1 -endif - -# put any compiler flags you want passed here -USER_CFLAGS = - -# link flags for your mod, make sure to include any special libraries here -LDFLAGS = "-lm -ldl $(LIB_DIR)/particles_i486.a $(LIB_DIR)/dmxloader_i486.a $(LIB_DIR)/mathlib_i486.a tier0_i486.so vstdlib_i486.so $(LIB_DIR)/tier1_i486.a $(LIB_DIR)/tier2_i486.a $(LIB_DIR)/tier3_i486.a $(LIB_DIR)/choreoobjects_i486.a steam_api_i486.so" - -# XERCES 2.6.0 or above ( http://xml.apache.org/xerces-c/ ) is used by the vcproj to makefile converter -# it must be installed before being able to run this makefile -# if you have xerces installed already you should be able to use the two lines below -XERCES_INC_DIR = /usr/include -XERCES_LIB_DIR = /usr/lib - -# Change this to true if you want to build debug binaries for everything -# The only exception is the mod/game as MOD_CONFIG determines if it's a debug build or not -DEBUG = false - -############################################################################# -# Things below here shouldn't need to be altered -############################################################################# -MAKE = make -AR = "ar rvs" - -# the dir we want to put binaries we build into -BUILD_DIR = . -# the place to put object files -BUILD_OBJ_DIR = $(BUILD_DIR)/obj - -# the location of the source code -SRC_DIR = .. - -# the location of the static libraries -ifeq "$(OS)" "Darwin" -LIB_DIR = $(SRC_DIR)/lib/mac -else -LIB_DIR = $(SRC_DIR)/lib/linux -endif - -# the CPU target for the build, must be i486 for now -ARCH = i486 -ARCH_CFLAGS = -mtune=i686 -march=pentium3 -mmmx -m32 - -ifeq "$(OS)" "Darwin" -DEFINES = -D_OSX -DOSX -SHLIBEXT = dylib -SHLIBLDFLAGS = -dynamiclib -mmacosx-version-min=10.5 -SHLIBSUFFIX = -else -DEFINES = -D_LINUX -DLINUX -SHLIBEXT = so -SHLIBLDFLAGS = -shared -Wl,-Map,$@_map.txt -Wl -SHLIBSUFFIX = _srv -endif - -DEFINES +=-DVPROF_LEVEL=1 -DSWDS -D_finite=finite -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ - -Dstrnicmp=strncasecmp -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -UNDEF = -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE - -BASE_CFLAGS = -fno-strict-aliasing -Wall -Wsign-compare -Werror -Wno-conversion -Wno-overloaded-virtual -Wno-non-virtual-dtor -Wno-invalid-offsetof \ - -Wno-delete-non-virtual-dtor -SHLIBCFLAGS = -fPIC - -# Flags passed to the c compiler -CFLAGS = $(DEFINES) $(ARCH_CFLAGS) -O3 $(BASE_CFLAGS) -ifdef USER_CFLAGS - CFLAGS += $(USER_CFLAGS) -endif -CFLAGS += $(UNDEF) - -# Debug flags -DBG_DEFINES = "-D_DEBUG -DDEBUG" -DBG_CFLAGS = "$(DEFINES) $(ARCH_CFLAGS) -g -ggdb $(BASE_CFLAGS) $(UNDEF)" - -# define list passed to make for the sub makefile -BASE_DEFINES = CC=$(CC) AR=$(AR) CPLUS=$(CPLUS) CPP_LIB=$(CPP_LIB) DEBUG=$(DEBUG) \ - BUILD_DIR=$(BUILD_DIR) BUILD_OBJ_DIR=$(BUILD_OBJ_DIR) SRC_DIR=$(SRC_DIR) \ - LIB_DIR=$(LIB_DIR) SHLIBLDFLAGS="$(SHLIBLDFLAGS)" SHLIBEXT=$(SHLIBEXT) SHLIBSUFFIX=$(SHLIBSUFFIX) \ - CLINK=$(CLINK) CFLAGS="$(CFLAGS)" DBG_CFLAGS=$(DBG_CFLAGS) LDFLAGS=$(LDFLAGS) \ - DEFINES="$(DEFINES)" DBG_DEFINES=$(DBG_DEFINES) \ - ARCH=$(ARCH) SRCDS_DIR=$(SRCDS_DIR) MOD_CONFIG=$(MOD_CONFIG) NAME=$(NAME) \ - XERCES_INC_DIR=$(XERCES_INC_DIR) XERCES_LIB_DIR=$(XERCES_LIB_DIR) - -# Project Makefile -MAKE_SERVER = Makefile.server -MAKE_VCPM = Makefile.vcpm -MAKE_PLUGIN = Makefile.plugin -MAKE_TIER1 = Makefile.tier1 -MAKE_MATH = Makefile.mathlib -MAKE_CHOREO = Makefile.choreo - -all: check vcpm mod - -check: - if [ -z "$(CC)" ]; then echo "Compiler not defined."; exit; fi - if [ ! -d $(BUILD_DIR) ];then mkdir -p $(BUILD_DIR);fi - cd $(BUILD_DIR) - if [ ! -e "$(LIB_DIR)/tier1_i486.a" ]; then $(MAKE) tier1;fi - if [ ! -e "$(LIB_DIR)/mathlib_i486.a" ]; then $(MAKE) mathlib;fi - if [ ! -e "$(LIB_DIR)/choreoobjects_i486.a" ]; then $(MAKE) choreo;fi - if [ ! -f "libtier0$(SHLIBSUFFIX).$(SHLIBEXT)" ]; then ln -fs $(LIB_DIR)/libtier0$(SHLIBSUFFIX).$(SHLIBEXT) .; fi - if [ ! -f "libvstdlib$(SHLIBSUFFIX).$(SHLIBEXT)" ]; then ln -fs $(LIB_DIR)/libvstdlib$(SHLIBSUFFIX).$(SHLIBEXT) .; fi - if [ ! -f "libsteam_api.$(SHLIBEXT)" ]; then ln -fs $(LIB_DIR)/libsteam_api.$(SHLIBEXT) .; fi - -vcpm: check - if [ ! -e "vcpm" ]; then $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES);fi - -mod: check vcpm - ./vcpm $(MOD_PROJ) - $(MAKE) -f $(MAKE_SERVER) $(BASE_DEFINES) - -plugin: check - $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) - -tier1: - $(MAKE) -f $(MAKE_TIER1) $(BASE_DEFINES) - -mathlib: - $(MAKE) -f $(MAKE_MATH) $(BASE_DEFINES) - -choreo: - $(MAKE) -f $(MAKE_CHOREO) $(BASE_DEFINES) - -install: - cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(GAME_DIR)/bin/$(NAME)_$(ARCH).$(SHLIBEXT) - -installrelease: - cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(GAME_DIR)/bin/$(NAME)_$(ARCH).$(SHLIBEXT) - strip $(GAME_DIR)/bin/$(NAME)_$(ARCH).$(SHLIBEXT) - -clean: - $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_SERVER) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_TIER1) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_MATH) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_CHOREO) $(BASE_DEFINES) clean diff --git a/linux_sdk/Makefile.choreo b/linux_sdk/Makefile.choreo deleted file mode 100644 index 4182e60a..00000000 --- a/linux_sdk/Makefile.choreo +++ /dev/null @@ -1,57 +0,0 @@ -# -# Choreoobjects Static Library Makefile -# - -override NAME = choreoobjects - -LIB_SRC_DIR = $(SRC_DIR)/game/shared -PUBLIC_SRC_DIR = $(SRC_DIR)/public -TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1 -UTIL_COMMON_SRC_DIR = $(SRC_DIR)/utils/common - -LIB_OBJ_DIR = $(BUILD_OBJ_DIR)/$(NAME)_$(ARCH) - -# Extension of linux static library -override SHLIBEXT = a - -INCLUDEDIRS = -I$(LIB_SRC_DIR) -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(UTIL_COMMON_SRC_DIR) -D_LIB -DCHOREOOBJECTS_STATIC_LIB - -DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH) - -ifeq "$(DEBUG)" "true" - DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS) -else - DO_CC += -DNDEBUG $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -##################################################################### - -LIB_OBJS= \ - $(LIB_OBJ_DIR)/choreoactor.o \ - $(LIB_OBJ_DIR)/choreochannel.o \ - $(LIB_OBJ_DIR)/choreoevent.o \ - $(LIB_OBJ_DIR)/choreoscene.o \ - $(LIB_OBJ_DIR)/sceneimage.o \ - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(LIB_OBJ_DIR) - -$(NAME)_$(ARCH).$(SHLIBEXT): $(LIB_OBJS) - $(AR) $(LIB_DIR)/$@ $(LIB_OBJS) - -$(LIB_OBJ_DIR)/%.o: $(LIB_SRC_DIR)/%.cpp - $(DO_CC) - -install: - cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(LIB_DIR)/$(NAME)_$(ARCH).$(SHLIBEXT) - -clean: - -rm -rf $(LIB_OBJ_DIR) - - diff --git a/linux_sdk/Makefile.mathlib b/linux_sdk/Makefile.mathlib deleted file mode 100644 index 638c4df6..00000000 --- a/linux_sdk/Makefile.mathlib +++ /dev/null @@ -1,70 +0,0 @@ -# -# Mathlin Static Library Makefile -# - -override NAME = mathlib - -LIB_SRC_DIR = $(SRC_DIR)/$(NAME) -PUBLIC_SRC_DIR = $(SRC_DIR)/public -TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1 -MATHLIB_PUBLIC_SRC_DIR = $(SRC_DIR)/public/mathlib - -LIB_OBJ_DIR = $(BUILD_OBJ_DIR)/$(NAME)_$(ARCH) - -# Extension of linux static library -override SHLIBEXT = a - -INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(MATHLIB_PUBLIC_SRC_DIR) -D_LIB - -DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH) - -ifeq "$(DEBUG)" "true" - DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS) -else - DO_CC += -DNDEBUG $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -##################################################################### - -LIB_OBJS= \ - $(LIB_OBJ_DIR)/anorms.o \ - $(LIB_OBJ_DIR)/bumpvects.o \ - $(LIB_OBJ_DIR)/color_conversion.o \ - $(LIB_OBJ_DIR)/halton.o \ - $(LIB_OBJ_DIR)/IceKey.o \ - $(LIB_OBJ_DIR)/imagequant.o \ - $(LIB_OBJ_DIR)/lightdesc.o \ - $(LIB_OBJ_DIR)/mathlib_base.o \ - $(LIB_OBJ_DIR)/polyhedron.o \ - $(LIB_OBJ_DIR)/powsse.o \ - $(LIB_OBJ_DIR)/quantize.o \ - $(LIB_OBJ_DIR)/randsse.o \ - $(LIB_OBJ_DIR)/simdvectormatrix.o \ - $(LIB_OBJ_DIR)/sparse_convolution_noise.o \ - $(LIB_OBJ_DIR)/sse.o \ - $(LIB_OBJ_DIR)/sseconst.o \ - $(LIB_OBJ_DIR)/ssenoise.o \ - $(LIB_OBJ_DIR)/vector.o \ - $(LIB_OBJ_DIR)/vmatrix.o \ - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(LIB_OBJ_DIR) - -$(NAME)_$(ARCH).$(SHLIBEXT): $(LIB_OBJS) - $(AR) $(LIB_DIR)/$@ $(LIB_OBJS) - -$(LIB_OBJ_DIR)/%.o: $(LIB_SRC_DIR)/%.cpp - $(DO_CC) - -install: - cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(LIB_DIR)/$(NAME)_$(ARCH).$(SHLIBEXT) - -clean: - -rm -rf $(LIB_OBJ_DIR) - diff --git a/linux_sdk/Makefile.plugin b/linux_sdk/Makefile.plugin deleted file mode 100644 index 9586b03c..00000000 --- a/linux_sdk/Makefile.plugin +++ /dev/null @@ -1,57 +0,0 @@ -# -# Sample server plugin for SRC engine -# -# October 2004, alfred@valvesoftware.com -# - -override NAME = serverplugin_empty - -PLUGIN_SRC_DIR = $(SRC_DIR)/utils/serverplugin_sample -PUBLIC_SRC_DIR = $(SRC_DIR)/public -TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1 - -PLUGIN_OBJ_DIR = $(BUILD_OBJ_DIR)/serverplugin_empty_$(ARCH) -TIER0_OBJ_DIR = $(PLUGIN_OBJ_DIR)/tier0 - -INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -LDFLAGS_PLG = -lm -ldl tier0_i486.so vstdlib_i486.so $(LIB_DIR)/mathlib_i486.a $(LIB_DIR)/tier1_i486.a $(LIB_DIR)/tier2_i486.a - -DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH) - -ifeq "$(DEBUG)" "true" - DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS) -else - DO_CC += -DNDEBUG $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -##################################################################### - -PLUGIN_OBJS = \ - $(PLUGIN_OBJ_DIR)/serverplugin_bot.o \ - $(PLUGIN_OBJ_DIR)/serverplugin_empty.o \ - -TIER0_OBJS = \ - $(TIER0_OBJ_DIR)/memoverride.o \ - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(PLUGIN_OBJ_DIR) - -mkdir -p $(TIER0_OBJ_DIR) - -$(NAME)_$(ARCH).$(SHLIBEXT): $(PLUGIN_OBJS) $(TIER0_OBJS) - $(CLINK) -o $(BUILD_DIR)/$@ -m32 $(SHLIBLDFLAGS) $(PLUGIN_OBJS) $(TIER0_OBJS) $(PUBLIC_OBJS) $(CPP_LIB) $(LDFLAGS_PLG) $(CPP_LIB) - -$(PLUGIN_OBJ_DIR)/%.o: $(PLUGIN_SRC_DIR)/%.cpp - $(DO_CC) - -$(TIER0_OBJ_DIR)/%.o: $(TIER0_PUBLIC_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(PLUGIN_OBJ_DIR) - -rm -f $(NAME)_$(ARCH).$(SHLIBEXT) diff --git a/linux_sdk/Makefile.server b/linux_sdk/Makefile.server deleted file mode 100644 index fe613f38..00000000 --- a/linux_sdk/Makefile.server +++ /dev/null @@ -1,28 +0,0 @@ -# -# wrapper Makefile for auto-generated make files -# -# - -############################################################################# -# PROJECT MAKEFILES -############################################################################# -MAKE_FILE = Makefile.$(MOD_CONFIG) --include $(MAKE_FILE) - -############################################################################# -# The compiler command line for each src code file to compile -############################################################################# -DO_CC = $(CPLUS) $(INCLUDES) -DARCH=$(ARCH) - -ifeq (_DEBUG,$(findstring _DEBUG,$(CFLAGS))) - DO_CC += $(DEFINES) $(DBG_CFLAGS) -else - DO_CC += $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -clean: - rm -rf obj/$(NAME)_$(ARCH) - rm -f $(NAME)_$(ARCH).$(SHLIBEXT) - diff --git a/linux_sdk/Makefile.tier1 b/linux_sdk/Makefile.tier1 deleted file mode 100644 index 20c0c818..00000000 --- a/linux_sdk/Makefile.tier1 +++ /dev/null @@ -1,77 +0,0 @@ -# -# Tier1 Static Library Makefile -# - -override NAME = tier1 - -LIB_SRC_DIR = $(SRC_DIR)/$(NAME) -PUBLIC_SRC_DIR = $(SRC_DIR)/public -TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1 - -LIB_OBJ_DIR=$(BUILD_OBJ_DIR)/$(NAME)_$(ARCH) - -# Extension of linux static library -override SHLIBEXT = a - -INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -D_LIB -DTIER1_STATIC_LIB - -DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH) - -ifeq "$(DEBUG)" "true" - DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS) -else - DO_CC += -DNDEBUG $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -##################################################################### - -LIB_OBJS= \ - $(LIB_OBJ_DIR)/bitbuf.o \ - $(LIB_OBJ_DIR)/byteswap.o \ - $(LIB_OBJ_DIR)/characterset.o \ - $(LIB_OBJ_DIR)/checksum_crc.o \ - $(LIB_OBJ_DIR)/checksum_md5.o \ - $(LIB_OBJ_DIR)/commandbuffer.o \ - $(LIB_OBJ_DIR)/convar.o \ - $(LIB_OBJ_DIR)/datamanager.o \ - $(LIB_OBJ_DIR)/diff.o \ - $(LIB_OBJ_DIR)/generichash.o \ - $(LIB_OBJ_DIR)/interface.o \ - $(LIB_OBJ_DIR)/KeyValues.o \ - $(LIB_OBJ_DIR)/mempool.o \ - $(LIB_OBJ_DIR)/NetAdr.o \ - $(LIB_OBJ_DIR)/newbitbuf.o \ - $(LIB_OBJ_DIR)/processor_detect.o \ - $(LIB_OBJ_DIR)/rangecheckedvar.o \ - $(LIB_OBJ_DIR)/stringpool.o \ - $(LIB_OBJ_DIR)/strtools.o \ - $(LIB_OBJ_DIR)/tier1.o \ - $(LIB_OBJ_DIR)/tokenreader.o \ - $(LIB_OBJ_DIR)/undiff.o \ - $(LIB_OBJ_DIR)/uniqueid.o \ - $(LIB_OBJ_DIR)/utlbuffer.o \ - $(LIB_OBJ_DIR)/utlbufferutil.o \ - $(LIB_OBJ_DIR)/utlstring.o \ - $(LIB_OBJ_DIR)/utlsymbol.o \ - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(LIB_OBJ_DIR) - -$(NAME)_$(ARCH).$(SHLIBEXT): $(LIB_OBJS) - $(AR) $(LIB_DIR)/$@ $(LIB_OBJS) - -$(LIB_OBJ_DIR)/%.o: $(LIB_SRC_DIR)/%.cpp - $(DO_CC) - -install: - cp -f $(NAME)_$(ARCH).$(SHLIBEXT) $(LIB_DIR)/$(NAME)_$(ARCH).$(SHLIBEXT) - -clean: - -rm -rf $(LIB_OBJ_DIR) - diff --git a/linux_sdk/Makefile.vcpm b/linux_sdk/Makefile.vcpm deleted file mode 100644 index eb8ecff9..00000000 --- a/linux_sdk/Makefile.vcpm +++ /dev/null @@ -1,50 +0,0 @@ -# -# VCProject file to Makefile converter -# -# November 2004, alfred@valvesoftware.com -# - -VCPM_SRC_DIR = $(SRC_DIR)/utils/vprojtomake -PUBLIC_SRC_DIR = $(SRC_DIR)/public -TIER0_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR = $(SRC_DIR)/public/tier1 -UTIL_COMMON_SRC_DIR = $(SRC_DIR)/utils/common - -VCPM_OBJ_DIR = $(BUILD_OBJ_DIR)/vcpm - -INCLUDEDIRS = -I$(PUBLIC_SRC_DIR) -I$(XERCES_INC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(UTIL_COMMON_SRC_DIR) -LDFLAGS_VC = -lm -ldl -L$(XERCES_LIB_DIR) -lxerces-c tier0_i486.so vstdlib_i486.so $(LIB_DIR)/tier1_i486.a - -DO_CC = $(CPLUS) $(INCLUDEDIRS) -DARCH=$(ARCH) - -ifeq "$(DEBUG)" "true" - DO_CC += $(DBG_DEFINES) $(DBG_CFLAGS) -else - DO_CC += -DNDEBUG $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -##################################################################### - -VCPM_OBJS = \ - $(VCPM_OBJ_DIR)/makefilecreator.o \ - $(VCPM_OBJ_DIR)/vprojtomake.o \ - $(VCPM_OBJ_DIR)/vcprojconvert.o \ - -all: dirs vcpm - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(VCPM_OBJ_DIR) - -vcpm: $(VCPM_OBJS) - $(CLINK) -m32 -o $(BUILD_DIR)/$@ $(VCPM_OBJS) $(CPP_LIB) $(LDFLAGS_VC) - -$(VCPM_OBJ_DIR)/%.o: $(VCPM_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(VCPM_OBJ_DIR) - -rm -f vcpm - diff --git a/mathlib/3dnow.cpp b/mathlib/3dnow.cpp new file mode 100644 index 00000000..71657044 --- /dev/null +++ b/mathlib/3dnow.cpp @@ -0,0 +1,197 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: 3DNow Math primitives. +// +//=====================================================================================// + +#include +#include // Needed for FLT_EPSILON +#include "basetypes.h" +#include +#include "tier0/dbg.h" +#include "mathlib/mathlib.h" +#include "mathlib/amd3dx.h" +#include "mathlib/vector.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#if !defined(COMPILER_MSVC64) && !defined(LINUX) +// Implement for 64-bit Windows if needed. +// Clang hits "fatal error: error in backend:" and other errors when trying +// to compile the inline assembly below. 3DNow support is highly unlikely to +// be useful/used, so it's not worth spending time on fixing. + +#pragma warning(disable:4244) // "conversion from 'const int' to 'float', possible loss of data" +#pragma warning(disable:4730) // "mixing _m64 and floating point expressions may result in incorrect code" + +//----------------------------------------------------------------------------- +// 3D Now Implementations of optimized routines: +//----------------------------------------------------------------------------- +float _3DNow_Sqrt(float x) +{ + Assert( s_bMathlibInitialized ); + float root = 0.f; +#ifdef _WIN32 + _asm + { + femms + movd mm0, x + PFRSQRT (mm1,mm0) + punpckldq mm0, mm0 + PFMUL (mm0, mm1) + movd root, mm0 + femms + } +#elif LINUX + __asm __volatile__( "femms" ); + __asm __volatile__ + ( + "pfrsqrt %y0, %y1 \n\t" + "punpckldq %y1, %y1 \n\t" + "pfmul %y1, %y0 \n\t" + : "=y" (root), "=y" (x) + :"0" (x) + ); + __asm __volatile__( "femms" ); +#else +#error +#endif + + return root; +} + +// NJS FIXME: Need to test Recripricol squareroot performance and accuraccy +// on AMD's before using the specialized instruction. +float _3DNow_RSqrt(float x) +{ + Assert( s_bMathlibInitialized ); + + return 1.f / _3DNow_Sqrt(x); +} + + +float FASTCALL _3DNow_VectorNormalize (Vector& vec) +{ + Assert( s_bMathlibInitialized ); + float *v = &vec[0]; + float radius = 0.f; + + if ( v[0] || v[1] || v[2] ) + { +#ifdef _WIN32 + _asm + { + mov eax, v + femms + movq mm0, QWORD PTR [eax] + movd mm1, DWORD PTR [eax+8] + movq mm2, mm0 + movq mm3, mm1 + PFMUL (mm0, mm0) + PFMUL (mm1, mm1) + PFACC (mm0, mm0) + PFADD (mm1, mm0) + PFRSQRT (mm0, mm1) + punpckldq mm1, mm1 + PFMUL (mm1, mm0) + PFMUL (mm2, mm0) + PFMUL (mm3, mm0) + movq QWORD PTR [eax], mm2 + movd DWORD PTR [eax+8], mm3 + movd radius, mm1 + femms + } +#elif LINUX + long long a,c; + int b,d; + memcpy(&a,&vec[0],sizeof(a)); + memcpy(&b,&vec[2],sizeof(b)); + memcpy(&c,&vec[0],sizeof(c)); + memcpy(&d,&vec[2],sizeof(d)); + + __asm __volatile__( "femms" ); + __asm __volatile__ + ( + "pfmul %y3, %y3\n\t" + "pfmul %y0, %y0 \n\t" + "pfacc %y3, %y3 \n\t" + "pfadd %y3, %y0 \n\t" + "pfrsqrt %y0, %y3 \n\t" + "punpckldq %y0, %y0 \n\t" + "pfmul %y3, %y0 \n\t" + "pfmul %y3, %y2 \n\t" + "pfmul %y3, %y1 \n\t" + : "=y" (radius), "=y" (c), "=y" (d) + : "y" (a), "0" (b), "1" (c), "2" (d) + ); + memcpy(&vec[0],&c,sizeof(c)); + memcpy(&vec[2],&d,sizeof(d)); + __asm __volatile__( "femms" ); + +#else +#error +#endif + } + return radius; +} + + +void FASTCALL _3DNow_VectorNormalizeFast (Vector& vec) +{ + _3DNow_VectorNormalize( vec ); +} + + +// JAY: This complains with the latest processor pack +#pragma warning(disable: 4730) + +float _3DNow_InvRSquared(const float* v) +{ + Assert( s_bMathlibInitialized ); + float r2 = 1.f; +#ifdef _WIN32 + _asm { // AMD 3DNow only routine + mov eax, v + femms + movq mm0, QWORD PTR [eax] + movd mm1, DWORD PTR [eax+8] + movd mm2, [r2] + PFMUL (mm0, mm0) + PFMUL (mm1, mm1) + PFACC (mm0, mm0) + PFADD (mm1, mm0) + PFMAX (mm1, mm2) + PFRCP (mm0, mm1) + movd [r2], mm0 + femms + } +#elif LINUX + long long a,c; + int b; + memcpy(&a,&v[0],sizeof(a)); + memcpy(&b,&v[2],sizeof(b)); + memcpy(&c,&v[0],sizeof(c)); + + __asm __volatile__( "femms" ); + __asm __volatile__ + ( + "PFMUL %y2, %y2 \n\t" + "PFMUL %y3, %y3 \n\t" + "PFACC %y2, %y2 \n\t" + "PFADD %y2, %y3 \n\t" + "PFMAX %y3, %y4 \n\t" + "PFRCP %y3, %y2 \n\t" + "movq %y2, %y0 \n\t" + : "=y" (r2) + : "0" (r2), "y" (a), "y" (b), "y" (c) + ); + __asm __volatile__( "femms" ); +#else +#error +#endif + + return r2; +} + +#endif // COMPILER_MSVC64 diff --git a/mathlib/3dnow.h b/mathlib/3dnow.h new file mode 100644 index 00000000..47659c1f --- /dev/null +++ b/mathlib/3dnow.h @@ -0,0 +1,16 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=====================================================================================// + +#ifndef _3DNOW_H +#define _3DNOW_H + +float _3DNow_Sqrt(float x); +float _3DNow_RSqrt(float x); +float FASTCALL _3DNow_VectorNormalize (Vector& vec); +void FASTCALL _3DNow_VectorNormalizeFast (Vector& vec); +float _3DNow_InvRSquared(const float* v); + +#endif // _3DNOW_H diff --git a/mathlib/AMBuilder b/mathlib/AMBuilder new file mode 100644 index 00000000..385e4f41 --- /dev/null +++ b/mathlib/AMBuilder @@ -0,0 +1,48 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys + +def AddSourceFilesFromDir(path, files): + list = [] + for file in files: + list.append(os.path.join(path, file)) + return list + +builder.SetBuildFolder('/') + +project = builder.StaticLibraryProject('mathlib') +project.sources = [ + '3dnow.cpp', + 'almostequal.cpp', + 'anorms.cpp', + 'bumpvects.cpp', + 'color_conversion.cpp', + 'halton.cpp', + 'IceKey.cpp', + 'imagequant.cpp', + 'lightdesc.cpp', + 'mathlib_base.cpp', + 'polyhedron.cpp', + 'powsse.cpp', + 'quantize.cpp', + 'randsse.cpp', + 'simdvectormatrix.cpp', + 'sparse_convolution_noise.cpp', + 'spherical.cpp', + 'sse.cpp', + 'sseconst.cpp', + 'ssenoise.cpp', + 'vector.cpp', + 'vmatrix.cpp', +] + +for cxx in HL2SDK.targets: + binary = HL2SDK.ConfigureLibrary(project, cxx, builder) + compiler = binary.compiler + + compiler.cxxincludes += [ + os.path.join(builder.currentSourcePath, '..', 'public'), + os.path.join(builder.currentSourcePath, '..', 'public', 'tier0'), + os.path.join(builder.currentSourcePath, '..', 'public', 'mathlib') + ] + +HL2SDK.libs += builder.Add(project) \ No newline at end of file diff --git a/mathlib/IceKey.cpp b/mathlib/IceKey.cpp index 3d1566a8..4470e4c7 100644 --- a/mathlib/IceKey.cpp +++ b/mathlib/IceKey.cpp @@ -5,6 +5,9 @@ #if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) #include "mathlib/IceKey.H" +#include + +#include "tier0/memdbgon.h" #ifdef _MSC_VER #pragma warning(disable: 4244) @@ -13,12 +16,12 @@ /* Structure of a single round subkey */ class IceSubkey { public: - unsigned long val[3]; + uint32_t val[3]; }; /* The S-boxes */ -static unsigned long ice_sbox[4][1024]; +static uint32_t ice_sbox[4][1024]; static int ice_sboxes_initialised = 0; @@ -37,7 +40,7 @@ static const int ice_sxor[4][4] = { {0xea, 0xcb, 0x2e, 0x04}}; /* Permutation values for the P-box */ -static const unsigned long ice_pbox[32] = { +static const uint32_t ice_pbox[32] = { 0x00000001, 0x00000080, 0x00000400, 0x00002000, 0x00080000, 0x00200000, 0x01000000, 0x40000000, 0x00000008, 0x00000020, 0x00000100, 0x00004000, @@ -61,11 +64,11 @@ static const int ice_keyrot[16] = { static unsigned int gf_mult ( - register unsigned int a, - register unsigned int b, - register unsigned int m + unsigned int a, + unsigned int b, + unsigned int m ) { - register unsigned int res = 0; + unsigned int res = 0; while (b) { if (b & 1) @@ -87,12 +90,12 @@ gf_mult ( * Raise the base to the power of 7, modulo m. */ -static unsigned long +static uint32_t gf_exp7 ( - register unsigned int b, + unsigned int b, unsigned int m ) { - register unsigned int x; + unsigned int x; if (b == 0) return (0); @@ -108,12 +111,12 @@ gf_exp7 ( * Carry out the ICE 32-bit P-box permutation. */ -static unsigned long +static uint32_t ice_perm32 ( - register unsigned long x + uint32_t x ) { - register unsigned long res = 0; - register const unsigned long *pbox = ice_pbox; + uint32_t res = 0; + const uint32_t *pbox = ice_pbox; while (x) { if (x & 1) @@ -134,12 +137,12 @@ ice_perm32 ( static void ice_sboxes_init (void) { - register int i; + int i; for (i=0; i<1024; i++) { int col = (i >> 1) & 0xff; int row = (i & 0x1) | ((i & 0x200) >> 8); - unsigned long x; + uint32_t x; x = gf_exp7 (col ^ ice_sxor[0][row], ice_smod[0][row]) << 24; ice_sbox[0][i] = ice_perm32 (x); @@ -201,13 +204,13 @@ IceKey::~IceKey () * The single round ICE f function. */ -static unsigned long +static uint32_t ice_f ( - register unsigned long p, + uint32_t p, const IceSubkey *sk ) { - unsigned long tl, tr; /* Expanded 40-bit values */ - unsigned long al, ar; /* Salted expanded 40-bit values */ + uint32_t tl, tr; /* Expanded 40-bit values */ + uint32_t al, ar; /* Salted expanded 40-bit values */ /* Left half expansion */ tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00); @@ -241,15 +244,15 @@ IceKey::encrypt ( unsigned char *ctext ) const { - register int i; - register unsigned long l, r; + int i; + uint32_t l, r; - l = (((unsigned long) ptext[0]) << 24) - | (((unsigned long) ptext[1]) << 16) - | (((unsigned long) ptext[2]) << 8) | ptext[3]; - r = (((unsigned long) ptext[4]) << 24) - | (((unsigned long) ptext[5]) << 16) - | (((unsigned long) ptext[6]) << 8) | ptext[7]; + l = (((uint32_t) ptext[0]) << 24) + | (((uint32_t) ptext[1]) << 16) + | (((uint32_t) ptext[2]) << 8) | ptext[3]; + r = (((uint32_t) ptext[4]) << 24) + | (((uint32_t) ptext[5]) << 16) + | (((uint32_t) ptext[6]) << 8) | ptext[7]; for (i = 0; i < _rounds; i += 2) { l ^= ice_f (r, &_keysched[i]); @@ -276,15 +279,15 @@ IceKey::decrypt ( unsigned char *ptext ) const { - register int i; - register unsigned long l, r; + int i; + uint32_t l, r; - l = (((unsigned long) ctext[0]) << 24) - | (((unsigned long) ctext[1]) << 16) - | (((unsigned long) ctext[2]) << 8) | ctext[3]; - r = (((unsigned long) ctext[4]) << 24) - | (((unsigned long) ctext[5]) << 16) - | (((unsigned long) ctext[6]) << 8) | ctext[7]; + l = (((uint32_t) ctext[0]) << 24) + | (((uint32_t) ctext[1]) << 16) + | (((uint32_t) ctext[2]) << 8) | ctext[3]; + r = (((uint32_t) ctext[4]) << 24) + | (((uint32_t) ctext[5]) << 16) + | (((uint32_t) ctext[6]) << 8) | ctext[7]; for (i = _rounds - 1; i > 0; i -= 2) { l ^= ice_f (r, &_keysched[i]); @@ -314,20 +317,20 @@ IceKey::scheduleBuild ( int i; for (i=0; i<8; i++) { - register int j; - register int kr = keyrot[i]; + int j; + int kr = keyrot[i]; IceSubkey *isk = &_keysched[n + i]; for (j=0; j<3; j++) isk->val[j] = 0; for (j=0; j<15; j++) { - register int k; - unsigned long *curr_sk = &isk->val[j % 3]; + int k; + uint32_t *curr_sk = &isk->val[j % 3]; for (k=0; k<4; k++) { unsigned short *curr_kb = &kb[(kr + k) & 3]; - register int bit = *curr_kb & 1; + int bit = *curr_kb & 1; *curr_sk = (*curr_sk << 1) | bit; *curr_kb = (*curr_kb >> 1) | ((bit ^ 1) << 15); diff --git a/mathlib/almostequal.cpp b/mathlib/almostequal.cpp new file mode 100644 index 00000000..d4d3fba2 --- /dev/null +++ b/mathlib/almostequal.cpp @@ -0,0 +1,97 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Fast ways to compare equality of two floats. Assumes +// sizeof(float) == sizeof(int) and we are using IEEE format. +// +// Source: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm +//=====================================================================================// + +#include +#include + +#include "mathlib/mathlib.h" + +static inline bool AE_IsInfinite(float a) +{ + const int kInfAsInt = 0x7F800000; + + // An infinity has an exponent of 255 (shift left 23 positions) and + // a zero mantissa. There are two infinities - positive and negative. + if ((*(int*)&a & 0x7FFFFFFF) == kInfAsInt) + return true; + return false; +} + +static inline bool AE_IsNan(float a) +{ + // a NAN has an exponent of 255 (shifted left 23 positions) and + // a non-zero mantissa. + int exp = *(int*)&a & 0x7F800000; + int mantissa = *(int*)&a & 0x007FFFFF; + if (exp == 0x7F800000 && mantissa != 0) + return true; + return false; +} + +static inline int AE_Sign(float a) +{ + // The sign bit of a number is the high bit. + return (*(int*)&a) & 0x80000000; +} + +// This is the 'final' version of the AlmostEqualUlps function. +// The optional checks are included for completeness, but in many +// cases they are not necessary, or even not desirable. +bool AlmostEqual(float a, float b, int maxUlps) +{ + // There are several optional checks that you can do, depending + // on what behavior you want from your floating point comparisons. + // These checks should not be necessary and they are included + // mainly for completeness. + + // If a or b are infinity (positive or negative) then + // only return true if they are exactly equal to each other - + // that is, if they are both infinities of the same sign. + // This check is only needed if you will be generating + // infinities and you don't want them 'close' to numbers + // near FLT_MAX. + if (AE_IsInfinite(a) || AE_IsInfinite(b)) + return a == b; + + // If a or b are a NAN, return false. NANs are equal to nothing, + // not even themselves. + // This check is only needed if you will be generating NANs + // and you use a maxUlps greater than 4 million or you want to + // ensure that a NAN does not equal itself. + if (AE_IsNan(a) || AE_IsNan(b)) + return false; + + // After adjusting floats so their representations are lexicographically + // ordered as twos-complement integers a very small positive number + // will compare as 'close' to a very small negative number. If this is + // not desireable, and if you are on a platform that supports + // subnormals (which is the only place the problem can show up) then + // you need this check. + // The check for a == b is because zero and negative zero have different + // signs but are equal to each other. + if (AE_Sign(a) != AE_Sign(b)) + return a == b; + + int aInt = *(int*)&a; + // Make aInt lexicographically ordered as a twos-complement int + if (aInt < 0) + aInt = 0x80000000 - aInt; + // Make bInt lexicographically ordered as a twos-complement int + int bInt = *(int*)&b; + if (bInt < 0) + bInt = 0x80000000 - bInt; + + // Now we can compare aInt and bInt to find out how far apart a and b + // are. + int intDiff = abs(aInt - bInt); + if (intDiff <= maxUlps) + return true; + return false; +} + + diff --git a/mathlib/color_conversion.cpp b/mathlib/color_conversion.cpp index c29d59ca..0b7dc87f 100644 --- a/mathlib/color_conversion.cpp +++ b/mathlib/color_conversion.cpp @@ -106,27 +106,23 @@ ALIGN128 float power2_n[256] = // 2**(index - 128) / 255 // You can use this to double check the exponent table and assert that // the precomputation is correct. #ifdef DBGFLAG_ASSERT -#ifdef _MSC_VER +#ifdef _WIN32 #pragma warning(push) #pragma warning( disable : 4189 ) // disable unused local variable warning #endif -#ifdef __GNUC__ -__attribute__((unused)) static void CheckExponentTable() -#else static void CheckExponentTable() -#endif { for( int i = 0; i < 256; i++ ) { float testAgainst = pow( 2.0f, i - 128 ) / 255.0f; float diff = testAgainst - power2_n[i] ; float relativeDiff = diff / testAgainst; - Assert( sizeof(relativeDiff) > 0 && testAgainst == 0 ? - power2_n[i] < 1.16E-041 : - power2_n[i] == testAgainst ); + Assert( testAgainst == 0 ? + power2_n[i] < 1.16E-041 : + power2_n[i] == testAgainst ); } } -#ifdef _MSC_VER +#ifdef _WIN32 #pragma warning(pop) #endif #endif @@ -617,10 +613,10 @@ void VectorToColorRGBExp32( const Vector& vin, ColorRGBExp32 &c ) scalar = *reinterpret_cast(&fbits); } - // we should never need to clamp: - Assert(vin.x * scalar <= 255.0f && - vin.y * scalar <= 255.0f && - vin.z * scalar <= 255.0f); + // We can totally wind up above 255 and that's okay--but above 256 would be right out. + Assert(vin.x * scalar < 256.0f && + vin.y * scalar < 256.0f && + vin.z * scalar < 256.0f); // This awful construction is necessary to prevent VC2005 from using the // fldcw/fnstcw control words around every float-to-unsigned-char operation. diff --git a/mathlib/imagequant.cpp b/mathlib/imagequant.cpp index b84d2c5c..e5a7a5ce 100644 --- a/mathlib/imagequant.cpp +++ b/mathlib/imagequant.cpp @@ -6,7 +6,7 @@ // //=============================================================================// #include -#include +#include #define N_EXTRAVALUES 1 #define N_DIMENSIONS (3+N_EXTRAVALUES) @@ -46,7 +46,7 @@ void ColorQuantize(uint8 const *Image, val1+=PIXEL(x,y,c)*ExtraValueXForms[i*3+c]; val1>>=8; NthSample(s,y*Width+x,N_DIMENSIONS)->Value[c]=(uint8) - (MIN(255,MAX(0,val1))); + (V_min(255,V_max(0,val1))); } } struct QuantizedValue *q=Quantize(s,Width*Height,N_DIMENSIONS, @@ -76,7 +76,7 @@ void ColorQuantize(uint8 const *Image, tryc+=Error[x][c][ErrorUse]; Error[x][c][ErrorUse]=0; } - samp[c]=(uint8) MIN(255,MAX(0,tryc)); + samp[c]=(uint8) V_min(255,V_max(0,tryc)); } struct QuantizedValue *f=FindMatch(samp,3,Weights,q); out_pixels[Width*y+x]=(uint8) (f->value); diff --git a/mathlib/lightdesc.cpp b/mathlib/lightdesc.cpp index 23c51c76..6693609c 100644 --- a/mathlib/lightdesc.cpp +++ b/mathlib/lightdesc.cpp @@ -10,7 +10,7 @@ void LightDesc_t::RecalculateDerivedValues(void) { - m_Flags=0; + m_Flags = LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED; if (m_Attenuation0) m_Flags|=LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0; if (m_Attenuation1) diff --git a/mathlib/mathlib-2005.vcproj b/mathlib/mathlib-2005.vcproj deleted file mode 100644 index a9c6c427..00000000 --- a/mathlib/mathlib-2005.vcproj +++ /dev/null @@ -1,399 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mathlib/mathlib_base.cpp b/mathlib/mathlib_base.cpp index 63ba0b60..d7dd7f29 100644 --- a/mathlib/mathlib_base.cpp +++ b/mathlib/mathlib_base.cpp @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: Math primitives. // @@ -6,6 +6,7 @@ /// FIXME: As soon as all references to mathlib.c are gone, include it in here +#include #include #include // Needed for FLT_EPSILON @@ -16,7 +17,7 @@ #include "tier0/vprof.h" //#define _VPROF_MATHLIB -#ifdef _MSC_VER +#ifdef _WIN32 #pragma warning(disable:4244) // "conversion from 'const int' to 'float', possible loss of data" #pragma warning(disable:4730) // "mixing _m64 and floating point expressions may result in incorrect code" #endif @@ -24,6 +25,10 @@ #include "mathlib/mathlib.h" #include "mathlib/vector.h" #if !defined( _X360 ) +#include "mathlib/amd3dx.h" +#ifndef OSX +#include "3dnow.h" +#endif #include "sse.h" #endif @@ -425,6 +430,33 @@ void MatrixSetColumn( const Vector &in, int column, matrix3x4_t& out ) out[2][column] = in.z; } +void MatrixScaleBy ( const float flScale, matrix3x4_t &out ) +{ + out[0][0] *= flScale; + out[1][0] *= flScale; + out[2][0] *= flScale; + out[0][1] *= flScale; + out[1][1] *= flScale; + out[2][1] *= flScale; + out[0][2] *= flScale; + out[1][2] *= flScale; + out[2][2] *= flScale; +} + +void MatrixScaleByZero ( matrix3x4_t &out ) +{ + out[0][0] = 0.0f; + out[1][0] = 0.0f; + out[2][0] = 0.0f; + out[0][1] = 0.0f; + out[1][1] = 0.0f; + out[2][1] = 0.0f; + out[0][2] = 0.0f; + out[1][2] = 0.0f; + out[2][2] = 0.0f; +} + + int VectorCompare (const float *v1, const float *v2) { @@ -564,53 +596,128 @@ void ConcatRotations (const float in1[3][3], const float in2[3][3], float out[3] in1[2][2] * in2[2][2]; } +void ConcatTransforms_Aligned( const matrix3x4_t &m0, const matrix3x4_t &m1, matrix3x4_t &out ) +{ + Assert( (((size_t)&m0) % 16) == 0 ); + Assert( (((size_t)&m1) % 16) == 0 ); + Assert( (((size_t)&out) % 16) == 0 ); + + fltx4 lastMask = *(fltx4 *)(&g_SIMD_ComponentMask[3]); + fltx4 rowA0 = LoadAlignedSIMD( m0.m_flMatVal[0] ); + fltx4 rowA1 = LoadAlignedSIMD( m0.m_flMatVal[1] ); + fltx4 rowA2 = LoadAlignedSIMD( m0.m_flMatVal[2] ); + + fltx4 rowB0 = LoadAlignedSIMD( m1.m_flMatVal[0] ); + fltx4 rowB1 = LoadAlignedSIMD( m1.m_flMatVal[1] ); + fltx4 rowB2 = LoadAlignedSIMD( m1.m_flMatVal[2] ); + + // now we have the rows of m0 and the columns of m1 + // first output row + fltx4 A0 = SplatXSIMD(rowA0); + fltx4 A1 = SplatYSIMD(rowA0); + fltx4 A2 = SplatZSIMD(rowA0); + fltx4 mul00 = MulSIMD( A0, rowB0 ); + fltx4 mul01 = MulSIMD( A1, rowB1 ); + fltx4 mul02 = MulSIMD( A2, rowB2 ); + fltx4 out0 = AddSIMD( mul00, AddSIMD(mul01,mul02) ); + + // second output row + A0 = SplatXSIMD(rowA1); + A1 = SplatYSIMD(rowA1); + A2 = SplatZSIMD(rowA1); + fltx4 mul10 = MulSIMD( A0, rowB0 ); + fltx4 mul11 = MulSIMD( A1, rowB1 ); + fltx4 mul12 = MulSIMD( A2, rowB2 ); + fltx4 out1 = AddSIMD( mul10, AddSIMD(mul11,mul12) ); + + // third output row + A0 = SplatXSIMD(rowA2); + A1 = SplatYSIMD(rowA2); + A2 = SplatZSIMD(rowA2); + fltx4 mul20 = MulSIMD( A0, rowB0 ); + fltx4 mul21 = MulSIMD( A1, rowB1 ); + fltx4 mul22 = MulSIMD( A2, rowB2 ); + fltx4 out2 = AddSIMD( mul20, AddSIMD(mul21,mul22) ); + + // add in translation vector + A0 = AndSIMD(rowA0,lastMask); + A1 = AndSIMD(rowA1,lastMask); + A2 = AndSIMD(rowA2,lastMask); + out0 = AddSIMD(out0, A0); + out1 = AddSIMD(out1, A1); + out2 = AddSIMD(out2, A2); + + StoreAlignedSIMD( out.m_flMatVal[0], out0 ); + StoreAlignedSIMD( out.m_flMatVal[1], out1 ); + StoreAlignedSIMD( out.m_flMatVal[2], out2 ); +} /* ================ R_ConcatTransforms ================ */ + void ConcatTransforms (const matrix3x4_t& in1, const matrix3x4_t& in2, matrix3x4_t& out) { - Assert( s_bMathlibInitialized ); - if ( &in1 == &out ) +#if 0 + // test for ones that'll be 2x faster + if ( (((size_t)&in1) % 16) == 0 && (((size_t)&in2) % 16) == 0 && (((size_t)&out) % 16) == 0 ) { - matrix3x4_t in1b; - MatrixCopy( in1, in1b ); - ConcatTransforms( in1b, in2, out ); + ConcatTransforms_Aligned( in1, in2, out ); return; } - if ( &in2 == &out ) - { - matrix3x4_t in2b; - MatrixCopy( in2, in2b ); - ConcatTransforms( in1, in2b, out ); - return; - } - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + - in1[0][2] * in2[2][3] + in1[0][3]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + - in1[1][2] * in2[2][3] + in1[1][3]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; - out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + - in1[2][2] * in2[2][3] + in1[2][3]; +#endif + + fltx4 lastMask = *(fltx4 *)(&g_SIMD_ComponentMask[3]); + fltx4 rowA0 = LoadUnalignedSIMD( in1.m_flMatVal[0] ); + fltx4 rowA1 = LoadUnalignedSIMD( in1.m_flMatVal[1] ); + fltx4 rowA2 = LoadUnalignedSIMD( in1.m_flMatVal[2] ); + + fltx4 rowB0 = LoadUnalignedSIMD( in2.m_flMatVal[0] ); + fltx4 rowB1 = LoadUnalignedSIMD( in2.m_flMatVal[1] ); + fltx4 rowB2 = LoadUnalignedSIMD( in2.m_flMatVal[2] ); + + // now we have the rows of m0 and the columns of m1 + // first output row + fltx4 A0 = SplatXSIMD(rowA0); + fltx4 A1 = SplatYSIMD(rowA0); + fltx4 A2 = SplatZSIMD(rowA0); + fltx4 mul00 = MulSIMD( A0, rowB0 ); + fltx4 mul01 = MulSIMD( A1, rowB1 ); + fltx4 mul02 = MulSIMD( A2, rowB2 ); + fltx4 out0 = AddSIMD( mul00, AddSIMD(mul01,mul02) ); + + // second output row + A0 = SplatXSIMD(rowA1); + A1 = SplatYSIMD(rowA1); + A2 = SplatZSIMD(rowA1); + fltx4 mul10 = MulSIMD( A0, rowB0 ); + fltx4 mul11 = MulSIMD( A1, rowB1 ); + fltx4 mul12 = MulSIMD( A2, rowB2 ); + fltx4 out1 = AddSIMD( mul10, AddSIMD(mul11,mul12) ); + + // third output row + A0 = SplatXSIMD(rowA2); + A1 = SplatYSIMD(rowA2); + A2 = SplatZSIMD(rowA2); + fltx4 mul20 = MulSIMD( A0, rowB0 ); + fltx4 mul21 = MulSIMD( A1, rowB1 ); + fltx4 mul22 = MulSIMD( A2, rowB2 ); + fltx4 out2 = AddSIMD( mul20, AddSIMD(mul21,mul22) ); + + // add in translation vector + A0 = AndSIMD(rowA0,lastMask); + A1 = AndSIMD(rowA1,lastMask); + A2 = AndSIMD(rowA2,lastMask); + out0 = AddSIMD(out0, A0); + out1 = AddSIMD(out1, A1); + out2 = AddSIMD(out2, A2); + + // write to output + StoreUnalignedSIMD( out.m_flMatVal[0], out0 ); + StoreUnalignedSIMD( out.m_flMatVal[1], out1 ); + StoreUnalignedSIMD( out.m_flMatVal[2], out2 ); } @@ -1357,7 +1464,9 @@ float Bias( float x, float biasAmt ) { lastExponent = log( biasAmt ) * -1.4427f; // (-1.4427 = 1 / log(0.5)) } - return pow( x, lastExponent ); + float fRet = pow( x, lastExponent ); + Assert ( !IS_NAN( fRet ) ); + return fRet; } @@ -1373,7 +1482,9 @@ float Gain( float x, float biasAmt ) float SmoothCurve( float x ) { - return (1 - cos( x * M_PI )) * 0.5f; + // Actual smooth curve. Visualization: + // http://www.wolframalpha.com/input/?i=plot%5B+0.5+*+%281+-+cos%5B2+*+pi+*+x%5D%29+for+x+%3D+%280%2C+1%29+%5D + return 0.5f * (1 - cos( 2.0f * M_PI * x ) ); } @@ -1565,7 +1676,9 @@ float QuaternionAngleDiff( const Quaternion &p, const Quaternion &q ) QuaternionConjugate( q, qInv ); QuaternionMult( p, qInv, diff ); - float sinang = sqrt( diff.x * diff.x + diff.y * diff.y + diff.z * diff.z ); + // Note if the quaternion is slightly non-normalized the square root below may be more than 1, + // the value is clamped to one otherwise it may result in asin() returning an undefined result. + float sinang = MIN( 1.0f, sqrt( diff.x * diff.x + diff.y * diff.y + diff.z * diff.z ) ); float angle = RAD2DEG( 2 * asin( sinang ) ); return angle; #else @@ -1665,7 +1778,7 @@ void QuaternionScale( const Quaternion &p, float t, Quaternion &q ) // FIXME: nick, this isn't overly sensitive to accuracy, and it may be faster to // use the cos part (w) of the quaternion (sin(omega)*N,cos(omega)) to figure the new scale. float sinom = sqrt( DotProduct( &p.x, &p.x ) ); - sinom = MIN( sinom, 1.f ); + sinom = V_min( sinom, 1.f ); float sinsom = sin( asin( sinom ) * t ); @@ -1750,7 +1863,13 @@ void QuaternionMult( const Quaternion &p, const Quaternion &q, Quaternion &qt ) void QuaternionMatrix( const Quaternion &q, const Vector &pos, matrix3x4_t& matrix ) { - Assert( pos.IsValid() ); +#ifdef DBGFLAG_ASSERT + static bool s_bHushAsserts = !!CommandLine()->FindParm("-hushasserts"); + if (!s_bHushAsserts) + { + Assert( pos.IsValid() ); + } +#endif QuaternionMatrix( q, matrix ); @@ -1762,7 +1881,13 @@ void QuaternionMatrix( const Quaternion &q, const Vector &pos, matrix3x4_t& matr void QuaternionMatrix( const Quaternion &q, matrix3x4_t& matrix ) { Assert( s_bMathlibInitialized ); - Assert( q.IsValid() ); +#ifdef DBGFLAG_ASSERT + static bool s_bHushAsserts = !!CommandLine()->FindParm("-hushasserts"); + if ( !s_bHushAsserts ) + { + Assert( q.IsValid() ); + } +#endif #ifdef _VPROF_MATHLIB VPROF_BUDGET( "QuaternionMatrix", "Mathlib" ); @@ -2949,9 +3074,9 @@ float CalcSqrDistanceToAABB( const Vector &mins, const Vector &maxs, const Vecto void CalcClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut ) { - closestOut.x = clamp( point.x, mins.x, maxs.x ); - closestOut.y = clamp( point.y, mins.y, maxs.y ); - closestOut.z = clamp( point.z, mins.z, maxs.z ); + closestOut.x = std::clamp( point.x, mins.x, maxs.x ); + closestOut.y = std::clamp( point.y, mins.y, maxs.y ); + closestOut.z = std::clamp( point.z, mins.z, maxs.z ); } void CalcSqrDistAndClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut, float &distSqrOut ) @@ -3027,7 +3152,7 @@ void CalcClosestPointOnLineSegment( const Vector &P, const Vector &vLineA, const { Vector vDir; float t = CalcClosestPointToLineT( P, vLineA, vLineB, vDir ); - t = clamp( t, 0, 1 ); + t = std::clamp( t, 0.0f, 1.0f ); if ( outT ) { *outT = t; @@ -3099,7 +3224,7 @@ void CalcClosestPointOnLineSegment2D( const Vector2D &P, const Vector2D &vLineA, { Vector2D vDir; float t = CalcClosestPointToLineT2D( P, vLineA, vLineB, vDir ); - t = clamp( t, 0, 1 ); + t = std::clamp( t, 0.0f, 1.0f ); if ( outT ) { *outT = t; @@ -3210,7 +3335,7 @@ void MathLib_Init( float gamma, float texGamma, float brightness, int overbright #if !defined( _X360 ) // Grab the processor information: - const CPUInformation& pi = GetCPUInformation(); + const CPUInformation& pi = *GetCPUInformation(); // Select the default generic routines. pfSqrt = _sqrtf; @@ -3233,12 +3358,33 @@ void MathLib_Init( float gamma, float texGamma, float brightness, int overbright s_bMMXEnabled = false; } - s_b3DNowEnabled = false; + // SSE Generally performs better than 3DNow when present, so this is placed + // first to allow SSE to override these settings. +#if !defined( OSX ) && !defined( PLATFORM_WINDOWS_PC64 ) && !defined(LINUX) + if ( bAllow3DNow && pi.m_b3DNow ) + { + s_b3DNowEnabled = true; + + // Select the 3DNow specific routines if available; + pfVectorNormalize = _3DNow_VectorNormalize; + pfVectorNormalizeFast = _3DNow_VectorNormalizeFast; + pfInvRSquared = _3DNow_InvRSquared; + pfSqrt = _3DNow_Sqrt; + pfRSqrt = _3DNow_RSqrt; + pfRSqrtFast = _3DNow_RSqrt; + } + else +#endif + { + s_b3DNowEnabled = false; + } if ( bAllowSSE && pi.m_bSSE ) { s_bSSEEnabled = true; +#ifndef PLATFORM_WINDOWS_PC64 + // These are not yet available. // Select the SSE specific routines if available pfVectorNormalize = _VectorNormalize; pfVectorNormalizeFast = _SSE_VectorNormalizeFast; @@ -3246,7 +3392,8 @@ void MathLib_Init( float gamma, float texGamma, float brightness, int overbright pfSqrt = _SSE_Sqrt; pfRSqrt = _SSE_RSqrtAccurate; pfRSqrtFast = _SSE_RSqrtFast; -#ifdef _WIN32 +#endif +#ifdef PLATFORM_WINDOWS_PC32 pfFastSinCos = _SSE_SinCos; pfFastCos = _SSE_cos; #endif @@ -3259,7 +3406,7 @@ void MathLib_Init( float gamma, float texGamma, float brightness, int overbright if ( bAllowSSE2 && pi.m_bSSE2 ) { s_bSSE2Enabled = true; -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS_PC32 pfFastSinCos = _SSE2_SinCos; pfFastCos = _SSE2_cos; #endif @@ -3268,7 +3415,7 @@ void MathLib_Init( float gamma, float texGamma, float brightness, int overbright { s_bSSE2Enabled = false; } -#endif +#endif // !_X360 s_bMathlibInitialized = true; @@ -3919,10 +4066,10 @@ void CalcTriangleTangentSpace( const Vector &p0, const Vector &p1, const Vector //----------------------------------------------------------------------------- void RGBtoHSV( const Vector &rgb, Vector &hsv ) { - float flMax = MAX( rgb.x, rgb.y ); - flMax = MAX( flMax, rgb.z ); - float flMin = MIN( rgb.x, rgb.y ); - flMin = MIN( flMin, rgb.z ); + float flMax = V_max( rgb.x, rgb.y ); + flMax = V_max( flMax, rgb.z ); + float flMin = V_min( rgb.x, rgb.y ); + flMin = V_min( flMin, rgb.z ); // hsv.z is the value hsv.z = flMax; @@ -4069,3 +4216,44 @@ void GetInterpolationData( float const *pKnotPositions, *pInterpolationValue = FLerp( 0, 1, 0, flSizeOfGap, flOffsetFromStartOfGap ); return; } + +float RandomVectorInUnitSphere( Vector *pVector ) +{ + // Guarantee uniform random distribution within a sphere + // Graphics gems III contains this algorithm ("Nonuniform random point sets via warping") + float u = ((float)rand() / VALVE_RAND_MAX); + float v = ((float)rand() / VALVE_RAND_MAX); + float w = ((float)rand() / VALVE_RAND_MAX); + + float flPhi = acos( 1 - 2 * u ); + float flTheta = 2 * M_PI * v; + float flRadius = powf( w, 1.0f / 3.0f ); + + float flSinPhi, flCosPhi; + float flSinTheta, flCosTheta; + SinCos( flPhi, &flSinPhi, &flCosPhi ); + SinCos( flTheta, &flSinTheta, &flCosTheta ); + + pVector->x = flRadius * flSinPhi * flCosTheta; + pVector->y = flRadius * flSinPhi * flSinTheta; + pVector->z = flRadius * flCosPhi; + return flRadius; +} + +float RandomVectorInUnitCircle( Vector2D *pVector ) +{ + // Guarantee uniform random distribution within a sphere + // Graphics gems III contains this algorithm ("Nonuniform random point sets via warping") + float u = ((float)rand() / VALVE_RAND_MAX); + float v = ((float)rand() / VALVE_RAND_MAX); + + float flTheta = 2 * M_PI * v; + float flRadius = powf( u, 1.0f / 2.0f ); + + float flSinTheta, flCosTheta; + SinCos( flTheta, &flSinTheta, &flCosTheta ); + + pVector->x = flRadius * flCosTheta; + pVector->y = flRadius * flSinTheta; + return flRadius; +} diff --git a/mathlib/polyhedron.cpp b/mathlib/polyhedron.cpp index c7fb669e..0a7ca56d 100644 --- a/mathlib/polyhedron.cpp +++ b/mathlib/polyhedron.cpp @@ -34,7 +34,6 @@ CPolyhedron *ConvertLinkedGeometryToPolyhedron( GeneratePolyhedronFromPlanes_Uno //#define DEBUG_DUMP_POLYHEDRONS_TO_NUMBERED_GLVIEWS //dumps successfully generated polyhedrons #ifdef _DEBUG -#include "filesystem.h" void DumpPolyhedronToGLView( const CPolyhedron *pPolyhedron, const char *pFilename, const VMatrix *pTransform ); void DumpPlaneToGlView( const float *pPlane, float fGrayScale, const char *pszFileName, const VMatrix *pTransform ); void DumpLineToGLView( const Vector &vPoint1, const Vector &vColor1, const Vector &vPoint2, const Vector &vColor2, float fThickness, FILE *pFile ); @@ -103,19 +102,19 @@ CPolyhedron_AllocByNew *CPolyhedron_AllocByNew::Allocate( unsigned short iVertic class CPolyhedron_TempMemory : public CPolyhedron { public: -#ifdef _DEBUG +#ifdef DBGFLAG_ASSERT int iReferenceCount; #endif virtual void Release( void ) { -#ifdef _DEBUG +#ifdef DBGFLAG_ASSERT --iReferenceCount; #endif } CPolyhedron_TempMemory( void ) -#ifdef _DEBUG +#ifdef DBGFLAG_ASSERT : iReferenceCount( 0 ) #endif { }; @@ -128,7 +127,7 @@ static CPolyhedron_TempMemory s_TempMemoryPolyhedron; CPolyhedron *GetTempPolyhedron( unsigned short iVertices, unsigned short iLines, unsigned short iIndices, unsigned short iPolygons ) //grab the temporary polyhedron. Avoids new/delete for quick work. Can only be in use by one chunk of code at a time { AssertMsg( s_TempMemoryPolyhedron.iReferenceCount == 0, "Temporary polyhedron memory being rewritten before released" ); -#ifdef _DEBUG +#ifdef DBGFLAG_ASSERT ++s_TempMemoryPolyhedron.iReferenceCount; #endif s_TempMemoryPolyhedron_Buffer.SetCount( (sizeof( Vector ) * iVertices) + @@ -857,8 +856,8 @@ const char * DumpPolyhedronCutHistory( const CUtlVector &DumpedHi #else -#define AssertMsg_DumpPolyhedron(condition, message) -#define Assert_DumpPolyhedron(condition) +#define AssertMsg_DumpPolyhedron(condition, message) NULL; +#define Assert_DumpPolyhedron(condition) NULL; #endif diff --git a/mathlib/powsse.cpp b/mathlib/powsse.cpp index ebd91fec..48c13d19 100644 --- a/mathlib/powsse.cpp +++ b/mathlib/powsse.cpp @@ -6,6 +6,10 @@ #include "mathlib/ssemath.h" +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + fltx4 Pow_FixedPoint_Exponent_SIMD( const fltx4 & x, int exponent) { fltx4 rslt=Four_Ones; // x^0=1.0 @@ -32,8 +36,61 @@ fltx4 Pow_FixedPoint_Exponent_SIMD( const fltx4 & x, int exponent) break; } if (exponent<0) - return ReciprocalEstSIMD(rslt); // pow(x,-b)=1/pow(x,b) + return ReciprocalEstSaturateSIMD(rslt); // pow(x,-b)=1/pow(x,b) else return rslt; } + + + +/* + * (c) Ian Stephenson + * + * ian@dctsystems.co.uk + * + * Fast pow() reference implementation + */ + + +static float shift23=(1<<23); +static float OOshift23=1.0/(1<<23); + +float FastLog2(float i) +{ + float LogBodge=0.346607f; + float x; + float y; + x=*(int *)&i; + x*= OOshift23; //1/pow(2,23); + x=x-127; + + y=x-floorf(x); + y=(y-y*y)*LogBodge; + return x+y; +} +float FastPow2(float i) +{ + float PowBodge=0.33971f; + float x; + float y=i-floorf(i); + y=(y-y*y)*PowBodge; + + x=i+127-y; + x*= shift23; //pow(2,23); + *(int*)&x=(int)x; + return x; +} +float FastPow(float a, float b) +{ + if (a <= OOshift23) + { + return 0.0f; + } + return FastPow2(b*FastLog2(a)); +} +float FastPow10( float i ) +{ + return FastPow2( i * 3.321928f ); +} + diff --git a/mathlib/quantize.cpp b/mathlib/quantize.cpp index 2c8c12e5..75e5c548 100644 --- a/mathlib/quantize.cpp +++ b/mathlib/quantize.cpp @@ -18,11 +18,10 @@ #endif #include +#include #include -#include - static int current_ndims; static struct QuantizedValue *current_root; static int current_ssize; @@ -412,8 +411,8 @@ static void Label(struct QuantizedValue *q, int updatecolor) else for(int i=0;iMins[i]=MIN(q->Children[0]->Mins[i],q->Children[1]->Mins[i]); - q->Maxs[i]=MAX(q->Children[0]->Maxs[i],q->Children[1]->Maxs[i]); + q->Mins[i]=V_min(q->Children[0]->Mins[i],q->Children[1]->Mins[i]); + q->Maxs[i]=V_max(q->Children[0]->Maxs[i],q->Children[1]->Maxs[i]); } } } diff --git a/mathlib/simdvectormatrix.cpp b/mathlib/simdvectormatrix.cpp index ca21743e..8e375ecf 100644 --- a/mathlib/simdvectormatrix.cpp +++ b/mathlib/simdvectormatrix.cpp @@ -48,7 +48,7 @@ void CSIMDVectorMatrix::CreateFromRGBA_FloatImageData(int srcwidth, int srcheigh { for(int cp=0;cp<4; cp++) { - int real_cp=MIN( cp, ntrailing_pixels_per_source_line-1 ); + int real_cp=V_min( cp, ntrailing_pixels_per_source_line-1 ); data_out[4*c+cp]= data_in[c+4*real_cp]; } } diff --git a/mathlib/spherical.cpp b/mathlib/spherical.cpp new file mode 100644 index 00000000..d3aa9679 --- /dev/null +++ b/mathlib/spherical.cpp @@ -0,0 +1,124 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: spherical math routines +// +//=====================================================================================// + +#include +#include // Needed for FLT_EPSILON +#include "basetypes.h" +#include +#include "tier0/dbg.h" +#include "mathlib/mathlib.h" +#include "mathlib/vector.h" +#include "mathlib/spherical_geometry.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +float s_flFactorials[]={ + 1., + 1., + 2., + 6., + 24., + 120., + 720., + 5040., + 40320., + 362880., + 3628800., + 39916800., + 479001600., + 6227020800., + 87178291200., + 1307674368000., + 20922789888000., + 355687428096000., + 6402373705728000., + 121645100408832000., + 2432902008176640000., + 51090942171709440000., + 1124000727777607680000., + 25852016738884976640000., + 620448401733239439360000., + 15511210043330985984000000., + 403291461126605635584000000., + 10888869450418352160768000000., + 304888344611713860501504000000., + 8841761993739701954543616000000., + 265252859812191058636308480000000., + 8222838654177922817725562880000000., + 263130836933693530167218012160000000., + 8683317618811886495518194401280000000. +}; + +float AssociatedLegendrePolynomial( int nL, int nM, float flX ) +{ + // evaluate associated legendre polynomial at flX, using recurrence relation + float flPmm = 1.; + if ( nM > 0 ) + { + float flSomX2 = sqrt( ( 1 - flX ) * ( 1 + flX ) ); + float flFact = 1.; + for( int i = 0 ; i < nM; i++ ) + { + flPmm *= -flFact * flSomX2; + flFact += 2.0; + } + } + if ( nL == nM ) + return flPmm; + float flPmmp1 = flX * ( 2.0 * nM + 1.0 ) * flPmm; + if ( nL == nM + 1 ) + return flPmmp1; + float flPll = 0.; + for( int nLL = nM + 2 ; nLL <= nL; nLL++ ) + { + flPll = ( ( 2.0 * nLL - 1.0 ) * flX * flPmmp1 - ( nLL + nM - 1.0 ) * flPmm ) * ( 1.0 / ( nLL - nM ) ); + flPmm = flPmmp1; + flPmmp1 = flPll; + } + return flPll; +} + +static float SHNormalizationFactor( int nL, int nM ) +{ + double flTemp = ( ( 2. * nL + 1.0 ) * s_flFactorials[ nL - nM ] )/ ( 4. * M_PI * s_flFactorials[ nL + nM ] ); + return sqrt( flTemp ); +} + +#define SQRT_2 1.414213562373095 + +FORCEINLINE float SphericalHarmonic( int nL, int nM, float flTheta, float flPhi, float flCosTheta ) +{ + if ( nM == 0 ) + return SHNormalizationFactor( nL, 0 ) * AssociatedLegendrePolynomial( nL, nM, flCosTheta ); + + if ( nM > 0 ) + return SQRT_2 * SHNormalizationFactor( nL, nM ) * cos ( nM * flPhi ) * + AssociatedLegendrePolynomial( nL, nM, flCosTheta ); + + return + SQRT_2 * SHNormalizationFactor( nL, -nM ) * sin( -nM * flPhi ) * AssociatedLegendrePolynomial( nL, -nM, flCosTheta ); + +} + +float SphericalHarmonic( int nL, int nM, float flTheta, float flPhi ) +{ + return SphericalHarmonic( nL, nM, flTheta, flPhi, cos( flTheta ) ); +} + +float SphericalHarmonic( int nL, int nM, Vector const &vecDirection ) +{ + Assert( fabs( VectorLength( vecDirection ) - 1.0 ) < 0.0001 ); + float flPhi = acos( vecDirection.z ); + float flTheta = 0; + float S = Square( vecDirection.x ) + Square( vecDirection.y ); + if ( S > 0 ) + { + flTheta = atan2( vecDirection.y, vecDirection.x ); + } + return SphericalHarmonic( nL, nM, flTheta, flPhi, cos( flTheta ) ); +} + diff --git a/mathlib/sse.cpp b/mathlib/sse.cpp index d39c24f8..f628a9c8 100644 --- a/mathlib/sse.cpp +++ b/mathlib/sse.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: SSE Math primitives. // @@ -16,8 +16,13 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" +#ifndef COMPILER_MSVC64 +// Implement for 64-bit Windows if needed. + +#ifdef _WIN32 static const uint32 _sincos_masks[] = { (uint32)0x0, (uint32)~0x0 }; static const uint32 _sincos_inv_masks[] = { (uint32)~0x0, (uint32)0x0 }; +#endif //----------------------------------------------------------------------------- // Macros and constants required by some of the SSE assembly: @@ -35,20 +40,21 @@ static const uint32 _sincos_inv_masks[] = { (uint32)~0x0, (uint32)0x0 }; #define _PS_CONST(Name, Val) \ static const __declspec(align(16)) float _ps_##Name[4] = { Val, Val, Val, Val } -#elif defined _LINUX || defined __APPLE__ +#elif POSIX #define _PS_EXTERN_CONST(Name, Val) \ - const __attribute__((aligned(16))) float _ps_##Name[4] = { Val, Val, Val, Val } + const float _ps_##Name[4] __attribute__((aligned(16))) = { Val, Val, Val, Val } #define _PS_EXTERN_CONST_TYPE(Name, Type, Val) \ - const __attribute__((aligned(16))) Type _ps_##Name[4] = { Val, Val, Val, Val }; \ + const Type _ps_##Name[4] __attribute__((aligned(16))) = { Val, Val, Val, Val }; \ #define _EPI32_CONST(Name, Val) \ - static const __attribute__((aligned(16))) int32 _epi32_##Name[4] = { Val, Val, Val, Val } + static const int32 _epi32_##Name[4] __attribute__((aligned(16))) = { Val, Val, Val, Val } #define _PS_CONST(Name, Val) \ - static const __attribute__((aligned(16))) float _ps_##Name[4] = { Val, Val, Val, Val } + static const float _ps_##Name[4] __attribute__((aligned(16))) = { Val, Val, Val, Val } #endif +#ifdef _WIN32 _PS_EXTERN_CONST(am_0, 0.0f); _PS_EXTERN_CONST(am_1, 1.0f); _PS_EXTERN_CONST(am_m1, -1.0f); @@ -59,8 +65,8 @@ _PS_EXTERN_CONST(am_pi_o_2, (float)(M_PI / 2.0)); _PS_EXTERN_CONST(am_2_o_pi, (float)(2.0 / M_PI)); _PS_EXTERN_CONST(am_pi_o_4, (float)(M_PI / 4.0)); _PS_EXTERN_CONST(am_4_o_pi, (float)(4.0 / M_PI)); -_PS_EXTERN_CONST_TYPE(am_sign_mask, int32, 0x80000000); -_PS_EXTERN_CONST_TYPE(am_inv_sign_mask, int32, ~0x80000000); +_PS_EXTERN_CONST_TYPE(am_sign_mask, int32, static_cast(0x80000000)); +_PS_EXTERN_CONST_TYPE(am_inv_sign_mask, int32, static_cast(~0x80000000)); _PS_EXTERN_CONST_TYPE(am_min_norm_pos,int32, 0x00800000); _PS_EXTERN_CONST_TYPE(am_mant_mask, int32, 0x7f800000); _PS_EXTERN_CONST_TYPE(am_inv_mant_mask, int32, ~0x7f800000); @@ -72,6 +78,7 @@ _PS_CONST(sincos_p0, 0.15707963267948963959e1f); _PS_CONST(sincos_p1, -0.64596409750621907082e0f); _PS_CONST(sincos_p2, 0.7969262624561800806e-1f); _PS_CONST(sincos_p3, -0.468175413106023168e-2f); +#endif #ifdef PFN_VECTORMA void __cdecl _SSE_VectorMA( const float *start, float scale, const float *direction, float *dest ); @@ -90,14 +97,8 @@ float _SSE_Sqrt(float x) sqrtss xmm0, x movss root, xmm0 } -#elif defined _LINUX || defined __APPLE__ - __asm__ __volatile__( - "movss %1,%%xmm2\n" - "sqrtss %%xmm2,%%xmm1\n" - "movss %%xmm1,%0" - : "=m" (root) - : "m" (x) - ); +#elif POSIX + _mm_store_ss( &root, _mm_sqrt_ss( _mm_load_ss( &x ) ) ); #endif return root; } @@ -120,14 +121,21 @@ float _SSE_RSqrtAccurate(float x) return (0.5f * rroot) * (3.f - (x * rroot) * rroot); } #else + +#ifdef POSIX +const __m128 f3 = _mm_set_ss(3.0f); // 3 as SSE value +const __m128 f05 = _mm_set_ss(0.5f); // 0.5 as SSE value +#endif + // Intel / Kipps SSE RSqrt. Significantly faster than above. float _SSE_RSqrtAccurate(float a) { + +#ifdef _WIN32 float x; float half = 0.5f; float three = 3.f; -#ifdef _WIN32 __asm { movss xmm3, a; @@ -143,26 +151,25 @@ float _SSE_RSqrtAccurate(float a) movss x, xmm1; } -#elif defined _LINUX || defined __APPLE__ - __asm__ __volatile__( - "movss %1, %%xmm3 \n\t" - "movss %2, %%xmm1 \n\t" - "movss %3, %%xmm2 \n\t" - "rsqrtss %%xmm3, %%xmm0 \n\t" - "mulss %%xmm0, %%xmm3 \n\t" - "mulss %%xmm0, %%xmm1 \n\t" - "mulss %%xmm0, %%xmm3 \n\t" - "subss %%xmm3, %%xmm2 \n\t" - "mulss %%xmm2, %%xmm1 \n\t" - "movss %%xmm1, %0 \n\t" - : "=m" (x) - : "m" (a), "m" (half), "m" (three) -); + + return x; +#elif POSIX + __m128 xx = _mm_load_ss( &a ); + __m128 xr = _mm_rsqrt_ss( xx ); + __m128 xt; + + xt = _mm_mul_ss( xr, xr ); + xt = _mm_mul_ss( xt, xx ); + xt = _mm_sub_ss( f3, xt ); + xt = _mm_mul_ss( xt, f05 ); + xr = _mm_mul_ss( xr, xt ); + + _mm_store_ss( &a, xr ); + return a; #else #error "Not Implemented" #endif - return x; } #endif @@ -172,21 +179,15 @@ float _SSE_RSqrtFast(float x) { Assert( s_bMathlibInitialized ); - float rroot = 0.0f; + float rroot; #ifdef _WIN32 _asm { rsqrtss xmm0, x movss rroot, xmm0 } -#elif defined _LINUX || defined __APPLE__ - __asm__ __volatile__( - "rsqrtss %1, %%xmm0 \n\t" - "movss %%xmm0, %0 \n\t" - : "=m" (x) - : "m" (rroot) - : "%xmm0" - ); +#elif POSIX + __asm__ __volatile__( "rsqrtss %0, %1" : "=x" (rroot) : "x" (x) ); #else #error #endif @@ -202,11 +203,14 @@ float FASTCALL _SSE_VectorNormalize (Vector& vec) // sice vec only has 3 floats, we can't "movaps" directly into it. #ifdef _WIN32 __declspec(align(16)) float result[4]; -#elif defined _LINUX || defined __APPLE__ - __attribute__((aligned(16))) float result[4]; +#elif POSIX + float result[4] __attribute__((aligned(16))); #endif float *v = &vec[0]; +#ifdef _WIN32 + float *r = &result[0]; +#endif float radius = 0.f; // Blah, get rid of these comparisons ... in reality, if you have all 3 as zero, it shouldn't @@ -214,7 +218,6 @@ float FASTCALL _SSE_VectorNormalize (Vector& vec) if ( v[0] || v[1] || v[2] ) { #ifdef _WIN32 - float *r = &result[0]; _asm { mov eax, v @@ -239,7 +242,7 @@ float FASTCALL _SSE_VectorNormalize (Vector& vec) mulps xmm4, xmm1 // r4 = vx * 1/radius, vy * 1/radius, vz * 1/radius, X movaps [edx], xmm4 // v = vx * 1/radius, vy * 1/radius, vz * 1/radius, X } -#elif defined _LINUX || defined __APPLE__ +#elif POSIX __asm__ __volatile__( #ifdef ALIGNED_VECTOR "movaps %2, %%xmm4 \n\t" @@ -262,6 +265,7 @@ float FASTCALL _SSE_VectorNormalize (Vector& vec) "movaps %%xmm4, %1 \n\t" : "=m" (radius), "=m" (result) : "m" (*v) + : "xmm1", "xmm2", "xmm3", "xmm4" ); #else #error "Not Implemented" @@ -303,12 +307,13 @@ float _SSE_InvRSquared(const float* v) shufps xmm2, xmm2, 1 // x2 = vy * vy, X, X, X addss xmm1, xmm2 // x1 = (vx * vx) + (vy * vy), X, X, X addss xmm1, xmm3 // x1 = (vx * vx) + (vy * vy) + (vz * vz), X, X, X - maxss xmm1, xmm5 // x1 = MAX( 1.0, x1 ) - rcpss xmm0, xmm1 // x0 = 1 / MAX( 1.0, x1 ) + maxss xmm1, xmm5 // x1 = max( 1.0, x1 ) + rcpss xmm0, xmm1 // x0 = 1 / max( 1.0, x1 ) movss inv_r2, xmm0 // inv_r2 = x0 } -#elif defined _LINUX || defined __APPLE__ +#elif POSIX __asm__ __volatile__( + "movss %0, %%xmm5 \n\t" #ifdef ALIGNED_VECTOR "movaps %1, %%xmm4 \n\t" #else @@ -324,8 +329,9 @@ float _SSE_InvRSquared(const float* v) "maxss %%xmm5, %%xmm1 \n\t" "rcpss %%xmm1, %%xmm0 \n\t" "movss %%xmm0, %0 \n\t" - : "=m" (inv_r2) - : "m" (*v), "m" (inv_r2) + : "+m" (inv_r2) + : "m" (*v) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); #else #error "Not Implemented" @@ -334,6 +340,50 @@ float _SSE_InvRSquared(const float* v) return inv_r2; } + +#ifdef POSIX +// #define _PS_CONST(Name, Val) static const ALIGN16 float _ps_##Name[4] ALIGN16_POST = { Val, Val, Val, Val } +#define _PS_CONST_TYPE(Name, Type, Val) static const ALIGN16 Type _ps_##Name[4] ALIGN16_POST = { static_cast(Val), static_cast(Val), static_cast(Val), static_cast(Val) } + +_PS_CONST_TYPE(sign_mask, int, 0x80000000); +_PS_CONST_TYPE(inv_sign_mask, int, ~0x80000000); + + +#define _PI32_CONST(Name, Val) static const ALIGN16 int _pi32_##Name[4] ALIGN16_POST = { Val, Val, Val, Val } + +_PI32_CONST(1, 1); +_PI32_CONST(inv1, ~1); +_PI32_CONST(2, 2); +_PI32_CONST(4, 4); +#ifdef _WIN32 +_PI32_CONST(0x7f, 0x7f); +#endif +_PS_CONST(1 , 1.0f); +_PS_CONST(0p5, 0.5f); + +_PS_CONST(minus_cephes_DP1, -0.78515625); +_PS_CONST(minus_cephes_DP2, -2.4187564849853515625e-4); +_PS_CONST(minus_cephes_DP3, -3.77489497744594108e-8); +_PS_CONST(sincof_p0, -1.9515295891E-4); +_PS_CONST(sincof_p1, 8.3321608736E-3); +_PS_CONST(sincof_p2, -1.6666654611E-1); +_PS_CONST(coscof_p0, 2.443315711809948E-005); +_PS_CONST(coscof_p1, -1.388731625493765E-003); +_PS_CONST(coscof_p2, 4.166664568298827E-002); +_PS_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI + +typedef union xmm_mm_union { + __m128 xmm; + __m64 mm[2]; +} xmm_mm_union; + +#define COPY_MM_TO_XMM(mm0_, mm1_, xmm_) { xmm_mm_union u; u.mm[0]=mm0_; u.mm[1]=mm1_; xmm_ = u.xmm; } + +typedef __m128 v4sf; // vector of 4 float (sse1) +typedef __m64 v2si; // vector of 2 int (mmx) + +#endif + void _SSE_SinCos(float x, float* s, float* c) { #ifdef _WIN32 @@ -421,8 +471,121 @@ void _SSE_SinCos(float x, float* s, float* c) movss [eax], xmm0 movss [edx], xmm4 } -#elif defined _LINUX || defined __APPLE__ -// #warning "_SSE_sincos NOT implemented!" +#elif POSIX + + Assert( "Needs testing, verify impl!\n" ); + + v4sf xx = _mm_load_ss( &x ); + + v4sf xmm1, xmm2, xmm3 = _mm_setzero_ps(), sign_bit_sin, y; + v2si mm0, mm1, mm2, mm3, mm4, mm5; + sign_bit_sin = xx; + /* take the absolute value */ + xx = _mm_and_ps(xx, *(v4sf*)_ps_inv_sign_mask); + /* extract the sign bit (upper one) */ + sign_bit_sin = _mm_and_ps(sign_bit_sin, *(v4sf*)_ps_sign_mask); + + /* scale by 4/Pi */ + y = _mm_mul_ps(xx, *(v4sf*)_ps_cephes_FOPI); + + /* store the integer part of y in mm2:mm3 */ + xmm3 = _mm_movehl_ps(xmm3, y); + mm2 = _mm_cvttps_pi32(y); + mm3 = _mm_cvttps_pi32(xmm3); + + /* j=(j+1) & (~1) (see the cephes sources) */ + mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1); + mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1); + mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1); + mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1); + + y = _mm_cvtpi32x2_ps(mm2, mm3); + + mm4 = mm2; + mm5 = mm3; + + /* get the swap sign flag for the sine */ + mm0 = _mm_and_si64(mm2, *(v2si*)_pi32_4); + mm1 = _mm_and_si64(mm3, *(v2si*)_pi32_4); + mm0 = _mm_slli_pi32(mm0, 29); + mm1 = _mm_slli_pi32(mm1, 29); + v4sf swap_sign_bit_sin; + COPY_MM_TO_XMM(mm0, mm1, swap_sign_bit_sin); + + /* get the polynom selection mask for the sine */ + + mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2); + mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2); + mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64()); + mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64()); + v4sf poly_mask; + COPY_MM_TO_XMM(mm2, mm3, poly_mask); + + /* The magic pass: "Extended precision modular arithmetic" + x = ((x - y * DP1) - y * DP2) - y * DP3; */ + xmm1 = *(v4sf*)_ps_minus_cephes_DP1; + xmm2 = *(v4sf*)_ps_minus_cephes_DP2; + xmm3 = *(v4sf*)_ps_minus_cephes_DP3; + xmm1 = _mm_mul_ps(y, xmm1); + xmm2 = _mm_mul_ps(y, xmm2); + xmm3 = _mm_mul_ps(y, xmm3); + xx = _mm_add_ps(xx, xmm1); + xx = _mm_add_ps(xx, xmm2); + xx = _mm_add_ps(xx, xmm3); + + /* get the sign flag for the cosine */ + mm4 = _mm_sub_pi32(mm4, *(v2si*)_pi32_2); + mm5 = _mm_sub_pi32(mm5, *(v2si*)_pi32_2); + mm4 = _mm_andnot_si64(mm4, *(v2si*)_pi32_4); + mm5 = _mm_andnot_si64(mm5, *(v2si*)_pi32_4); + mm4 = _mm_slli_pi32(mm4, 29); + mm5 = _mm_slli_pi32(mm5, 29); + v4sf sign_bit_cos; + COPY_MM_TO_XMM(mm4, mm5, sign_bit_cos); + _mm_empty(); /* good-bye mmx */ + + sign_bit_sin = _mm_xor_ps(sign_bit_sin, swap_sign_bit_sin); + + + /* Evaluate the first polynom (0 <= x <= Pi/4) */ + v4sf z = _mm_mul_ps(xx,xx); + y = *(v4sf*)_ps_coscof_p0; + + y = _mm_mul_ps(y, z); + y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1); + y = _mm_mul_ps(y, z); + y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2); + y = _mm_mul_ps(y, z); + y = _mm_mul_ps(y, z); + v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5); + y = _mm_sub_ps(y, tmp); + y = _mm_add_ps(y, *(v4sf*)_ps_1); + + /* Evaluate the second polynom (Pi/4 <= x <= 0) */ + + v4sf y2 = *(v4sf*)_ps_sincof_p0; + y2 = _mm_mul_ps(y2, z); + y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1); + y2 = _mm_mul_ps(y2, z); + y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2); + y2 = _mm_mul_ps(y2, z); + y2 = _mm_mul_ps(y2, xx); + y2 = _mm_add_ps(y2, xx); + + /* select the correct result from the two polynoms */ + xmm3 = poly_mask; + v4sf ysin2 = _mm_and_ps(xmm3, y2); + v4sf ysin1 = _mm_andnot_ps(xmm3, y); + y2 = _mm_sub_ps(y2,ysin2); + y = _mm_sub_ps(y, ysin1); + + xmm1 = _mm_add_ps(ysin1,ysin2); + xmm2 = _mm_add_ps(y,y2); + + /* update the sign */ + _mm_store_ss( s, _mm_xor_ps(xmm1, sign_bit_sin) ); + _mm_store_ss( c, _mm_xor_ps(xmm2, sign_bit_cos) ); + #else #error "Not Implemented" #endif @@ -479,8 +642,102 @@ float _SSE_cos( float x ) movss x, xmm0 } -#elif defined _LINUX || defined __APPLE__ -// #warning "_SSE_cos NOT implemented!" +#elif POSIX + + Assert( "Needs testing, verify impl!\n" ); + + v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, y; + v2si mm0, mm1, mm2, mm3; + /* take the absolute value */ + v4sf xx = _mm_load_ss( &x ); + + xx = _mm_and_ps(xx, *(v4sf*)_ps_inv_sign_mask); + + /* scale by 4/Pi */ + y = _mm_mul_ps(xx, *(v4sf*)_ps_cephes_FOPI); + + /* store the integer part of y in mm0:mm1 */ + xmm2 = _mm_movehl_ps(xmm2, y); + mm2 = _mm_cvttps_pi32(y); + mm3 = _mm_cvttps_pi32(xmm2); + + /* j=(j+1) & (~1) (see the cephes sources) */ + mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1); + mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1); + mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1); + mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1); + + y = _mm_cvtpi32x2_ps(mm2, mm3); + + + mm2 = _mm_sub_pi32(mm2, *(v2si*)_pi32_2); + mm3 = _mm_sub_pi32(mm3, *(v2si*)_pi32_2); + + /* get the swap sign flag in mm0:mm1 and the + polynom selection mask in mm2:mm3 */ + + mm0 = _mm_andnot_si64(mm2, *(v2si*)_pi32_4); + mm1 = _mm_andnot_si64(mm3, *(v2si*)_pi32_4); + mm0 = _mm_slli_pi32(mm0, 29); + mm1 = _mm_slli_pi32(mm1, 29); + + mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2); + mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2); + + mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64()); + mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64()); + + v4sf sign_bit, poly_mask; + COPY_MM_TO_XMM(mm0, mm1, sign_bit); + COPY_MM_TO_XMM(mm2, mm3, poly_mask); + _mm_empty(); /* good-bye mmx */ + + /* The magic pass: "Extended precision modular arithmetic" + x = ((x - y * DP1) - y * DP2) - y * DP3; */ + xmm1 = *(v4sf*)_ps_minus_cephes_DP1; + xmm2 = *(v4sf*)_ps_minus_cephes_DP2; + xmm3 = *(v4sf*)_ps_minus_cephes_DP3; + xmm1 = _mm_mul_ps(y, xmm1); + xmm2 = _mm_mul_ps(y, xmm2); + xmm3 = _mm_mul_ps(y, xmm3); + xx = _mm_add_ps(xx, xmm1); + xx = _mm_add_ps(xx, xmm2); + xx = _mm_add_ps(xx, xmm3); + + /* Evaluate the first polynom (0 <= x <= Pi/4) */ + y = *(v4sf*)_ps_coscof_p0; + v4sf z = _mm_mul_ps(xx,xx); + + y = _mm_mul_ps(y, z); + y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1); + y = _mm_mul_ps(y, z); + y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2); + y = _mm_mul_ps(y, z); + y = _mm_mul_ps(y, z); + v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5); + y = _mm_sub_ps(y, tmp); + y = _mm_add_ps(y, *(v4sf*)_ps_1); + + /* Evaluate the second polynom (Pi/4 <= x <= 0) */ + + v4sf y2 = *(v4sf*)_ps_sincof_p0; + y2 = _mm_mul_ps(y2, z); + y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1); + y2 = _mm_mul_ps(y2, z); + y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2); + y2 = _mm_mul_ps(y2, z); + y2 = _mm_mul_ps(y2, xx); + y2 = _mm_add_ps(y2, xx); + + /* select the correct result from the two polynoms */ + xmm3 = poly_mask; + y2 = _mm_and_ps(xmm3, y2); //, xmm3); + y = _mm_andnot_ps(xmm3, y); + y = _mm_add_ps(y,y2); + /* update the sign */ + + _mm_store_ss( &x, _mm_xor_ps(y, sign_bit) ); + #else #error "Not Implemented" #endif @@ -491,6 +748,7 @@ float _SSE_cos( float x ) //----------------------------------------------------------------------------- // SSE2 implementations of optimized routines: //----------------------------------------------------------------------------- +#ifdef PLATFORM_WINDOWS_PC32 void _SSE2_SinCos(float x, float* s, float* c) // any x { #ifdef _WIN32 @@ -569,13 +827,16 @@ void _SSE2_SinCos(float x, float* s, float* c) // any x movss [eax], xmm0 movss [edx], xmm6 } -#elif defined _LINUX || defined __APPLE__ -// #warning "_SSE2_SinCos NOT implemented!" +#elif POSIX + #warning "_SSE2_SinCos NOT implemented!" + Assert( 0 ); #else #error "Not Implemented" #endif } +#endif // PLATFORM_WINDOWS_PC32 +#ifdef PLATFORM_WINDOWS_PC32 float _SSE2_cos(float x) { #ifdef _WIN32 @@ -624,15 +885,18 @@ float _SSE2_cos(float x) mulss xmm0, xmm1 movss x, xmm0 } -#elif defined _LINUX || defined __APPLE__ -// #warning "_SSE2_cos NOT implemented!" +#elif POSIX + #warning "_SSE2_cos NOT implemented!" + Assert( 0 ); #else #error "Not Implemented" #endif return x; } +#endif // PLATFORM_WINDOWS_PC32 +#if 0 // SSE Version of VectorTransform void VectorTransformSSE(const float *in1, const matrix3x4_t& in2, float *out1) { @@ -681,8 +945,8 @@ void VectorTransformSSE(const float *in1, const matrix3x4_t& in2, float *out1) addss xmm0, [ecx+12] movss [edx+8], xmm0; } -#elif defined _LINUX || defined __APPLE__ -// #warning "VectorTransformSSE C implementation only" +#elif POSIX + #warning "VectorTransformSSE C implementation only" out1[0] = DotProduct(in1, in2[0]) + in2[0][3]; out1[1] = DotProduct(in1, in2[1]) + in2[1][3]; out1[2] = DotProduct(in1, in2[2]) + in2[2][3]; @@ -690,7 +954,9 @@ void VectorTransformSSE(const float *in1, const matrix3x4_t& in2, float *out1) #error "Not Implemented" #endif } +#endif +#if 0 void VectorRotateSSE( const float *in1, const matrix3x4_t& in2, float *out1 ) { Assert( s_bMathlibInitialized ); @@ -735,8 +1001,8 @@ void VectorRotateSSE( const float *in1, const matrix3x4_t& in2, float *out1 ) addss xmm0, xmm2; movss [edx+8], xmm0; } -#elif defined _LINUX || defined __APPLE__ -// #warning "VectorRotateSSE C implementation only" +#elif POSIX + #warning "VectorRotateSSE C implementation only" out1[0] = DotProduct( in1, in2[0] ); out1[1] = DotProduct( in1, in2[1] ); out1[2] = DotProduct( in1, in2[2] ); @@ -744,6 +1010,7 @@ void VectorRotateSSE( const float *in1, const matrix3x4_t& in2, float *out1 ) #error "Not Implemented" #endif } +#endif #ifdef _WIN32 void _declspec(naked) _SSE_VectorMA( const float *start, float scale, const float *direction, float *dest ) @@ -843,3 +1110,4 @@ vec_t DotProduct (const vec_t *a, const vec_t *c) } */ +#endif // COMPILER_MSVC64 diff --git a/mathlib/sse.h b/mathlib/sse.h index 0bc9f8c4..75a19163 100644 --- a/mathlib/sse.h +++ b/mathlib/sse.h @@ -15,9 +15,13 @@ void FASTCALL _SSE_VectorNormalizeFast(Vector& vec); float _SSE_InvRSquared(const float* v); void _SSE_SinCos(float x, float* s, float* c); float _SSE_cos( float x); +#ifdef PLATFORM_WINDOWS_PC32 void _SSE2_SinCos(float x, float* s, float* c); float _SSE2_cos(float x); +#endif +#if 0 void VectorTransformSSE(const float *in1, const matrix3x4_t& in2, float *out1); void VectorRotateSSE( const float *in1, const matrix3x4_t& in2, float *out1 ); +#endif #endif // _SSE_H diff --git a/mathlib/sseconst.cpp b/mathlib/sseconst.cpp index 662943be..d57f3c5e 100644 --- a/mathlib/sseconst.cpp +++ b/mathlib/sseconst.cpp @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -30,6 +30,7 @@ const fltx4 Four_FLT_MAX={FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; const fltx4 Four_Negative_FLT_MAX={-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX}; const fltx4 g_SIMD_0123 = { 0., 1., 2., 3. }; +extern const fltx4 g_QuatMultRowSign[4]; const fltx4 g_QuatMultRowSign[4] = { { 1.0f, 1.0f, -1.0f, 1.0f }, @@ -38,24 +39,24 @@ const fltx4 g_QuatMultRowSign[4] = { -1.0f, -1.0f, -1.0f, 1.0f } }; -const int32 ALIGN16 g_SIMD_clear_signmask[4]= {0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; -const int32 ALIGN16 g_SIMD_signmask[4]= { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; -const int32 ALIGN16 g_SIMD_lsbmask[4]= { 0xfffffffe, 0xfffffffe, 0xfffffffe, 0xfffffffe }; -const int32 ALIGN16 g_SIMD_clear_wmask[4]= { 0xffffffff, 0xffffffff, 0xffffffff, 0 }; -const int32 ALIGN16 g_SIMD_AllOnesMask[4]= { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; // ~0,~0,~0,~0 -const int32 ALIGN16 g_SIMD_Low16BitsMask[4]= { 0xffff, 0xffff, 0xffff, 0xffff }; // 0xffff x 4 +const int32 ALIGN16 g_SIMD_clear_signmask[4] ALIGN16_POST = {static_cast(0x7fffffff), static_cast(0x7fffffff), static_cast(0x7fffffff), static_cast(0x7fffffff)}; +const int32 ALIGN16 g_SIMD_signmask[4] ALIGN16_POST = { static_cast(0x80000000), static_cast(0x80000000), static_cast(0x80000000), static_cast(0x80000000) }; +const int32 ALIGN16 g_SIMD_lsbmask[4] ALIGN16_POST = { static_cast(0xfffffffe), static_cast(0xfffffffe), static_cast(0xfffffffe), static_cast(0xfffffffe) }; +const int32 ALIGN16 g_SIMD_clear_wmask[4] ALIGN16_POST = { static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0xffffffff), 0 }; +const int32 ALIGN16 g_SIMD_AllOnesMask[4] ALIGN16_POST = { static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0xffffffff) }; // ~0,~0,~0,~0 +const int32 ALIGN16 g_SIMD_Low16BitsMask[4] ALIGN16_POST = { 0xffff, 0xffff, 0xffff, 0xffff }; // 0xffff x 4 -const int32 ALIGN16 g_SIMD_ComponentMask[4][4] = +const int32 ALIGN16 g_SIMD_ComponentMask[4][4] ALIGN16_POST = { - { 0xFFFFFFFF, 0, 0, 0 }, { 0, 0xFFFFFFFF, 0, 0 }, { 0, 0, 0xFFFFFFFF, 0 }, { 0, 0, 0, 0xFFFFFFFF } + { static_cast(0xFFFFFFFF), 0, 0, 0 }, { 0, static_cast(0xFFFFFFFF), 0, 0 }, { 0, 0, static_cast(0xFFFFFFFF), 0 }, { 0, 0, 0, static_cast(0xFFFFFFFF) } }; -const int32 ALIGN16 g_SIMD_SkipTailMask[4][4] = +const int32 ALIGN16 g_SIMD_SkipTailMask[4][4] ALIGN16_POST = { - { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, - { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 }, - { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000 }, - { 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 }, + { static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0xffffffff) }, + { static_cast(0xffffffff), static_cast(0x00000000), static_cast(0x00000000), static_cast(0x00000000) }, + { static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0x00000000), static_cast(0x00000000) }, + { static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0xffffffff), static_cast(0x00000000) }, }; diff --git a/mathlib/ssenoise.cpp b/mathlib/ssenoise.cpp index 9aad6712..06f85222 100644 --- a/mathlib/ssenoise.cpp +++ b/mathlib/ssenoise.cpp @@ -30,6 +30,10 @@ static ALIGN16 int32 idx_mask[4]= {0xffff, 0xffff, 0xffff, 0xffff}; // returns 0..1 static inline float GetLatticePointValue( int idx_x, int idx_y, int idx_z ) { + NOTE_UNUSED(perm_d); + NOTE_UNUSED(impulse_ycoords); + NOTE_UNUSED(impulse_zcoords); + int ret_idx = perm_a[idx_x & 0xff]; ret_idx = perm_b[( idx_y + ret_idx ) & 0xff]; ret_idx = perm_c[( idx_z + ret_idx ) & 0xff]; diff --git a/mathlib/vmatrix.cpp b/mathlib/vmatrix.cpp index e4aa096f..b7852a5c 100644 --- a/mathlib/vmatrix.cpp +++ b/mathlib/vmatrix.cpp @@ -18,7 +18,7 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -#ifdef _MSC_VER +#ifdef _WIN32 #pragma warning (disable : 4700) // local variable 'x' used without having been initialized #endif @@ -306,7 +306,7 @@ bool MatrixInverseGeneral(const VMatrix& src, VMatrix& dst) for(iRow=0; iRow < 4; iRow++) { // Find the row with the largest element in this column. - fLargest = 0.001f; + fLargest = 0.00001f; iLargest = -1; for(iTest=iRow; iTest < 4; iTest++) { @@ -509,7 +509,7 @@ bool VMatrix::IsRotationMatrix() const FloatMakePositive( v2.Dot(v3) ) < 0.01f; } -void VMatrix::SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles ) +static void SetupMatrixAnglesInternal( vec_t m[4][4], const QAngle & vAngles ) { float sr, sp, sy, cr, cp, cy; @@ -530,6 +530,11 @@ void VMatrix::SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles m[0][3] = 0.f; m[1][3] = 0.f; m[2][3] = 0.f; +} + +void VMatrix::SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles ) +{ + SetupMatrixAnglesInternal( m, vAngles ); // Add translation m[0][3] = origin.x; @@ -542,6 +547,21 @@ void VMatrix::SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles } +void VMatrix::SetupMatrixAngles( const QAngle &vAngles ) +{ + SetupMatrixAnglesInternal( m, vAngles ); + + // Zero everything else + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][0] = 0.0f; + m[3][1] = 0.0f; + m[3][2] = 0.0f; + m[3][3] = 1.0f; +} + + //----------------------------------------------------------------------------- // Sets matrix to identity //----------------------------------------------------------------------------- @@ -728,7 +748,7 @@ void Vector4DMultiplyPosition( const VMatrix& src1, Vector const& src2, Vector4D { // Make sure it works if src2 == dst Vector tmp; - Vector const&v = ( &src2 == &dst.AsVector3D() ) ? tmp : src2; + Vector const&v = ( &src2 == &dst.AsVector3D() ) ? static_cast(tmp) : src2; if (&src2 == &dst.AsVector3D()) { @@ -751,7 +771,7 @@ void Vector3DMultiply( const VMatrix &src1, const Vector &src2, Vector &dst ) { // Make sure it works if src2 == dst Vector tmp; - const Vector &v = (&src2 == &dst) ? tmp : src2; + const Vector &v = (&src2 == &dst) ? static_cast(tmp) : src2; if( &src2 == &dst ) { @@ -772,7 +792,7 @@ void Vector3DMultiplyPositionProjective( const VMatrix& src1, const Vector &src2 { // Make sure it works if src2 == dst Vector tmp; - const Vector &v = (&src2 == &dst) ? tmp: src2; + const Vector &v = (&src2 == &dst) ? static_cast(tmp): src2; if( &src2 == &dst ) { VectorCopy( src2, tmp ); @@ -799,7 +819,7 @@ void Vector3DMultiplyProjective( const VMatrix& src1, const Vector &src2, Vector { // Make sure it works if src2 == dst Vector tmp; - const Vector &v = (&src2 == &dst) ? tmp : src2; + const Vector &v = (&src2 == &dst) ? static_cast(tmp) : src2; if( &src2 == &dst ) { VectorCopy( src2, tmp ); @@ -852,7 +872,7 @@ void Vector3DMultiplyTranspose( const VMatrix& src1, const Vector& src2, Vector& bool srcEqualsDst = (&src2 == &dst); Vector tmp; - const Vector&v = srcEqualsDst ? tmp : src2; + const Vector&v = srcEqualsDst ? static_cast(tmp) : src2; if (srcEqualsDst) { @@ -937,7 +957,7 @@ void MatrixBuildTranslation( VMatrix& dst, const Vector &translation ) //----------------------------------------------------------------------------- void MatrixBuildRotationAboutAxis( VMatrix &dst, const Vector &vAxisOfRot, float angleDegrees ) { - MatrixBuildRotationAboutAxis( vAxisOfRot, angleDegrees, dst.As3x4() ); + MatrixBuildRotationAboutAxis( vAxisOfRot, angleDegrees, const_cast< matrix3x4_t &> ( dst.As3x4() ) ); dst[3][0] = 0; dst[3][1] = 0; dst[3][2] = 0; @@ -1233,19 +1253,29 @@ void MatrixBuildOrtho( VMatrix& dst, double left, double top, double right, doub 0.0f, 0.0f, 0.0f, 1.0f ); } +void MatrixBuildPerspectiveZRange( VMatrix& dst, double flZNear, double flZFar ) +{ + dst.m[2][0] = 0.0f; + dst.m[2][1] = 0.0f; + dst.m[2][2] = flZFar / ( flZNear - flZFar ); + dst.m[2][3] = flZNear * flZFar / ( flZNear - flZFar ); +} + void MatrixBuildPerspectiveX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar ) { - float flWidth = 2.0f * flZNear * tanf( flFovX * M_PI / 360.0f ); - float flHeight = flWidth / flAspect; - dst.Init( 2.0f * flZNear / flWidth, 0.0f, 0.0f, 0.0f, - 0.0f, 2.0f * flZNear/ flHeight, 0.0f, 0.0f, - 0.0f, 0.0f, flZFar / ( flZNear - flZFar ), flZNear * flZFar / ( flZNear - flZFar ), + float flWidthScale = 1.0f / tanf( flFovX * M_PI / 360.0f ); + float flHeightScale = flAspect * flWidthScale; + dst.Init( flWidthScale, 0.0f, 0.0f, 0.0f, + 0.0f, flHeightScale, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f ); + + MatrixBuildPerspectiveZRange ( dst, flZNear, flZFar ); } void MatrixBuildPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right ) { - float flWidth = 2.0f * flZNear * tanf( flFovX * M_PI / 360.0f ); + float flWidth = tanf( flFovX * M_PI / 360.0f ); float flHeight = flWidth / flAspect; // bottom, top, left, right are 0..1 so convert to -/2../2 @@ -1254,10 +1284,12 @@ void MatrixBuildPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAsp float flBottom = -(flHeight/2.0f) * (1.0f - bottom) + bottom * (flHeight/2.0f); float flTop = -(flHeight/2.0f) * (1.0f - top) + top * (flHeight/2.0f); - dst.Init( (2.0f * flZNear) / (flRight-flLeft), 0.0f, (flLeft+flRight)/(flRight-flLeft), 0.0f, - 0.0f, 2.0f*flZNear/(flTop-flBottom), (flTop+flBottom)/(flTop-flBottom), 0.0f, - 0.0f, 0.0f, flZFar/(flZNear-flZFar), flZNear*flZFar/(flZNear-flZFar), - 0.0f, 0.0f, -1.0f, 0.0f ); + dst.Init( 1.0f / (flRight-flLeft), 0.0f, (flLeft+flRight)/(flRight-flLeft), 0.0f, + 0.0f, 1.0f /(flTop-flBottom), (flTop+flBottom)/(flTop-flBottom), 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f ); + + MatrixBuildPerspectiveZRange ( dst, flZNear, flZFar ); } #endif // !_STATIC_LINKED || _SHARED_LIB diff --git a/public/appframework/ilaunchermgr.h b/public/appframework/ilaunchermgr.h new file mode 100644 index 00000000..431782a2 --- /dev/null +++ b/public/appframework/ilaunchermgr.h @@ -0,0 +1,162 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// ilaunchermgr.h +// +//================================================================================================== +#ifndef ILAUNCHERMGR_H +#define ILAUNCHERMGR_H + +#ifdef _WIN32 +#pragma once +#endif + +#if defined( USE_SDL ) + +#include "tier0/threadtools.h" +#include "appframework/IAppSystem.h" + +#if defined( DX_TO_GL_ABSTRACTION ) +#if !defined(DEDICATED) +#include "togl/linuxwin/glmgrbasics.h" +#include "togl/linuxwin/glmdisplay.h" +#endif + +class GLMDisplayDB; +class CShowPixelsParams; + +#if defined(DEDICATED) +typedef void *PseudoGLContextPtr; +class GLMRendererInfoFields; +#endif +#endif + +// if you rev this version also update materialsystem/cmaterialsystem.cpp CMaterialSystem::Connect as it defines the string directly +#define SDLMGR_INTERFACE_VERSION "SDLMgrInterface001" + +class CCocoaEvent; +class CStackCrawlParams; + +typedef struct SDL_Cursor SDL_Cursor; + +class ILauncherMgr : public IAppSystem +{ +public: + virtual bool Connect( CreateInterfaceFn factory ) = 0; + virtual void Disconnect() = 0; + + virtual void *QueryInterface( const char *pInterfaceName ) = 0; + + // Init, shutdown + virtual InitReturnVal_t Init() = 0; + virtual void Shutdown() = 0; + + // Create the window. + virtual bool CreateGameWindow( const char *pTitle, bool bWindowed, int width, int height ) = 0; + + virtual void IncWindowRefCount() = 0; + virtual void DecWindowRefCount() = 0; + + // Get the next N events. The function returns the number of events that were filled into your array. + virtual int GetEvents( CCocoaEvent *pEvents, int nMaxEventsToReturn, bool debugEvents = false ) = 0; +#ifdef LINUX + virtual int PeekAndRemoveKeyboardEvents( bool *pbEsc, bool *pbReturn, bool *pbSpace, bool debugEvents = false ) = 0; +#endif + + // Set the mouse cursor position. + virtual void SetCursorPosition( int x, int y ) = 0; + + virtual void SetWindowFullScreen( bool bFullScreen, int nWidth, int nHeight ) = 0; + virtual bool IsWindowFullScreen() = 0; + virtual void MoveWindow( int x, int y ) = 0; + virtual void SizeWindow( int width, int tall ) = 0; + virtual void PumpWindowsMessageLoop() = 0; + + virtual void DestroyGameWindow() = 0; + virtual void SetApplicationIcon( const char *pchAppIconFile ) = 0; + + virtual void GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta = false ) = 0; + + virtual void GetNativeDisplayInfo( int nDisplay, uint &nWidth, uint &nHeight, uint &nRefreshHz ) = 0; // Retrieve the size of the monitor (desktop) + virtual void RenderedSize( uint &width, uint &height, bool set ) = 0; // either set or retrieve rendered size value (from dxabstract) + virtual void DisplayedSize( uint &width, uint &height ) = 0; // query backbuffer size (window size whether FS or windowed) + +#if defined( DX_TO_GL_ABSTRACTION ) + virtual PseudoGLContextPtr GetMainContext() = 0; + // Get the NSGLContext for a window's main view - note this is the carbon windowref as an argument + virtual PseudoGLContextPtr GetGLContextForWindow( void* windowref ) = 0; + virtual PseudoGLContextPtr CreateExtraContext() = 0; + virtual void DeleteContext( PseudoGLContextPtr hContext ) = 0; + virtual bool MakeContextCurrent( PseudoGLContextPtr hContext ) = 0; + virtual GLMDisplayDB *GetDisplayDB( void ) = 0; + virtual void GetDesiredPixelFormatAttribsAndRendererInfo( uint **ptrOut, uint *countOut, GLMRendererInfoFields *rendInfoOut ) = 0; + virtual void ShowPixels( CShowPixelsParams *params ) = 0; +#endif + + virtual void GetStackCrawl( CStackCrawlParams *params ) = 0; + + virtual void WaitUntilUserInput( int msSleepTime ) = 0; + + virtual void *GetWindowRef() = 0; + + virtual void SetMouseVisible( bool bState ) = 0; + virtual void SetMouseCursor( SDL_Cursor *hCursor ) = 0; + virtual void SetForbidMouseGrab( bool bForbidMouseGrab ) = 0; + virtual void OnFrameRendered() = 0; + + virtual void SetGammaRamp( const uint16 *pRed, const uint16 *pGreen, const uint16 *pBlue ) = 0; + + virtual double GetPrevGLSwapWindowTime() = 0; +}; + +extern ILauncherMgr *g_pLauncherMgr; + +enum CocoaEventType_t +{ + CocoaEvent_KeyDown, + CocoaEvent_KeyUp, + CocoaEvent_MouseButtonDown, + CocoaEvent_MouseMove, + CocoaEvent_MouseButtonUp, + CocoaEvent_AppActivate, + CocoaEvent_MouseScroll, + CocoaEvent_AppQuit, + CocoaEvent_Deleted, // Event was one of the above, but has been handled and should be ignored now. +}; + +// enum values need to match bit-shifting logic in CInputSystem::UpdateMouseButtonState and +// the codes from NSEvent pressedMouseButtons, turns out the two are in agreement right now +enum CocoaMouseButton_t +{ + COCOABUTTON_LEFT = 1 << 0, + COCOABUTTON_RIGHT = 1 << 1, + COCOABUTTON_MIDDLE = 1 << 2, + COCOABUTTON_4 = 1 << 3, + COCOABUTTON_5 = 1 << 4, +}; + +enum ECocoaKeyModifier +{ + eCapsLockKey, + eShiftKey, + eControlKey, + eAltKey, // aka option + eCommandKey +}; + +class CCocoaEvent +{ +public: + CocoaEventType_t m_EventType; + int m_VirtualKeyCode; + wchar_t m_UnicodeKey; + wchar_t m_UnicodeKeyUnmodified; + uint m_ModifierKeyMask; // + int m_MousePos[2]; + int m_MouseButtonFlags; // Current state of the mouse buttons. See COCOABUTTON_xxxx. + uint m_nMouseClickCount; + int m_MouseButton; // which of the CocoaMouseButton_t buttons this is for from above +}; + +#endif // defined( USE_SDL ) + +#endif // ILAUNCHERMGR_H diff --git a/public/basehandle.h b/public/basehandle.h index 492a20b3..1e618b61 100644 --- a/public/basehandle.h +++ b/public/basehandle.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -30,7 +30,7 @@ public: CBaseHandle(); CBaseHandle( const CBaseHandle &other ); - CBaseHandle( unsigned long value ); + CBaseHandle( uint32_t value ); CBaseHandle( int iEntry, int iSerialNumber ); void Init( int iEntry, int iSerialNumber ); @@ -63,7 +63,7 @@ public: protected: // The low NUM_SERIAL_BITS hold the index. If this value is less than MAX_EDICTS, then the entity is networkable. // The high NUM_SERIAL_NUM_BITS bits are the serial number. - unsigned long m_Index; + uint32_t m_Index; }; @@ -80,7 +80,7 @@ inline CBaseHandle::CBaseHandle( const CBaseHandle &other ) m_Index = other.m_Index; } -inline CBaseHandle::CBaseHandle( unsigned long value ) +inline CBaseHandle::CBaseHandle( uint32_t value ) { m_Index = value; } @@ -92,10 +92,10 @@ inline CBaseHandle::CBaseHandle( int iEntry, int iSerialNumber ) inline void CBaseHandle::Init( int iEntry, int iSerialNumber ) { - Assert( iEntry >= 0 && iEntry < NUM_ENT_ENTRIES ); + Assert( iEntry >= 0 && (iEntry & ENT_ENTRY_MASK) == iEntry); Assert( iSerialNumber >= 0 && iSerialNumber < (1 << NUM_SERIAL_NUM_BITS) ); - m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS); + m_Index = iEntry | (iSerialNumber << NUM_SERIAL_NUM_SHIFT_BITS); } inline void CBaseHandle::Term() @@ -110,12 +110,26 @@ inline bool CBaseHandle::IsValid() const inline int CBaseHandle::GetEntryIndex() const { + // There is a hack here: due to a bug in the original implementation of the + // entity handle system, an attempt to look up an invalid entity index in + // certain cirumstances might fall through to the the mask operation below. + // This would mask an invalid index to be in fact a lookup of entity number + // NUM_ENT_ENTRIES, so invalid ent indexes end up actually looking up the + // last slot in the entities array. Since this slot is always empty, the + // lookup returns NULL and the expected behavior occurs through this unexpected + // route. + // A lot of code actually depends on this behavior, and the bug was only exposed + // after a change to NUM_SERIAL_NUM_BITS increased the number of allowable + // static props in the world. So the if-stanza below detects this case and + // retains the prior (bug-submarining) behavior. + if ( !IsValid() ) + return NUM_ENT_ENTRIES-1; return m_Index & ENT_ENTRY_MASK; } inline int CBaseHandle::GetSerialNumber() const { - return m_Index >> NUM_ENT_ENTRY_BITS; + return m_Index >> NUM_SERIAL_NUM_SHIFT_BITS; } inline int CBaseHandle::ToInt() const @@ -150,7 +164,7 @@ inline bool CBaseHandle::operator <( const CBaseHandle &other ) const inline bool CBaseHandle::operator <( const IHandleEntity *pEntity ) const { - unsigned long otherIndex = (pEntity) ? pEntity->GetRefEHandle().m_Index : INVALID_EHANDLE_INDEX; + uint32_t otherIndex = (pEntity) ? pEntity->GetRefEHandle().m_Index : INVALID_EHANDLE_INDEX; return m_Index < otherIndex; } diff --git a/public/bitvec.h b/public/bitvec.h index 9b52ac4d..633f6573 100644 --- a/public/bitvec.h +++ b/public/bitvec.h @@ -1403,7 +1403,7 @@ inline void CBitVecAccessor::operator=(int val) if(val) m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31)); else - m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31)); + m_pDWords[m_iBit >> 5] &= ~(uint32_t)(1 << (m_iBit & 31)); } inline CBitVecAccessor::operator uint32() diff --git a/public/bspfile.h b/public/bspfile.h index 36e6074c..d90ab23c 100644 --- a/public/bspfile.h +++ b/public/bspfile.h @@ -660,7 +660,7 @@ public: CDispCornerNeighbors m_CornerNeighbors[4]; // Indexed by CORNER_ defines. enum unnamed { ALLOWEDVERTS_SIZE = PAD_NUMBER( MAX_DISPVERTS, 32 ) / 32 }; - unsigned long m_AllowedVerts[ALLOWEDVERTS_SIZE]; // This is built based on the layout and sizes of our neighbors + uint32_t m_AllowedVerts[ALLOWEDVERTS_SIZE]; // This is built based on the layout and sizes of our neighbors // and tells us which vertices are allowed to be active. }; diff --git a/public/const.h b/public/const.h index 90e5d187..3a22a20d 100644 --- a/public/const.h +++ b/public/const.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -63,13 +63,13 @@ #define SIGNED_GUID_LEN 32 // Hashed CD Key (32 hex alphabetic chars + 0 terminator ) // Used for networking ehandles. -#define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 1) +#define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 2) #define NUM_ENT_ENTRIES (1 << NUM_ENT_ENTRY_BITS) #define ENT_ENTRY_MASK (NUM_ENT_ENTRIES - 1) #define INVALID_EHANDLE_INDEX 0xFFFFFFFF #define NUM_SERIAL_NUM_BITS (32 - NUM_ENT_ENTRY_BITS) - +#define NUM_SERIAL_NUM_SHIFT_BITS 16 // Networked ehandles use less bits to encode the serial number. #define NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS 10 diff --git a/public/datacache/idatacache.h b/public/datacache/idatacache.h index 029ff0e1..2a56e4ba 100644 --- a/public/datacache/idatacache.h +++ b/public/datacache/idatacache.h @@ -513,12 +513,14 @@ public: case DC_AGE_DISCARD: case DC_FLUSH_DISCARD: case DC_REMOVED: - STORAGE_TYPE *p = (STORAGE_TYPE *)notification.clientId; - p->DestroyResource(); + { + STORAGE_TYPE *p = (STORAGE_TYPE *)notification.clientId; + p->DestroyResource(); + } return true; + default: + return CDefaultDataCacheClient::HandleCacheNotification( notification ); } - - return CDefaultDataCacheClient::HandleCacheNotification( notification ); } diff --git a/public/eiface.h b/public/eiface.h index 96f403f3..0cff030c 100644 --- a/public/eiface.h +++ b/public/eiface.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -60,6 +60,7 @@ class CSteamID; class IReplayFactory; class IReplaySystem; class IServer; +class WorkshopMapDesc_t; typedef struct player_info_s player_info_t; @@ -73,7 +74,9 @@ typedef struct player_info_s player_info_t; #define DLLEXPORT /* */ #endif -#define INTERFACEVERSION_VENGINESERVER "VEngineServer023" +#define INTERFACEVERSION_VENGINESERVER_VERSION_21 "VEngineServer021" +#define INTERFACEVERSION_VENGINESERVER_VERSION_22 "VEngineServer022" +#define INTERFACEVERSION_VENGINESERVER "VEngineServer023" #define INTERFACEVERSION_VENGINESERVER_INT 23 struct bbox_t @@ -90,16 +93,16 @@ abstract_class IVEngineServer public: // Tell engine to change level ( "changelevel s1\n" or "changelevel2 s1 s2\n" ) virtual void ChangeLevel( const char *s1, const char *s2 ) = 0; - + // Ask engine whether the specified map is a valid map file (exists and has valid version number). virtual int IsMapValid( const char *filename ) = 0; - + // Is this a dedicated server? virtual bool IsDedicatedServer( void ) = 0; - + // Is in Hammer editing mode? virtual int IsInEditMode( void ) = 0; - + // Add to the server/client lookup/precache table, the specified string is given a unique index // NOTE: The indices for PrecacheModel are 1 based // a 0 returned from those methods indicates the model or sound was not correctly precached @@ -340,9 +343,6 @@ public: // even though we may not have waited enough time virtual void AllowImmediateEdictReuse( ) = 0; - // Returns true if the engine is an internal build. i.e. is using the internal bugreporter. - virtual bool IsInternalBuild( void ) = 0; - virtual IChangeInfoAccessor *GetChangeAccessor( const edict_t *pEdict ) = 0; // Name of most recently load .sav file @@ -410,8 +410,6 @@ public: // Server version from the steam.inf, this will be compared to the GC version virtual int GetServerVersion() const = 0; - // Only in VEngineServer022 and later - // Get sv.GetTime() virtual float GetServerTime() const = 0; @@ -447,14 +445,15 @@ public: virtual IReplaySystem *GetReplay() = 0; }; -#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_4 "ServerGameDLL004" -#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_5 "ServerGameDLL005" -#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_6 "ServerGameDLL006" -#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_7 "ServerGameDLL007" +// These only differ in new items added to the end +typedef IVEngineServer IVEngineServer021; +typedef IVEngineServer IVEngineServer022; + #define INTERFACEVERSION_SERVERGAMEDLL_VERSION_8 "ServerGameDLL008" #define INTERFACEVERSION_SERVERGAMEDLL_VERSION_9 "ServerGameDLL009" -#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL010" -#define INTERFACEVERSION_SERVERGAMEDLL_INT 10 +#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_10 "ServerGameDLL010" +#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL012" +#define INTERFACEVERSION_SERVERGAMEDLL_INT 12 class IServerGCLobby; @@ -630,6 +629,8 @@ public: // Called to see if the game server is okay with a manual changelevel or map command virtual bool IsManualMapChangeOkay( const char **pszReason ) = 0; + + virtual bool GetWorkshopMap( unsigned int unk, WorkshopMapDesc_t *pMapDesc ) = 0; }; typedef IServerGameDLL IServerGameDLL008; diff --git a/public/engine/ivdebugoverlay.h b/public/engine/ivdebugoverlay.h index f1e404f9..6b77bf30 100644 --- a/public/engine/ivdebugoverlay.h +++ b/public/engine/ivdebugoverlay.h @@ -39,6 +39,7 @@ public: virtual void AddTextOverlay(const Vector& origin, float duration, const char *format, ...) = 0; virtual void AddTextOverlay(const Vector& origin, int line_offset, float duration, const char *format, ...) = 0; virtual void AddScreenTextOverlay(float flXPos, float flYPos,float flDuration, int r, int g, int b, int a, const char *text) = 0; + virtual void AddScreenTextOverlay(float flXPos, float flYPos, int line_offset, float flDuration, int r, int g, int b, int a, const char *text) = 0; virtual void AddSweptBoxOverlay(const Vector& start, const Vector& end, const Vector& mins, const Vector& max, const QAngle & angles, int r, int g, int b, int a, float flDuration) = 0; virtual void AddGridOverlay(const Vector& origin) = 0; virtual int ScreenPosition(const Vector& point, Vector& screen) = 0; diff --git a/public/filesystem.h b/public/filesystem.h index 986a8be7..42c3eead 100644 --- a/public/filesystem.h +++ b/public/filesystem.h @@ -420,7 +420,7 @@ public: virtual bool IsFileWritable( char const *pFileName, const char *pPathID = 0 ) = 0; virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID = 0 ) = 0; - virtual long GetFileTime( const char *pFileName, const char *pPathID = 0 ) = 0; + virtual int32_t GetFileTime( const char *pFileName, const char *pPathID = 0 ) = 0; //-------------------------------------------------------- // Reads/writes files to utlbuffers. Use this for optimal read performance when doing open/read/close @@ -505,7 +505,7 @@ public: // File I/O and info virtual bool IsDirectory( const char *pFileName, const char *pathID = 0 ) = 0; - virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) = 0; + virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, int32_t fileTime ) = 0; //-------------------------------------------------------- // Open file operations @@ -716,7 +716,7 @@ public: virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, char *pRelative, int maxlen ) = 0; virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0; - virtual long GetPathTime( const char *pPath, const char *pPathID ) = 0; + virtual int32_t GetPathTime( const char *pPath, const char *pPathID ) = 0; virtual DVDMode_t GetDVDMode() = 0; diff --git a/public/filesystem/IQueuedLoader.h b/public/filesystem/IQueuedLoader.h index 17a80119..a167cec8 100644 --- a/public/filesystem/IQueuedLoader.h +++ b/public/filesystem/IQueuedLoader.h @@ -14,6 +14,8 @@ #include "tier0/platform.h" #include "appframework/IAppSystem.h" +class CFunctor; + enum LoaderError_t { LOADERERROR_NONE = 0, @@ -30,6 +32,8 @@ enum LoaderPriority_t typedef void ( *QueuedLoaderCallback_t )( void *pContext, void *pContext2, const void *pData, int nSize, LoaderError_t loaderError ); +typedef void ( *DynamicResourceCallback_t )( const char *pFilename, void *pContext, void *pContext2 ); + struct LoaderJob_t { LoaderJob_t() @@ -106,7 +110,7 @@ public: #define LOADER_DETAIL_LATECOMPLETIONS (1<<2) #define LOADER_DETAIL_PURGES (1<<3) -#define QUEUEDLOADER_INTERFACE_VERSION "QueuedLoaderVersion001" +#define QUEUEDLOADER_INTERFACE_VERSION "QueuedLoaderVersion004" abstract_class IQueuedLoader : public IAppSystem { public: @@ -122,6 +126,11 @@ public: // injects a resource into the map's reslist, rejected if not understood virtual void AddMapResource( const char *pFilename ) = 0; + // dynamically load a map resource + virtual void DynamicLoadMapResource( const char *pFilename, DynamicResourceCallback_t pCallback, void *pContext, void *pContext2 ) = 0; + virtual void QueueDynamicLoadFunctor( CFunctor* pFunctor ) = 0; + virtual bool CompleteDynamicLoad() = 0; + // callback is asynchronous virtual bool ClaimAnonymousJob( const char *pFilename, QueuedLoaderCallback_t pCallback, void *pContext, void *pContext2 = NULL ) = 0; // provides data if loaded, caller owns data @@ -134,6 +143,8 @@ public: // callers can expect that jobs are not immediately started when batching virtual bool IsBatching() const = 0; + virtual bool IsDynamic() const = 0; + // callers can conditionalize operational spew virtual int GetSpewDetail() const = 0; diff --git a/public/filesystem_init.cpp b/public/filesystem_init.cpp index 022522ad..6b97faf9 100644 --- a/public/filesystem_init.cpp +++ b/public/filesystem_init.cpp @@ -1,4 +1,4 @@ -//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -6,21 +6,24 @@ #undef PROTECTED_THINGS_ENABLE #undef PROTECT_FILEIO_FUNCTIONS +#ifndef POSIX +#undef fopen +#endif #if defined( _WIN32 ) && !defined( _X360 ) #include #include #include #include -#elif defined( _LINUX ) || defined( __APPLE__ ) +#elif defined( POSIX ) #include -#define _putenv putenv #define _chdir chdir #define _access access #endif #include #include #include "tier1/strtools.h" +#include "tier1/utlbuffer.h" #include "filesystem_init.h" #include "tier0/icommandline.h" #include "KeyValues.h" @@ -83,7 +86,7 @@ public: if ( pValue ) { m_bExisted = true; - m_OriginalValue.SetSize( strlen( pValue ) + 1 ); + m_OriginalValue.SetSize( Q_strlen( pValue ) + 1 ); memcpy( m_OriginalValue.Base(), pValue, m_OriginalValue.Count() ); } else @@ -144,16 +147,24 @@ public: Q_vsnprintf( valueString, sizeof( valueString ), pValue, marker ); va_end( marker ); +#ifdef WIN32 char str[4096]; Q_snprintf( str, sizeof( str ), "%s=%s", m_pVarName, valueString ); _putenv( str ); +#else + setenv( m_pVarName, valueString, 1 ); +#endif } void ClearValue() { +#ifdef WIN32 char str[512]; Q_snprintf( str, sizeof( str ), "%s=", m_pVarName ); _putenv( str ); +#else + setenv( m_pVarName, "", 1 ); +#endif } private: @@ -213,6 +224,7 @@ CFSSearchPathsInit::CFSSearchPathsInit() m_pDirectoryName = NULL; m_pLanguage = NULL; m_ModPath[0] = 0; + m_bMountHDContent = m_bLowViolence = false; } @@ -248,47 +260,6 @@ const char *FileSystem_GetLastErrorString() } -void AddLanguageGameDir( IFileSystem *pFileSystem, const char *pLocation, const char *pLanguage ) -{ - if ( IsX360() ) - { - // 360 does not use this path for localization - return; - } - -#if !defined( SWDS ) - char temp[MAX_PATH]; - Q_snprintf( temp, sizeof(temp), "%s_%s", pLocation, pLanguage ); - pFileSystem->AddSearchPath( temp, "GAME", PATH_ADD_TO_TAIL ); - - if ( !pFileSystem->IsSteam() ) - { - // also look in "..\localization\" if not running Steam - char baseDir[MAX_PATH]; - char *tempPtr = NULL, *gameDir = NULL; - - Q_strncpy( baseDir, pLocation, sizeof(baseDir) ); - tempPtr = Q_strstr( baseDir, "\\game\\" ); - - if ( tempPtr ) - { - gameDir = tempPtr + Q_strlen( "\\game\\" ); - *tempPtr = 0; - Q_snprintf( temp, sizeof(temp), "%s%clocalization%c%s_%s", baseDir, CORRECT_PATH_SEPARATOR, CORRECT_PATH_SEPARATOR, gameDir, pLanguage ); - pFileSystem->AddSearchPath( temp, "GAME", PATH_ADD_TO_TAIL ); - } - } -#endif -} - - -void AddGameBinDir( IFileSystem *pFileSystem, const char *pLocation ) -{ - char temp[MAX_PATH]; - Q_snprintf( temp, sizeof(temp), "%s%cbin", pLocation, CORRECT_PATH_SEPARATOR ); - pFileSystem->AddSearchPath( temp, "GAMEBIN", PATH_ADD_TO_TAIL ); -} - KeyValues* ReadKeyValuesFile( const char *pFilename ) { // Read in the gameinfo.txt file and null-terminate it. @@ -376,7 +347,8 @@ bool FileSystem_GetExecutableDir( char *exedir, int exeDirLen ) Q_StrRight( exedir, 4, ext, sizeof( ext ) ); if ( ext[0] != CORRECT_PATH_SEPARATOR || Q_stricmp( ext+1, "bin" ) != 0 ) { - Q_strncat( exedir, "\\bin", exeDirLen, COPY_ALL_CHARACTERS ); + Q_strncat( exedir, CORRECT_PATH_SEPARATOR_S, exeDirLen, COPY_ALL_CHARACTERS ); + Q_strncat( exedir, "bin", exeDirLen, COPY_ALL_CHARACTERS ); Q_FixSlashes( exedir ); } @@ -489,124 +461,73 @@ FSReturnCode_t LoadGameInfoFile( return FS_OK; } -// checks the registry for the low violence setting -// Check "HKEY_CURRENT_USER\Software\Valve\Source\Settings" and "User Token 2" or "User Token 3" -bool IsLowViolenceBuild( void ) -{ -#if defined(_WIN32) - HKEY hKey; - char szValue[64]; - unsigned long len = sizeof(szValue) - 1; - bool retVal = false; - - if ( IsPC() && RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Valve\\Source\\Settings", NULL, KEY_READ, &hKey) == ERROR_SUCCESS ) - { - // User Token 2 - if ( RegQueryValueEx( hKey, "User Token 2", NULL, NULL, (unsigned char*)szValue, &len ) == ERROR_SUCCESS ) - { - if ( Q_strlen( szValue ) > 0 ) - { - retVal = true; - } - } - - if ( !retVal ) - { - // reset "len" for the next check - len = sizeof(szValue) - 1; - - // User Token 3 - if ( RegQueryValueEx( hKey, "User Token 3", NULL, NULL, (unsigned char*)szValue, &len ) == ERROR_SUCCESS ) - { - if ( Q_strlen( szValue ) > 0 ) - { - retVal = true; - } - } - } - - RegCloseKey(hKey); - } - - return retVal; -#elif _LINUX - return false; -#else - #error "Fix me" -#endif -} static void FileSystem_AddLoadedSearchPath( CFSSearchPathsInit &initInfo, const char *pPathID, - bool *bFirstGamePath, - const char *pBaseDir, - const char *pLocation, + const char *fullLocationPath, bool bLowViolence ) { - char fullLocationPath[MAX_PATH]; - Q_MakeAbsolutePath( fullLocationPath, sizeof( fullLocationPath ), pLocation, pBaseDir ); - // Now resolve any ./'s. - V_FixSlashes( fullLocationPath ); - if ( !V_RemoveDotSlashes( fullLocationPath ) ) - Error( "FileSystem_AddLoadedSearchPath - Can't resolve pathname for '%s'", fullLocationPath ); - - // Add language, mod, and gamebin search paths automatically. - if ( Q_stricmp( pPathID, "game" ) == 0 ) + // Check for mounting LV game content in LV builds only + if ( V_stricmp( pPathID, "game_lv" ) == 0 ) { - // add the low violence path - if ( bLowViolence ) - { - char szPath[MAX_PATH]; - Q_snprintf( szPath, sizeof(szPath), "%s_lv", fullLocationPath ); - initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL ); - } - - // add the language path - if ( initInfo.m_pLanguage ) - { - AddLanguageGameDir( initInfo.m_pFileSystem, fullLocationPath, initInfo.m_pLanguage ); - } + // Not in LV build, don't mount + if ( !initInfo.m_bLowViolence ) + return; + + // Mount, as a game path + pPathID = "game"; + } + + // Check for mounting HD game content if enabled + if ( V_stricmp( pPathID, "game_hd" ) == 0 ) + { + + // Not in LV build, don't mount + if ( !initInfo.m_bMountHDContent ) + return; + + // Mount, as a game path + pPathID = "game"; + } + + + // Special processing for ordinary game folders + if ( V_stristr( fullLocationPath, ".vpk" ) == NULL && Q_stricmp( pPathID, "game" ) == 0 ) + { if ( CommandLine()->FindParm( "-tempcontent" ) != 0 ) { char szPath[MAX_PATH]; Q_snprintf( szPath, sizeof(szPath), "%s_tempcontent", fullLocationPath ); initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL ); } + } - // mark the first "game" dir as the "MOD" dir - if ( *bFirstGamePath ) - { - *bFirstGamePath = false; - initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, "MOD", PATH_ADD_TO_TAIL ); - Q_strncpy( initInfo.m_ModPath, fullLocationPath, sizeof( initInfo.m_ModPath ) ); - } - // add the game bin - AddGameBinDir( initInfo.m_pFileSystem, fullLocationPath ); + if ( initInfo.m_pLanguage && + Q_stricmp( initInfo.m_pLanguage, "english" ) && + V_strstr( fullLocationPath, "_english" ) != NULL ) + { + char szPath[MAX_PATH]; + char szLangString[MAX_PATH]; + + // Need to add a language version of this path first + + Q_snprintf( szLangString, sizeof(szLangString), "_%s", initInfo.m_pLanguage); + V_StrSubst( fullLocationPath, "_english", szLangString, szPath, sizeof( szPath ), true ); + initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL ); } initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, pPathID, PATH_ADD_TO_TAIL ); } - -bool FileSystem_IsHldsUpdateToolDedicatedServer() +static int SortStricmp( char * const * sz1, char * const * sz2 ) { - // To determine this, we see if the directory our executable was launched from is "orangebox". - // We only are under "orangebox" if we're run from hldsupdatetool. - char baseDir[MAX_PATH]; - if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) - return false; - - V_FixSlashes( baseDir ); - V_StripTrailingSlash( baseDir ); - const char *pLastDir = V_UnqualifiedFileName( baseDir ); - return ( pLastDir && V_stricmp( pLastDir, "orangebox" ) == 0 ); + return V_stricmp( *sz1, *sz2 ); } - FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ) { if ( !initInfo.m_pFileSystem || !initInfo.m_pDirectoryName ) @@ -622,23 +543,41 @@ FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ) if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); - initInfo.m_ModPath[0] = 0; + // The MOD directory is always the one that contains gameinfo.txt + Q_strncpy( initInfo.m_ModPath, initInfo.m_pDirectoryName, sizeof( initInfo.m_ModPath ) ); #define GAMEINFOPATH_TOKEN "|gameinfo_path|" #define BASESOURCEPATHS_TOKEN "|all_source_engine_paths|" - bool bLowViolence = IsLowViolenceBuild(); - bool bFirstGamePath = true; - + const char *pszExtraSearchPath = CommandLine()->ParmValue( "-insert_search_path" ); + if ( pszExtraSearchPath ) + { + CUtlStringList vecPaths; + V_SplitString( pszExtraSearchPath, ",", vecPaths ); + FOR_EACH_VEC( vecPaths, idxExtraPath ) + { + char szAbsSearchPath[MAX_PATH]; + Q_StripPrecedingAndTrailingWhitespace( vecPaths[ idxExtraPath ] ); + V_MakeAbsolutePath( szAbsSearchPath, sizeof( szAbsSearchPath ), vecPaths[ idxExtraPath ], baseDir ); + V_FixSlashes( szAbsSearchPath ); + if ( !V_RemoveDotSlashes( szAbsSearchPath ) ) + Error( "Bad -insert_search_path - Can't resolve pathname for '%s'", szAbsSearchPath ); + V_StripTrailingSlash( szAbsSearchPath ); + FileSystem_AddLoadedSearchPath( initInfo, "GAME", szAbsSearchPath, false ); + FileSystem_AddLoadedSearchPath( initInfo, "MOD", szAbsSearchPath, false ); + } + } + + bool bLowViolence = initInfo.m_bLowViolence; for ( KeyValues *pCur=pSearchPaths->GetFirstValue(); pCur; pCur=pCur->GetNextValue() ) { - const char *pPathID = pCur->GetName(); const char *pLocation = pCur->GetString(); - + const char *pszBaseDir = baseDir; + if ( Q_stristr( pLocation, GAMEINFOPATH_TOKEN ) == pLocation ) { pLocation += strlen( GAMEINFOPATH_TOKEN ); - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, initInfo.m_pDirectoryName, pLocation, bLowViolence ); + pszBaseDir = initInfo.m_pDirectoryName; } else if ( Q_stristr( pLocation, BASESOURCEPATHS_TOKEN ) == pLocation ) { @@ -650,26 +589,117 @@ FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ) // We need a special identifier in the gameinfo.txt here because the base hl2 folder exists in different places. // In the case of a game or a Steam-launched dedicated server, all the necessary prior engine content is mapped in with the Steam depots, // so we can just use the path as-is. - - // In the case of an hldsupdatetool dedicated server, the base hl2 folder is "..\..\hl2" (since we're up in the 'orangebox' folder). - pLocation += strlen( BASESOURCEPATHS_TOKEN ); + } - // Add the Orange-box path (which also will include whatever the depots mapped in as well if we're - // running a Steam-launched app). - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, pLocation, bLowViolence ); + CUtlStringList vecFullLocationPaths; + char szAbsSearchPath[MAX_PATH]; + V_MakeAbsolutePath( szAbsSearchPath, sizeof( szAbsSearchPath ), pLocation, pszBaseDir ); - if ( FileSystem_IsHldsUpdateToolDedicatedServer() ) - { - // If we're using the hldsupdatetool dedicated server, then go up a directory to get the ep1-era files too. - char ep1EraPath[MAX_PATH]; - V_snprintf( ep1EraPath, sizeof( ep1EraPath ), "..%c%s", CORRECT_PATH_SEPARATOR, pLocation ); - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, ep1EraPath, bLowViolence ); - } + // Now resolve any ./'s. + V_FixSlashes( szAbsSearchPath ); + if ( !V_RemoveDotSlashes( szAbsSearchPath ) ) + Error( "FileSystem_AddLoadedSearchPath - Can't resolve pathname for '%s'", szAbsSearchPath ); + V_StripTrailingSlash( szAbsSearchPath ); + + // Don't bother doing any wildcard expansion unless it has wildcards. This avoids the weird + // thing with xxx_dir.vpk files being referred to simply as xxx.vpk. + if ( V_stristr( pLocation, "?") == NULL && V_stristr( pLocation, "*") == NULL ) + { + vecFullLocationPaths.CopyAndAddToTail( szAbsSearchPath ); } else { - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, pLocation, bLowViolence ); + FileFindHandle_t findHandle = 0; + const char *pszFoundShortName = initInfo.m_pFileSystem->FindFirst( szAbsSearchPath, &findHandle ); + if ( pszFoundShortName ) + { + do + { + + // We only know how to mount VPK's and directories + if ( pszFoundShortName[0] != '.' && ( initInfo.m_pFileSystem->FindIsDirectory( findHandle ) || V_stristr( pszFoundShortName, ".vpk" ) ) ) + { + char szAbsName[MAX_PATH]; + V_ExtractFilePath( szAbsSearchPath, szAbsName, sizeof( szAbsName ) ); + V_AppendSlash( szAbsName, sizeof(szAbsName) ); + V_strcat_safe( szAbsName, pszFoundShortName ); + + vecFullLocationPaths.CopyAndAddToTail( szAbsName ); + + // Check for a common mistake + if ( + !V_stricmp( pszFoundShortName, "materials" ) + || !V_stricmp( pszFoundShortName, "maps" ) + || !V_stricmp( pszFoundShortName, "resource" ) + || !V_stricmp( pszFoundShortName, "scripts" ) + || !V_stricmp( pszFoundShortName, "sound" ) + || !V_stricmp( pszFoundShortName, "models" ) ) + { + + char szReadme[MAX_PATH]; + V_ExtractFilePath( szAbsSearchPath, szReadme, sizeof( szReadme ) ); + V_AppendSlash( szReadme, sizeof(szReadme) ); + V_strcat_safe( szReadme, "readme.txt" ); + + Error( + "Tried to add %s as a search path.\n" + "\nThis is probably not what you intended.\n" + "\nCheck %s for more info\n", + szAbsName, szReadme ); + } + + } + pszFoundShortName = initInfo.m_pFileSystem->FindNext( findHandle ); + } while ( pszFoundShortName ); + initInfo.m_pFileSystem->FindClose( findHandle ); + } + + // Sort alphabetically. Also note that this will put + // all the xxx_000.vpk packs just before the corresponding + // xxx_dir.vpk + vecFullLocationPaths.Sort( SortStricmp ); + + // Now for any _dir.vpk files, remove the _nnn.vpk ones. + int idx = vecFullLocationPaths.Count()-1; + while ( idx > 0 ) + { + char szTemp[ MAX_PATH ]; + V_strcpy_safe( szTemp, vecFullLocationPaths[ idx ] ); + --idx; + + char *szDirVpk = V_stristr( szTemp, "_dir.vpk" ); + if ( szDirVpk != NULL ) + { + *szDirVpk = '\0'; + while ( idx >= 0 ) + { + char *pszPath = vecFullLocationPaths[ idx ]; + if ( V_stristr( pszPath, szTemp ) != pszPath ) + break; + delete pszPath; + vecFullLocationPaths.Remove( idx ); + --idx; + } + } + } + } + + // Parse Path ID list + CUtlStringList vecPathIDs; + V_SplitString( pCur->GetName(), "+", vecPathIDs ); + FOR_EACH_VEC( vecPathIDs, idxPathID ) + { + Q_StripPrecedingAndTrailingWhitespace( vecPathIDs[ idxPathID ] ); + } + + // Mount them. + FOR_EACH_VEC( vecFullLocationPaths, idxLocation ) + { + FOR_EACH_VEC( vecPathIDs, idxPathID ) + { + FileSystem_AddLoadedSearchPath( initInfo, vecPathIDs[ idxPathID ], vecFullLocationPaths[ idxLocation ], bLowViolence ); + } } } @@ -679,15 +709,13 @@ FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ) // when people forget to specify a search path. initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "executable_path", true ); initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "gamebin", true ); + initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "download", true ); initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "mod", true ); - if ( initInfo.m_ModPath[0] != 0 ) - { - // Add the write path last. - initInfo.m_pFileSystem->AddSearchPath( initInfo.m_ModPath, "DEFAULT_WRITE_PATH", PATH_ADD_TO_TAIL ); - } + initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "game_write", true ); + initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "mod_write", true ); #ifdef _DEBUG - initInfo.m_pFileSystem->PrintSearchPaths(); + // initInfo.m_pFileSystem->PrintSearchPaths(); #endif return FS_OK; @@ -954,60 +982,6 @@ bool DoesPathExistAlready( const char *pPathEnvVar, const char *pTestPath ) } } -FSReturnCode_t SetSteamInstallPath( char *steamInstallPath, int steamInstallPathLen, CSteamEnvVars &steamEnvVars, bool bErrorsAsWarnings ) -{ - if ( IsConsole() ) - { - // consoles don't use steam - return FS_MISSING_STEAM_DLL; - } - - // Start at our bin directory and move up until we find a directory with steam.dll in it. - char executablePath[MAX_PATH]; - if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) - { - if ( bErrorsAsWarnings ) - { - Warning( "SetSteamInstallPath: FileSystem_GetExecutableDir failed.\n" ); - return FS_INVALID_PARAMETERS; - } - else - { - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - } - } - - Q_strncpy( steamInstallPath, executablePath, steamInstallPathLen ); - while ( 1 ) - { - // Ignore steamapp.cfg here in case they're debugging. We still need to know the real steam path so we can find their username. - // find - if ( DoesFileExistIn( steamInstallPath, "steam.dll" ) && !DoesFileExistIn( steamInstallPath, "steamapp.cfg" ) ) - break; - - if ( !Q_StripLastDir( steamInstallPath, steamInstallPathLen ) ) - { - if ( bErrorsAsWarnings ) - { - Warning( "Can't find steam.dll relative to executable path: %s.\n", executablePath ); - return FS_MISSING_STEAM_DLL; - } - else - { - return SetupFileSystemError( false, FS_MISSING_STEAM_DLL, "Can't find steam.dll relative to executable path: %s.", executablePath ); - } - } - } - - // Also, add the install path to their PATH environment variable, so filesystem_steam.dll can get to steam.dll. - char szPath[ 8192 ]; - steamEnvVars.m_Path.GetValue( szPath, sizeof( szPath ) ); - if ( !DoesPathExistAlready( szPath, steamInstallPath ) ) - { - steamEnvVars.m_Path.SetValue( "%s;%s", szPath, steamInstallPath ); - } - return FS_OK; -} FSReturnCode_t GetSteamCfgPath( char *steamCfgPath, int steamCfgPathLen ) { @@ -1087,53 +1061,6 @@ void SetSteamUserPassphrase( KeyValues *pSteamInfo, CSteamEnvVars &steamEnvVars } } -void SetSteamAppId( KeyValues *pFileSystemInfo, const char *pGameInfoDirectory, CSteamEnvVars &steamEnvVars ) -{ - // SteamAppId is in gameinfo.txt->FileSystem->FileSystemInfo_Steam->SteamAppId. - int iAppId = pFileSystemInfo->GetInt( "SteamAppId", -1 ); - if ( iAppId == -1 ) - Error( "Missing SteamAppId in %s\\%s.", pGameInfoDirectory, GAMEINFO_FILENAME ); - - steamEnvVars.m_SteamAppId.SetValue( "%d", iAppId ); -} - -FSReturnCode_t SetupSteamStartupEnvironment( KeyValues *pFileSystemInfo, const char *pGameInfoDirectory, CSteamEnvVars &steamEnvVars ) -{ - // Ok, we're going to run Steam. See if they have SteamInfo.txt. If not, we'll try to deduce what we can. - char steamInfoFile[MAX_PATH]; - Q_strncpy( steamInfoFile, pGameInfoDirectory, sizeof( steamInfoFile ) ); - Q_AppendSlash( steamInfoFile, sizeof( steamInfoFile ) ); - Q_strncat( steamInfoFile, "steaminfo.txt", sizeof( steamInfoFile ), COPY_ALL_CHARACTERS ); - KeyValues *pSteamInfo = ReadKeyValuesFile( steamInfoFile ); - - char steamInstallPath[MAX_PATH]; - FSReturnCode_t ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, false ); - if ( ret != FS_OK ) - return ret; - - SetSteamAppUser( pSteamInfo, steamInstallPath, steamEnvVars ); - SetSteamUserPassphrase( pSteamInfo, steamEnvVars ); - SetSteamAppId( pFileSystemInfo, pGameInfoDirectory, steamEnvVars ); - - if ( pSteamInfo ) - pSteamInfo->deleteThis(); - - return FS_OK; -} - -FSReturnCode_t GetSteamExtraAppId( const char *pDirectoryName, int *nExtraAppId ) -{ - // Now, load gameinfo.txt (to make sure it's there) - KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; - FSReturnCode_t ret = LoadGameInfoFile( pDirectoryName, pMainFile, pFileSystemInfo, pSearchPaths ); - if ( ret != FS_OK ) - return ret; - - *nExtraAppId = pFileSystemInfo->GetInt( "ToolsAppId", -1 ); - pMainFile->deleteThis(); - return FS_OK; -} - FSReturnCode_t FileSystem_SetBasePaths( IFileSystem *pFileSystem ) { pFileSystem->RemoveSearchPaths( "EXECUTABLE_PATH" ); @@ -1143,6 +1070,12 @@ FSReturnCode_t FileSystem_SetBasePaths( IFileSystem *pFileSystem ) return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); pFileSystem->AddSearchPath( executablePath, "EXECUTABLE_PATH" ); + + if ( !FileSystem_GetBaseDir( executablePath, sizeof( executablePath ) ) ) + return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); + + pFileSystem->AddSearchPath( executablePath, "BASE_PATH" ); + return FS_OK; } @@ -1158,41 +1091,31 @@ FSReturnCode_t FileSystem_GetFileSystemDLLName( char *pFileSystemDLL, int nMaxLe char executablePath[MAX_PATH]; if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - -#if defined( _WIN32 ) && !defined( _X360 ) - // If filesystem_stdio.dll is missing or -steam is specified, then load filesystem_steam.dll. - // There are two command line parameters for Steam: - // 1) -steam (runs Steam in remote filesystem mode; requires Steam backend) - // 2) -steamlocal (runs Steam in local filesystem mode (all content off HDD) - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_stdio.dll", executablePath, CORRECT_PATH_SEPARATOR ); - if ( CommandLine()->FindParm( "-steam" ) || CommandLine()->FindParm( "-steamlocal" ) || _access( pFileSystemDLL, 0 ) != 0 ) - { - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_steam.dll", executablePath, CORRECT_PATH_SEPARATOR ); - bSteam = true; - } -#elif defined( _X360 ) - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_stdio.dll", executablePath, CORRECT_PATH_SEPARATOR ); -#elif defined( _LINUX ) - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_i486.so", executablePath, CORRECT_PATH_SEPARATOR ); -#else - #error "define a filesystem dll name" -#endif + + // Assume we'll use local files + Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_stdio" DLL_EXT_STRING, executablePath, CORRECT_PATH_SEPARATOR ); + + #if !defined( _X360 ) + + // Use filsystem_steam if it exists? + #if defined( OSX ) || defined( LINUX ) + struct stat statBuf; + #endif + if ( + #if defined( OSX ) || defined( LINUX ) + stat( pFileSystemDLL, &statBuf ) != 0 + #else + _access( pFileSystemDLL, 0 ) != 0 + #endif + ) { + Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_steam" DLL_EXT_STRING, executablePath, CORRECT_PATH_SEPARATOR ); + bSteam = true; + } + #endif return FS_OK; } -//----------------------------------------------------------------------------- -// Sets up the steam.dll install path in our PATH env var (so you can then just -// LoadLibrary() on filesystem_steam.dll without having to copy steam.dll anywhere special ) -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_SetupSteamInstallPath() -{ - CSteamEnvVars steamEnvVars; - char steamInstallPath[MAX_PATH]; - FSReturnCode_t ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, true ); - steamEnvVars.m_Path.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - return ret; -} //----------------------------------------------------------------------------- // Sets up the steam environment + gets back the gameinfo.txt path @@ -1205,45 +1128,13 @@ FSReturnCode_t FileSystem_SetupSteamEnvironment( CFSSteamSetupInfo &fsInfo ) return ret; // This is so that processes spawned by this application will have the same VPROJECT +#ifdef WIN32 char pEnvBuf[MAX_PATH+32]; Q_snprintf( pEnvBuf, sizeof(pEnvBuf), "%s=%s", GAMEDIR_TOKEN, fsInfo.m_GameInfoPath ); _putenv( pEnvBuf ); - - CSteamEnvVars steamEnvVars; - if ( fsInfo.m_bSteam ) - { - if ( fsInfo.m_bToolsMode ) - { - // Now, load gameinfo.txt (to make sure it's there) - KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; - ret = LoadGameInfoFile( fsInfo.m_GameInfoPath, pMainFile, pFileSystemInfo, pSearchPaths ); - if ( ret != FS_OK ) - return ret; - - // If filesystem_stdio.dll is missing or -steam is specified, then load filesystem_steam.dll. - // There are two command line parameters for Steam: - // 1) -steam (runs Steam in remote filesystem mode; requires Steam backend) - // 2) -steamlocal (runs Steam in local filesystem mode (all content off HDD) - - // Setup all the environment variables related to Steam so filesystem_steam.dll knows how to initialize Steam. - ret = SetupSteamStartupEnvironment( pFileSystemInfo, fsInfo.m_GameInfoPath, steamEnvVars ); - if ( ret != FS_OK ) - return ret; - - steamEnvVars.m_SteamAppId.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - - // We're done with main file - pMainFile->deleteThis(); - } - else if ( fsInfo.m_bSetSteamDLLPath ) - { - // This is used by the engine to automatically set the path to their steam.dll when running the engine, - // so they can debug it without having to copy steam.dll up into their hl2.exe folder. - char steamInstallPath[MAX_PATH]; - ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, true ); - steamEnvVars.m_Path.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - } - } +#else + setenv( GAMEDIR_TOKEN, fsInfo.m_GameInfoPath, 1 ); +#endif return FS_OK; } @@ -1287,33 +1178,33 @@ FSReturnCode_t FileSystem_MountContent( CFSMountContentInfo &mountContentInfo ) // This part is Steam-only. if ( mountContentInfo.m_pFileSystem->IsSteam() ) { - // Find out the "extra app id". This is for tools, which want to mount a base app's filesystem - // like HL2, then mount the SDK content (tools materials and models, etc) in addition. - int nExtraAppId = -1; - if ( mountContentInfo.m_bToolsMode ) - { - FSReturnCode_t ret = GetSteamExtraAppId( mountContentInfo.m_pDirectoryName, &nExtraAppId ); - if ( ret != FS_OK ) - return ret; - } + return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "Should not be using filesystem_steam anymore!" ); - // Set our working directory temporarily so Steam can remember it. - // This is what Steam strips off absolute filenames like c:\program files\valve\steam\steamapps\username\sourcesdk - // to get to the relative part of the path. - char baseDir[MAX_PATH], oldWorkingDir[MAX_PATH]; - if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); - - Q_getwd( oldWorkingDir, sizeof( oldWorkingDir ) ); - _chdir( baseDir ); - - // Filesystem_tools needs to add dependencies in here beforehand. - FilesystemMountRetval_t retVal = mountContentInfo.m_pFileSystem->MountSteamContent( nExtraAppId ); - - _chdir( oldWorkingDir ); - - if ( retVal != FILESYSTEM_MOUNT_OK ) - return SetupFileSystemError( true, FS_UNABLE_TO_INIT, "Unable to mount Steam content in the file system" ); +// // Find out the "extra app id". This is for tools, which want to mount a base app's filesystem +// // like HL2, then mount the SDK content (tools materials and models, etc) in addition. +// int nExtraAppId = -1; +// if ( mountContentInfo.m_bToolsMode ) +// { +// // !FIXME! Here we need to mount the tools content (VPK's) in some way...? +// } +// +// // Set our working directory temporarily so Steam can remember it. +// // This is what Steam strips off absolute filenames like c:\program files\valve\steam\steamapps\username\sourcesdk +// // to get to the relative part of the path. +// char baseDir[MAX_PATH], oldWorkingDir[MAX_PATH]; +// if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) +// return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); +// +// Q_getwd( oldWorkingDir, sizeof( oldWorkingDir ) ); +// _chdir( baseDir ); +// +// // Filesystem_tools needs to add dependencies in here beforehand. +// FilesystemMountRetval_t retVal = mountContentInfo.m_pFileSystem->MountSteamContent( nExtraAppId ); +// +// _chdir( oldWorkingDir ); +// +// if ( retVal != FILESYSTEM_MOUNT_OK ) +// return SetupFileSystemError( true, FS_UNABLE_TO_INIT, "Unable to mount Steam content in the file system" ); } return FileSystem_SetBasePaths( mountContentInfo.m_pFileSystem ); @@ -1342,17 +1233,9 @@ void FileSystem_ClearSteamEnvVars() void FileSystem_AddSearchPath_Platform( IFileSystem *pFileSystem, const char *szGameInfoPath ) { char platform[MAX_PATH]; - if ( pFileSystem->IsSteam() ) - { - // Steam doesn't support relative paths - Q_strncpy( platform, "platform", MAX_PATH ); - } - else - { - Q_strncpy( platform, szGameInfoPath, MAX_PATH ); - Q_StripTrailingSlash( platform ); - Q_strncat( platform, "/../platform", MAX_PATH, MAX_PATH ); - } + Q_strncpy( platform, szGameInfoPath, MAX_PATH ); + Q_StripTrailingSlash( platform ); + Q_strncat( platform, "/../platform", MAX_PATH, MAX_PATH ); pFileSystem->AddSearchPath( platform, "PLATFORM" ); } diff --git a/public/filesystem_init.h b/public/filesystem_init.h index fc48b03f..e9787ab7 100644 --- a/public/filesystem_init.h +++ b/public/filesystem_init.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -148,14 +148,17 @@ public: // This specifies the directory where gameinfo.txt is. This must be set. const char *m_pDirectoryName; - // If this is set, then it will add a search path with _ appended to the pathname - // for each search path with a path ID of "game". + // If this is set, then any search paths with a _english will be replaced with _m_pLanguage and added before the + // _english path // (default: null) const char *m_pLanguage; // This is the filesystem FileSystem_LoadSearchPaths is talking to. IFileSystem *m_pFileSystem; + bool m_bMountHDContent; + bool m_bLowViolence; + // Outputs. public: // This is the location of the first search path called "game", which also becomes your "mod" search path. @@ -206,11 +209,6 @@ void FileSystem_ClearSteamEnvVars(); // Find the steam.cfg above you for optional stuff FSReturnCode_t GetSteamCfgPath( char *steamCfgPath, int steamCfgPathLen ); -// Setup the Steam.dll path without needing all the extra gameinfo stuff first -// used by the CSteamApplication::Create() code to LoadModule() on the filesystem -// before the underlying apps know specific details about the environment to load -FSReturnCode_t FileSystem_SetupSteamInstallPath(); - // Returns the last error. const char *FileSystem_GetLastErrorString(); diff --git a/public/filesystem_passthru.h b/public/filesystem_passthru.h index ba3a75de..e834ff6b 100644 --- a/public/filesystem_passthru.h +++ b/public/filesystem_passthru.h @@ -52,7 +52,7 @@ public: virtual bool FileExists( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->FileExists( pFileName, pPathID ); } virtual bool IsFileWritable( char const *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->IsFileWritable( pFileName, pPathID ); } virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID ) { return m_pBaseFileSystemPassThru->SetFileWritable( pFileName, writable, pPathID ); } - virtual long GetFileTime( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->GetFileTime( pFileName, pPathID ); } + virtual int32_t GetFileTime( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->GetFileTime( pFileName, pPathID ); } virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pBaseFileSystemPassThru->ReadFile( pFileName, pPath, buf, nMaxBytes, nStartingByte, pfnAlloc ); } virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) { return m_pBaseFileSystemPassThru->WriteFile( pFileName, pPath, buf ); } virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) { return m_pBaseFileSystemPassThru->UnzipFile( pFileName, pPath, pDestination ); } @@ -100,7 +100,7 @@ public: virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID ) { return m_pFileSystemPassThru->RenameFile( pOldPath, pNewPath, pathID ); } virtual void CreateDirHierarchy( const char *path, const char *pathID ) { m_pFileSystemPassThru->CreateDirHierarchy( path, pathID ); } virtual bool IsDirectory( const char *pFileName, const char *pathID ) { return m_pFileSystemPassThru->IsDirectory( pFileName, pathID ); } - virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) { m_pFileSystemPassThru->FileTimeToString( pStrip, maxCharsIncludingTerminator, fileTime ); } + virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, int32_t fileTime ) { m_pFileSystemPassThru->FileTimeToString( pStrip, maxCharsIncludingTerminator, fileTime ); } virtual void SetBufferSize( FileHandle_t file, unsigned nBytes ) { m_pFileSystemPassThru->SetBufferSize( file, nBytes ); } virtual bool IsOk( FileHandle_t file ) { return m_pFileSystemPassThru->IsOk( file ); } virtual bool EndOfFile( FileHandle_t file ) { return m_pFileSystemPassThru->EndOfFile( file ); } @@ -211,7 +211,7 @@ public: virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadToBuffer( hFile, buf, nMaxBytes, pfnAlloc ); } virtual bool FullPathToRelativePathEx( const char *pFullPath, const char *pPathId, char *pRelative, int nMaxLen ) { return m_pFileSystemPassThru->FullPathToRelativePathEx( pFullPath, pPathId, pRelative, nMaxLen ); } virtual int GetPathIndex( const FileNameHandle_t &handle ) { return m_pFileSystemPassThru->GetPathIndex( handle ); } - virtual long GetPathTime( const char *pPath, const char *pPathID ) { return m_pFileSystemPassThru->GetPathTime( pPath, pPathID ); } + virtual int32_t GetPathTime( const char *pPath, const char *pPathID ) { return m_pFileSystemPassThru->GetPathTime( pPath, pPathID ); } virtual DVDMode_t GetDVDMode() { return m_pFileSystemPassThru->GetDVDMode(); } diff --git a/public/icvar.h b/public/icvar.h index d3ee53af..950cf507 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -102,8 +102,91 @@ public: #if defined( _X360 ) virtual void PublishToVXConsole( ) = 0; #endif + virtual bool IsMaterialThreadSetAllowed( ) const = 0; + virtual void QueueMaterialThreadSetValue( ConVar *pConVar, const char *pValue ) = 0; + virtual void QueueMaterialThreadSetValue( ConVar *pConVar, int nValue ) = 0; + virtual void QueueMaterialThreadSetValue( ConVar *pConVar, float flValue ) = 0; + virtual bool HasQueuedMaterialThreadConVarSets() const = 0; + virtual int ProcessQueuedMaterialThreadConVarSets() = 0; + +protected: class ICVarIteratorInternal; +public: + /// Iteration over all cvars. + /// (THIS IS A SLOW OPERATION AND YOU SHOULD AVOID IT.) + /// usage: + /// { ICVar::Iterator iter(g_pCVar); + /// for ( iter.SetFirst() ; iter.IsValid() ; iter.Next() ) + /// { + /// ConCommandBase *cmd = iter.Get(); + /// } + /// } + /// The Iterator class actually wraps the internal factory methods + /// so you don't need to worry about new/delete -- scope takes care + // of it. + /// We need an iterator like this because we can't simply return a + /// pointer to the internal data type that contains the cvars -- + /// it's a custom, protected class with unusual semantics and is + /// prone to change. + class Iterator + { + public: + inline Iterator(ICvar *icvar); + inline ~Iterator(void); + inline void SetFirst( void ); + inline void Next( void ); + inline bool IsValid( void ); + inline ConCommandBase *Get( void ); + private: + ICVarIteratorInternal *m_pIter; + }; + +protected: + // internals for ICVarIterator + class ICVarIteratorInternal + { + public: + // warning: delete called on 'ICvar::ICVarIteratorInternal' that is abstract but has non-virtual destructor [-Wdelete-non-virtual-dtor] + virtual ~ICVarIteratorInternal() {} + virtual void SetFirst( void ) = 0; + virtual void Next( void ) = 0; + virtual bool IsValid( void ) = 0; + virtual ConCommandBase *Get( void ) = 0; + }; + + virtual ICVarIteratorInternal *FactoryInternalIterator( void ) = 0; + friend class Iterator; }; +inline ICvar::Iterator::Iterator(ICvar *icvar) +{ + m_pIter = icvar->FactoryInternalIterator(); +} + +inline ICvar::Iterator::~Iterator( void ) +{ + delete m_pIter; +} + +inline void ICvar::Iterator::SetFirst( void ) +{ + m_pIter->SetFirst(); +} + +inline void ICvar::Iterator::Next( void ) +{ + m_pIter->Next(); +} + +inline bool ICvar::Iterator::IsValid( void ) +{ + return m_pIter->IsValid(); +} + +inline ConCommandBase * ICvar::Iterator::Get( void ) +{ + return m_pIter->Get(); +} + #define CVAR_INTERFACE_VERSION "VEngineCvar004" @@ -114,7 +197,7 @@ public: // These are marked DLL_EXPORT for Linux. DLL_EXPORT ICvar *cvar; -DLL_EXPORT ICvar *g_pCVar; +extern ICvar *g_pCVar; #endif // ICVAR_H diff --git a/public/inetchannel.h b/public/inetchannel.h index 2ac5e872..99555ff2 100644 --- a/public/inetchannel.h +++ b/public/inetchannel.h @@ -28,8 +28,6 @@ public: virtual void SetDataRate(float rate) = 0; virtual bool RegisterMessage(INetMessage *msg) = 0; - virtual bool StartStreaming( unsigned int challengeNr ) = 0; - virtual void ResetStreaming( void ) = 0; virtual void SetTimeout(float seconds) = 0; virtual void SetDemoRecorder(IDemoRecorder *recorder) = 0; virtual void SetChallengeNr(unsigned int chnr) = 0; @@ -39,7 +37,6 @@ public: virtual void Shutdown(const char *reason) = 0; virtual void ProcessPlayback( void ) = 0; - virtual bool ProcessStream( void ) = 0; virtual void ProcessPacket( struct netpacket_s* packet, bool bHasHeader ) = 0; virtual bool SendNetMsg(INetMessage &msg, bool bForceReliable = false, bool bVoice = false ) = 0; @@ -72,8 +69,6 @@ public: virtual void SetCompressionMode( bool bUseCompression ) = 0; virtual unsigned int RequestFile(const char *filename) = 0; - virtual float GetTimeSinceLastReceived( void ) const = 0; - virtual void SetMaxBufferSize(bool bReliable, int nBytes, bool bVoice = false ) = 0; virtual bool IsNull() const = 0; diff --git a/public/iserver.h b/public/iserver.h index 29de610c..6554359f 100644 --- a/public/iserver.h +++ b/public/iserver.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -13,6 +13,7 @@ #include #include #include +#include class INetMessage; class IRecipientFilter; @@ -31,7 +32,9 @@ public: virtual int GetMaxClients( void ) const = 0; // returns current client limit virtual IClient *GetClient( int index ) = 0; // returns interface to client virtual int GetClientCount() const = 0; // returns number of clients slots (used & unused) - virtual int GetUDPPort( void ) const = 0; // returns current used UDP port + virtual netadr_t GetPublicAddress() = 0; + virtual bool IsUsingFakeIP( void ) const = 0; + virtual int GetLocalUDPPort( void ) const = 0; // returns current used UDP port virtual float GetTime( void ) const = 0; // returns game world time virtual int GetTick( void ) const = 0; // returns game world tick virtual float GetTickInterval( void ) const = 0; // tick interval in seconds diff --git a/public/ivrenderview.h b/public/ivrenderview.h index 0cee48b7..8fbd7ca4 100644 --- a/public/ivrenderview.h +++ b/public/ivrenderview.h @@ -209,7 +209,7 @@ public: virtual IWorldRenderList * CreateWorldList() = 0; virtual void BuildWorldLists( IWorldRenderList *pList, WorldListInfo_t* pInfo, int iForceFViewLeaf, const VisOverrideData_t* pVisData = NULL, bool bShadowDepth = false, float *pReflectionWaterHeight = NULL ) = 0; - virtual void DrawWorldLists( IWorldRenderList *pList, unsigned long flags, float waterZAdjust ) = 0; + virtual void DrawWorldLists( IWorldRenderList *pList, uint32_t flags, float waterZAdjust ) = 0; // Optimization for top view virtual void DrawTopView( bool enable ) = 0; @@ -221,7 +221,7 @@ public: virtual void DrawMaskEntities( void ) = 0; // Draw surfaces with alpha - virtual void DrawTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags, bool bShadowDepth ) = 0; + virtual void DrawTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, uint32_t flags, bool bShadowDepth ) = 0; // Draw Particles ( just draws the linefine for debugging map leaks ) virtual void DrawLineFile( void ) = 0; @@ -257,7 +257,7 @@ public: virtual void DrawBrushModelShadow( IClientRenderable *pRenderable ) = 0; // Does the leaf contain translucent surfaces? - virtual bool LeafContainsTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags ) = 0; + virtual bool LeafContainsTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, uint32_t flags ) = 0; virtual bool DoesBoxIntersectWaterVolume( const Vector &mins, const Vector &maxs, int leafWaterDataID ) = 0; diff --git a/public/materialsystem/imaterialsystem.h b/public/materialsystem/imaterialsystem.h index 8d863224..1334d80f 100644 --- a/public/materialsystem/imaterialsystem.h +++ b/public/materialsystem/imaterialsystem.h @@ -43,6 +43,7 @@ struct MaterialSystem_Config_t; class VMatrix; struct matrix3x4_t; class ITexture; +class ITextureCompositor; struct MaterialSystemHardwareIdentifier_t; class KeyValues; class IShader; @@ -65,7 +66,13 @@ typedef uint64 VertexFormat_t; // NOTE NOTE NOTE!!!! If you up this, grep for "NEW_INTERFACE" to see if there is anything // waiting to be enabled during an interface revision. -#define MATERIAL_SYSTEM_INTERFACE_VERSION "VMaterialSystem079" +#define MATERIAL_SYSTEM_INTERFACE_VERSION "VMaterialSystem081" + +#ifdef POSIX +#define ABSOLUTE_MINIMUM_DXLEVEL 90 +#else +#define ABSOLUTE_MINIMUM_DXLEVEL 80 +#endif enum ShaderParamType_t { @@ -82,6 +89,7 @@ enum ShaderParamType_t SHADER_PARAM_TYPE_MATRIX, SHADER_PARAM_TYPE_MATERIAL, SHADER_PARAM_TYPE_STRING, + SHADER_PARAM_TYPE_MATRIX4X2 }; enum MaterialMatrixMode_t @@ -217,6 +225,15 @@ enum MaterialContextType_t MATERIAL_NULL_CONTEXT }; +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +enum MaterialFindContext_t +{ + MATERIAL_FINDCONTEXT_NONE, + MATERIAL_FINDCONTEXT_ISONAMODEL, +}; //----------------------------------------------------------------------------- // Light structure @@ -274,7 +291,6 @@ private: #define CREATERENDERTARGETFLAGS_NOEDRAM 0x00000008 // inhibit allocation in 360 EDRAM #define CREATERENDERTARGETFLAGS_TEMP 0x00000010 // only allocates memory upon first resolve, destroyed at level end - //----------------------------------------------------------------------------- // allowed stencil operations. These match the d3d operations //----------------------------------------------------------------------------- @@ -463,6 +479,21 @@ private: int m_nBottom; }; +// Passed as the callback object to Async functions in the material system +// so that callers don't have to worry about memory going out of scope before the +// results return. +abstract_class IAsyncTextureOperationReceiver : public IRefCounted +{ +public: + virtual void OnAsyncCreateComplete( ITexture* pTex, void* pExtraArgs ) = 0; + virtual void OnAsyncFindComplete( ITexture* pTex, void* pExtraArgs ) = 0; + virtual void OnAsyncMapComplete( ITexture* pTex, void* pExtraArgs, void* pMemory, int nPitch ) = 0; + virtual void OnAsyncReadbackBegin( ITexture* pDst, ITexture* pSrc, void* pExtraArgs ) = 0; + + virtual int GetRefCount() const = 0; +}; + + //----------------------------------------------------------------------------- // Flags to be used with the Init call //----------------------------------------------------------------------------- @@ -508,7 +539,11 @@ enum RenderTargetSizeMode_t RT_SIZE_HDR=3, // frame_buffer_width / 4 RT_SIZE_FULL_FRAME_BUFFER=4, // Same size as frame buffer, or next lower power of 2 if we can't do that. RT_SIZE_OFFSCREEN=5, // Target of specified size, don't mess with dimensions - RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP=6 // Same size as the frame buffer, rounded up if necessary for systems that can't do non-power of two textures. + RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP=6, // Same size as the frame buffer, rounded up if necessary for systems that can't do non-power of two textures. + RT_SIZE_REPLAY_SCREENSHOT = 7, // Rounded down to power of 2, essentially... + RT_SIZE_LITERAL = 8, // Use the size passed in. Don't clamp it to the frame buffer size. Really. + RT_SIZE_LITERAL_PICMIP = 9 // Use the size passed in, don't clamp to the frame buffer size, but do apply picmip restrictions. + }; typedef void (*MaterialBufferReleaseFunc_t)( ); @@ -569,9 +604,10 @@ public: //--------------------------------------------------------- // //--------------------------------------------------------- - virtual void SetThreadMode( MaterialThreadMode_t mode, int nServiceThread = -1 ) = 0; - virtual MaterialThreadMode_t GetThreadMode() = 0; - virtual void ExecuteQueued() = 0; + virtual void SetThreadMode( MaterialThreadMode_t mode, int nServiceThread = -1 ) = 0; + virtual MaterialThreadMode_t GetThreadMode( ) = 0; + virtual bool IsRenderThreadSafe( ) = 0; + virtual void ExecuteQueued() = 0; //--------------------------------------------------------- // Config management @@ -765,6 +801,8 @@ public: //--------------------------------------------------------- // Material and texture management //--------------------------------------------------------- + virtual void SuspendTextureStreaming( void ) = 0; + virtual void ResumeTextureStreaming( void ) = 0; // uncache all materials. . good for forcing reload of materials. virtual void UncacheAllMaterials( ) = 0; @@ -800,6 +838,9 @@ public: // (Or use the global IsErrorMaterial function, which checks if it's null too). virtual IMaterial * FindMaterial( char const* pMaterialName, const char *pTextureGroupName, bool complain = true, const char *pComplainPrefix = NULL ) = 0; + // Query whether a material is loaded (eg, whether FindMaterial will be nonblocking) + virtual bool IsMaterialLoaded( char const* pMaterialName ) = 0; + //--------------------------------- // This is the interface for knowing what materials are available // is to use the following functions to get a list of materials. The @@ -827,7 +868,9 @@ public: //--------------------------------- - virtual ITexture * FindTexture( char const* pTextureName, const char *pTextureGroupName, bool complain = true ) = 0; + virtual void SetAsyncTextureLoadCache( void* hFileCache ) = 0; + + virtual ITexture * FindTexture( char const* pTextureName, const char *pTextureGroupName, bool complain = true, int nAdditionalCreationFlags = 0 ) = 0; // Checks to see if a particular texture is loaded virtual bool IsTextureLoaded( char const* pTextureName ) const = 0; @@ -997,6 +1040,49 @@ public: // For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences. virtual void ReloadFilesInList( IFileList *pFilesToReload ) = 0; + virtual bool AllowThreading( bool bAllow, int nServiceThread ) = 0; + + // Extended version of FindMaterial(). + // Contains context in so it can make decisions (i.e. if it's a model, ignore certain cheat parameters) + virtual IMaterial * FindMaterialEx( char const* pMaterialName, const char *pTextureGroupName, int nContext, bool complain = true, const char *pComplainPrefix = NULL ) = 0; + +#ifdef DX_TO_GL_ABSTRACTION + virtual void DoStartupShaderPreloading( void ) = 0; +#endif + + // Sets the override sizes for all render target size tests. These replace the frame buffer size. + // Set them when you are rendering primarily to something larger than the frame buffer (as in VR mode). + virtual void SetRenderTargetFrameBufferSizeOverrides( int nWidth, int nHeight ) = 0; + + // Returns the (possibly overridden) framebuffer size for render target sizing. + virtual void GetRenderTargetFrameBufferDimensions( int & nWidth, int & nHeight ) = 0; + + // returns the display device name that matches the adapter index we were started with + virtual char *GetDisplayDeviceName() const = 0; + + // creates a texture suitable for use with materials from a raw stream of bits. + // The bits will be retained by the material system and can be freed upon return. + virtual ITexture* CreateTextureFromBits(int w, int h, int mips, ImageFormat fmt, int srcBufferSize, byte* srcBits) = 0; + + // Lie to the material system to pretend to be in render target allocation mode at the beginning of time. + // This was a thing that mattered a lot to old hardware, but doesn't matter at all to new hardware, + // where new is defined to be "anything from the last decade." However, we want to preserve legacy behavior + // for the old games because it's easier than testing them. + virtual void OverrideRenderTargetAllocation( bool rtAlloc ) = 0; + + // creates a texture compositor that will attempt to composite a new textuer from the steps of the specified KeyValues. + virtual ITextureCompositor* NewTextureCompositor( int w, int h, const char* pCompositeName, int nTeamNum, uint64 randomSeed, KeyValues* stageDesc, uint32 texCompositeCreateFlags = 0 ) = 0; + + // Loads the texture with the specified name, calls pRecipient->OnAsyncFindComplete with the result from the main thread. + // once the texture load is complete. If the texture cannot be found, the returned texture will return true for IsError(). + virtual void AsyncFindTexture( const char* pFilename, const char *pTextureGroupName, IAsyncTextureOperationReceiver* pRecipient, void* pExtraArgs, bool bComplain = true, int nAdditionalCreationFlags = 0 ) = 0; + + // creates a texture suitable for use with materials from a raw stream of bits. + // The bits will be retained by the material system and can be freed upon return. + virtual ITexture* CreateNamedTextureFromBitsEx( const char* pName, const char *pTextureGroupName, int w, int h, int mips, ImageFormat fmt, int srcBufferSize, byte* srcBits, int nFlags ) = 0; + + virtual bool AddTextureCompositorTemplate( const char *pName, KeyValues *kv, int a ) = 0; + virtual bool VerifyTextureCompositorTemplates ( void ) = 0; }; @@ -1282,6 +1368,7 @@ public: // Blit a subrect of the current render target to another texture virtual void CopyRenderTargetToTextureEx( ITexture *pTexture, int nRenderTargetID, Rect_t *pSrcRect, Rect_t *pDstRect = NULL ) = 0; + virtual void CopyTextureToRenderTargetEx( int nRenderTargetID, ITexture *pTexture, Rect_t *pSrcRect, Rect_t *pDstRect = NULL ) = 0; // Special off-center perspective matrix for DoF, MSAA jitter and poster rendering virtual void PerspectiveOffCenterX( double fovx, double aspect, double zNear, double zFar, double bottom, double top, double left, double right ) = 0; @@ -1341,9 +1428,9 @@ public: virtual void GetFogDistances( float *fStart, float *fEnd, float *fFogZ ) = 0; // Hooks for firing PIX events from outside the Material System... - virtual void BeginPIXEvent( unsigned long color, const char *szName ) = 0; + virtual void BeginPIXEvent( uint32_t color, const char *szName ) = 0; virtual void EndPIXEvent() = 0; - virtual void SetPIXMarker( unsigned long color, const char *szName ) = 0; + virtual void SetPIXMarker( uint32_t color, const char *szName ) = 0; // Batch API // from changelist 166623: @@ -1433,8 +1520,221 @@ public: virtual void SetNonInteractiveTempFullscreenBuffer( ITexture *pTexture, MaterialNonInteractiveMode_t mode ) = 0; virtual void EnableNonInteractiveMode( MaterialNonInteractiveMode_t mode ) = 0; virtual void RefreshFrontBufferNonInteractive() = 0; + // Allocates temp render data. Renderdata goes out of scope at frame end in multicore + // Renderdata goes out of scope after refcount goes to zero in singlecore. + // Locking/unlocking increases + decreases refcount + virtual void * LockRenderData( int nSizeInBytes ) = 0; + virtual void UnlockRenderData( void *pData ) = 0; + + // Typed version. If specified, pSrcData is copied into the locked memory. + template< class E > E* LockRenderDataTyped( int nCount, const E* pSrcData = NULL ); + + // Temp render data gets immediately freed after it's all unlocked in single core. + // This prevents it from being freed + virtual void AddRefRenderData() = 0; + virtual void ReleaseRenderData() = 0; + + // Returns whether a pointer is render data. NOTE: passing NULL returns true + virtual bool IsRenderData( const void *pData ) const = 0; + virtual void PrintfVA( char *fmt, va_list vargs ) = 0; + virtual void Printf( PRINTF_FORMAT_STRING const char *fmt, ... ) = 0; + virtual float Knob( char *knobname, float *setvalue = NULL ) = 0; + // Allows us to override the alpha write setting of a material + virtual void OverrideAlphaWriteEnable( bool bEnable, bool bAlphaWriteEnable ) = 0; + virtual void OverrideColorWriteEnable( bool bOverrideEnable, bool bColorWriteEnable ) = 0; + + virtual void ClearBuffersObeyStencilEx( bool bClearColor, bool bClearAlpha, bool bClearDepth ) = 0; + + // Create a texture from the specified src render target, then call pRecipient->OnAsyncCreateComplete from the main thread. + // The texture will be created using the destination format, and will optionally have mipmaps generated. + // In case of error, the provided callback function will be called with the error texture. + virtual void AsyncCreateTextureFromRenderTarget( ITexture* pSrcRt, const char* pDstName, ImageFormat dstFmt, bool bGenMips, int nAdditionalCreationFlags, IAsyncTextureOperationReceiver* pRecipient, void* pExtraArgs ) = 0; }; +template< class E > inline E* IMatRenderContext::LockRenderDataTyped( int nCount, const E* pSrcData ) +{ + int nSizeInBytes = nCount * sizeof(E); + E *pDstData = (E*)LockRenderData( nSizeInBytes ); + if ( pSrcData && pDstData ) + { + memcpy( pDstData, pSrcData, nSizeInBytes ); + } + return pDstData; +} + + +//----------------------------------------------------------------------------- +// Utility class for addreffing/releasing render data (prevents freeing on single core) +//----------------------------------------------------------------------------- +class CMatRenderDataReference +{ +public: + CMatRenderDataReference(); + CMatRenderDataReference( IMatRenderContext* pRenderContext ); + ~CMatRenderDataReference(); + void Lock( IMatRenderContext *pRenderContext ); + void Release(); + +private: + IMatRenderContext *m_pRenderContext; +}; + + +inline CMatRenderDataReference::CMatRenderDataReference() +{ + m_pRenderContext = NULL; +} + +inline CMatRenderDataReference::CMatRenderDataReference( IMatRenderContext* pRenderContext ) +{ + m_pRenderContext = NULL; + Lock( pRenderContext ); +} + +inline CMatRenderDataReference::~CMatRenderDataReference() +{ + Release(); +} + +inline void CMatRenderDataReference::Lock( IMatRenderContext* pRenderContext ) +{ + if ( !m_pRenderContext ) + { + m_pRenderContext = pRenderContext; + m_pRenderContext->AddRefRenderData( ); + } +} + +inline void CMatRenderDataReference::Release() +{ + if ( m_pRenderContext ) + { + m_pRenderContext->ReleaseRenderData( ); + m_pRenderContext = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Utility class for locking/unlocking render data +//----------------------------------------------------------------------------- +template< typename E > +class CMatRenderData +{ +public: + CMatRenderData( IMatRenderContext* pRenderContext ); + CMatRenderData( IMatRenderContext* pRenderContext, int nCount, const E *pSrcData = NULL ); + ~CMatRenderData(); + E* Lock( int nCount, const E* pSrcData = NULL ); + void Release(); + bool IsValid() const; + const E* Base() const; + E* Base(); + const E& operator[]( int i ) const; + E& operator[]( int i ); + +private: + IMatRenderContext* m_pRenderContext; + E *m_pRenderData; + int m_nCount; + bool m_bNeedsUnlock; +}; + +template< typename E > +inline CMatRenderData::CMatRenderData( IMatRenderContext* pRenderContext ) +{ + m_pRenderContext = pRenderContext; + m_nCount = 0; + m_pRenderData = 0; + m_bNeedsUnlock = false; +} + +template< typename E > +inline CMatRenderData::CMatRenderData( IMatRenderContext* pRenderContext, int nCount, const E* pSrcData ) +{ + m_pRenderContext = pRenderContext; + m_nCount = 0; + m_pRenderData = 0; + m_bNeedsUnlock = false; + Lock( nCount, pSrcData ); +} + +template< typename E > +inline CMatRenderData::~CMatRenderData() +{ + Release(); +} + +template< typename E > +inline bool CMatRenderData::IsValid() const +{ + return m_pRenderData != NULL; +} + +template< typename E > +inline E* CMatRenderData::Lock( int nCount, const E* pSrcData ) +{ + m_nCount = nCount; + if ( pSrcData && m_pRenderContext->IsRenderData( pSrcData ) ) + { + // Yes, we're const-casting away, but that should be ok since + // the src data is render data + m_pRenderData = const_cast( pSrcData ); + m_pRenderContext->AddRefRenderData(); + m_bNeedsUnlock = false; + return m_pRenderData; + } + m_pRenderData = m_pRenderContext->LockRenderDataTyped( nCount, pSrcData ); + m_bNeedsUnlock = true; + return m_pRenderData; +} + +template< typename E > +inline void CMatRenderData::Release() +{ + if ( m_pRenderContext && m_pRenderData ) + { + if ( m_bNeedsUnlock ) + { + m_pRenderContext->UnlockRenderData( m_pRenderData ); + } + else + { + m_pRenderContext->ReleaseRenderData(); + } + } + m_pRenderData = NULL; + m_nCount = 0; + m_bNeedsUnlock = false; +} + +template< typename E > +inline E* CMatRenderData::Base() +{ + return m_pRenderData; +} + +template< typename E > +inline const E* CMatRenderData::Base() const +{ + return m_pRenderData; +} + +template< typename E > +inline E& CMatRenderData::operator[]( int i ) +{ + Assert( ( i >= 0 ) && ( i < m_nCount ) ); + return m_pRenderData[i]; +} + +template< typename E > +inline const E& CMatRenderData::operator[]( int i ) const +{ + Assert( ( i >= 0 ) && ( i < m_nCount ) ); + return m_pRenderData[i]; +} + + //----------------------------------------------------------------------------- class CMatRenderContextPtr : public CRefPtr @@ -1468,7 +1768,7 @@ private: class PIXEvent { public: - PIXEvent( IMatRenderContext *pRenderContext, const char *szName, unsigned long color = PIX_VALVE_ORANGE ) + PIXEvent( IMatRenderContext *pRenderContext, const char *szName, uint32_t color = PIX_VALVE_ORANGE ) { m_pRenderContext = pRenderContext; Assert( m_pRenderContext ); @@ -1484,7 +1784,8 @@ private: }; -#define PIX_ENABLE 0 // set this to 1 and build engine/studiorender to enable pix events in the engine +// Also be sure to enable PIX_INSTRUMENTATION in shaderdevicedx8.h +//#define PIX_ENABLE 1 // set this to 1 and build engine/studiorender to enable pix events in the engine #if PIX_ENABLE # define PIXEVENT PIXEvent _pixEvent diff --git a/public/materialsystem/imaterialvar.h b/public/materialsystem/imaterialvar.h index 8c24df7d..2728e489 100644 --- a/public/materialsystem/imaterialvar.h +++ b/public/materialsystem/imaterialvar.h @@ -21,8 +21,8 @@ class VMatrix; class ITexture; #define MAKE_MATERIALVAR_FOURCC(ch0, ch1, ch2, ch3) \ - ((unsigned long)(ch0) | ((unsigned long)(ch1) << 8) | \ - ((unsigned long)(ch2) << 16) | ((unsigned long)(ch3) << 24 )) + ((uint32_t)(ch0) | ((uint32_t)(ch1) << 8) | \ + ((uint32_t)(ch2) << 16) | ((uint32_t)(ch3) << 24 )) // This fourcc is reserved. #define FOURCC_UNKNOWN MAKE_MATERIALVAR_FOURCC('U','N','K','N') @@ -49,7 +49,7 @@ typedef unsigned short MaterialVarSym_t; class IMaterialVar { public: - typedef unsigned long FourCC; + typedef uint32_t FourCC; protected: // base data and accessors diff --git a/public/mathlib/amd3dx.h b/public/mathlib/amd3dx.h new file mode 100644 index 00000000..4a95ec52 --- /dev/null +++ b/public/mathlib/amd3dx.h @@ -0,0 +1,1190 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +/****************************************************************************** + + Copyright (c) 1999 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com + +******************************************************************************* + + AMD3DX.H + + MACRO FORMAT + ============ + This file contains inline assembly macros that + generate AMD-3D instructions in binary format. + Therefore, C or C++ programmer can use AMD-3D instructions + without any penalty in their C or C++ source code. + + The macro's name and format conventions are as follow: + + + 1. First argument of macro is a destination and + second argument is a source operand. + ex) _asm PFCMPEQ (mm3, mm4) + | | + dst src + + 2. The destination operand can be m0 to m7 only. + The source operand can be any one of the register + m0 to m7 or _eax, _ecx, _edx, _ebx, _esi, or _edi + that contains effective address. + ex) _asm PFRCP (MM7, MM6) + ex) _asm PFRCPIT2 (mm0, mm4) + ex) _asm PFMUL (mm3, _edi) + + 3. The prefetch(w) takes one src operand _eax, ecx, _edx, + _ebx, _esi, or _edi that contains effective address. + ex) _asm PREFETCH (_edi) + + For WATCOM C/C++ users, when using #pragma aux instead if + _asm, all macro names should be prefixed by a p_ or P_. + Macros should not be enclosed in quotes. + ex) p_pfrcp (MM7,MM6) + + NOTE: Not all instruction macros, nor all possible + combinations of operands have been explicitely + tested. If any errors are found, please report + them. + + EXAMPLE + ======= + Following program doesn't do anything but it shows you + how to use inline assembly AMD-3D instructions in C. + Note that this will only work in flat memory model which + segment registers cs, ds, ss and es point to the same + linear address space total less than 4GB. + + Used Microsoft VC++ 5.0 + + #include + #include "amd3d.h" + + void main () + { + float x = (float)1.25; + float y = (float)1.25; + float z, zz; + + _asm { + movd mm1, x + movd mm2, y + pfmul (mm1, mm2) + movd z, mm1 + femms + } + + printf ("value of z = %f\n", z); + + // + // Demonstration of using the memory instead of + // multimedia register + // + _asm { + movd mm3, x + lea esi, y // load effective address of y + pfmul (mm3, _esi) + movd zz, mm3 + femms + } + + printf ("value of zz = %f\n", zz); + } + + #pragma aux EXAMPLE with WATCOM C/C++ v11.x + =========================================== + + extern void Add(float *__Dest, float *__A, float *__B); + #pragma aux Add = \ + p_femms \ + "movd mm6,[esi]" \ + p_pfadd(mm6,_edi) \ + "movd [ebx],mm6" \ + p_femms \ + parm [ebx] [esi] [edi]; + +*******************************************************************************/ + +#ifndef _K3DMACROSINCLUDED_ +#define _K3DMACROSINCLUDED_ + +#if defined (__WATCOMC__) + +// The WATCOM C/C++ version of the 3DNow! macros. +// +// The older, compbined register style for WATCOM C/C++ macros is not +// supported. + +/* Operand defines for instructions two operands */ +#define _k3d_mm0_mm0 0xc0 +#define _k3d_mm0_mm1 0xc1 +#define _k3d_mm0_mm2 0xc2 +#define _k3d_mm0_mm3 0xc3 +#define _k3d_mm0_mm4 0xc4 +#define _k3d_mm0_mm5 0xc5 +#define _k3d_mm0_mm6 0xc6 +#define _k3d_mm0_mm7 0xc7 +#define _k3d_mm0_eax 0x00 +#define _k3d_mm0_ecx 0x01 +#define _k3d_mm0_edx 0x02 +#define _k3d_mm0_ebx 0x03 +#define _k3d_mm0_esi 0x06 +#define _k3d_mm0_edi 0x07 +#define _k3d_mm1_mm0 0xc8 +#define _k3d_mm1_mm1 0xc9 +#define _k3d_mm1_mm2 0xca +#define _k3d_mm1_mm3 0xcb +#define _k3d_mm1_mm4 0xcc +#define _k3d_mm1_mm5 0xcd +#define _k3d_mm1_mm6 0xce +#define _k3d_mm1_mm7 0xcf +#define _k3d_mm1_eax 0x08 +#define _k3d_mm1_ecx 0x09 +#define _k3d_mm1_edx 0x0a +#define _k3d_mm1_ebx 0x0b +#define _k3d_mm1_esi 0x0e +#define _k3d_mm1_edi 0x0f +#define _k3d_mm2_mm0 0xd0 +#define _k3d_mm2_mm1 0xd1 +#define _k3d_mm2_mm2 0xd2 +#define _k3d_mm2_mm3 0xd3 +#define _k3d_mm2_mm4 0xd4 +#define _k3d_mm2_mm5 0xd5 +#define _k3d_mm2_mm6 0xd6 +#define _k3d_mm2_mm7 0xd7 +#define _k3d_mm2_eax 0x10 +#define _k3d_mm2_ecx 0x11 +#define _k3d_mm2_edx 0x12 +#define _k3d_mm2_ebx 0x13 +#define _k3d_mm2_esi 0x16 +#define _k3d_mm2_edi 0x17 +#define _k3d_mm3_mm0 0xd8 +#define _k3d_mm3_mm1 0xd9 +#define _k3d_mm3_mm2 0xda +#define _k3d_mm3_mm3 0xdb +#define _k3d_mm3_mm4 0xdc +#define _k3d_mm3_mm5 0xdd +#define _k3d_mm3_mm6 0xde +#define _k3d_mm3_mm7 0xdf +#define _k3d_mm3_eax 0x18 +#define _k3d_mm3_ecx 0x19 +#define _k3d_mm3_edx 0x1a +#define _k3d_mm3_ebx 0x1b +#define _k3d_mm3_esi 0x1e +#define _k3d_mm3_edi 0x1f +#define _k3d_mm4_mm0 0xe0 +#define _k3d_mm4_mm1 0xe1 +#define _k3d_mm4_mm2 0xe2 +#define _k3d_mm4_mm3 0xe3 +#define _k3d_mm4_mm4 0xe4 +#define _k3d_mm4_mm5 0xe5 +#define _k3d_mm4_mm6 0xe6 +#define _k3d_mm4_mm7 0xe7 +#define _k3d_mm4_eax 0x20 +#define _k3d_mm4_ecx 0x21 +#define _k3d_mm4_edx 0x22 +#define _k3d_mm4_ebx 0x23 +#define _k3d_mm4_esi 0x26 +#define _k3d_mm4_edi 0x27 +#define _k3d_mm5_mm0 0xe8 +#define _k3d_mm5_mm1 0xe9 +#define _k3d_mm5_mm2 0xea +#define _k3d_mm5_mm3 0xeb +#define _k3d_mm5_mm4 0xec +#define _k3d_mm5_mm5 0xed +#define _k3d_mm5_mm6 0xee +#define _k3d_mm5_mm7 0xef +#define _k3d_mm5_eax 0x28 +#define _k3d_mm5_ecx 0x29 +#define _k3d_mm5_edx 0x2a +#define _k3d_mm5_ebx 0x2b +#define _k3d_mm5_esi 0x2e +#define _k3d_mm5_edi 0x2f +#define _k3d_mm6_mm0 0xf0 +#define _k3d_mm6_mm1 0xf1 +#define _k3d_mm6_mm2 0xf2 +#define _k3d_mm6_mm3 0xf3 +#define _k3d_mm6_mm4 0xf4 +#define _k3d_mm6_mm5 0xf5 +#define _k3d_mm6_mm6 0xf6 +#define _k3d_mm6_mm7 0xf7 +#define _k3d_mm6_eax 0x30 +#define _k3d_mm6_ecx 0x31 +#define _k3d_mm6_edx 0x32 +#define _k3d_mm6_ebx 0x33 +#define _k3d_mm6_esi 0x36 +#define _k3d_mm6_edi 0x37 +#define _k3d_mm7_mm0 0xf8 +#define _k3d_mm7_mm1 0xf9 +#define _k3d_mm7_mm2 0xfa +#define _k3d_mm7_mm3 0xfb +#define _k3d_mm7_mm4 0xfc +#define _k3d_mm7_mm5 0xfd +#define _k3d_mm7_mm6 0xfe +#define _k3d_mm7_mm7 0xff +#define _k3d_mm7_eax 0x38 +#define _k3d_mm7_ecx 0x39 +#define _k3d_mm7_edx 0x3a +#define _k3d_mm7_ebx 0x3b +#define _k3d_mm7_esi 0x3e +#define _k3d_mm7_edi 0x3f + +#define _k3d_name_xlat_m0 _mm0 +#define _k3d_name_xlat_m1 _mm1 +#define _k3d_name_xlat_m2 _mm2 +#define _k3d_name_xlat_m3 _mm3 +#define _k3d_name_xlat_m4 _mm4 +#define _k3d_name_xlat_m5 _mm5 +#define _k3d_name_xlat_m6 _mm6 +#define _k3d_name_xlat_m7 _mm7 +#define _k3d_name_xlat_M0 _mm0 +#define _k3d_name_xlat_M1 _mm1 +#define _k3d_name_xlat_M2 _mm2 +#define _k3d_name_xlat_M3 _mm3 +#define _k3d_name_xlat_M4 _mm4 +#define _k3d_name_xlat_M5 _mm5 +#define _k3d_name_xlat_M6 _mm6 +#define _k3d_name_xlat_M7 _mm7 +#define _k3d_name_xlat_mm0 _mm0 +#define _k3d_name_xlat_mm1 _mm1 +#define _k3d_name_xlat_mm2 _mm2 +#define _k3d_name_xlat_mm3 _mm3 +#define _k3d_name_xlat_mm4 _mm4 +#define _k3d_name_xlat_mm5 _mm5 +#define _k3d_name_xlat_mm6 _mm6 +#define _k3d_name_xlat_mm7 _mm7 +#define _k3d_name_xlat_MM0 _mm0 +#define _k3d_name_xlat_MM1 _mm1 +#define _k3d_name_xlat_MM2 _mm2 +#define _k3d_name_xlat_MM3 _mm3 +#define _k3d_name_xlat_MM4 _mm4 +#define _k3d_name_xlat_MM5 _mm5 +#define _k3d_name_xlat_MM6 _mm6 +#define _k3d_name_xlat_MM7 _mm7 +#define _k3d_name_xlat_eax _eax +#define _k3d_name_xlat_ebx _ebx +#define _k3d_name_xlat_ecx _ecx +#define _k3d_name_xlat_edx _edx +#define _k3d_name_xlat_esi _esi +#define _k3d_name_xlat_edi _edi +#define _k3d_name_xlat_ebp _ebp +#define _k3d_name_xlat_EAX _eax +#define _k3d_name_xlat_EBX _ebx +#define _k3d_name_xlat_ECX _ecx +#define _k3d_name_xlat_EDX _edx +#define _k3d_name_xlat_ESI _esi +#define _k3d_name_xlat_EDI _edi +#define _k3d_name_xlat_EBP _ebp +#define _k3d_name_xlat__eax _eax +#define _k3d_name_xlat__ebx _ebx +#define _k3d_name_xlat__ecx _ecx +#define _k3d_name_xlat__edx _edx +#define _k3d_name_xlat__esi _esi +#define _k3d_name_xlat__edi _edi +#define _k3d_name_xlat__ebp _ebp +#define _k3d_name_xlat__EAX _eax +#define _k3d_name_xlat__EBX _ebx +#define _k3d_name_xlat__ECX _ecx +#define _k3d_name_xlat__EDX _edx +#define _k3d_name_xlat__ESI _esi +#define _k3d_name_xlat__EDI _edi +#define _k3d_name_xlat__EBP _ebp + +#define _k3d_xglue3(a,b,c) a##b##c +#define _k3d_glue3(a,b,c) _k3d_xglue3(a,b,c) +#define _k3d_MODRM(dst, src) _k3d_glue3(_k3d,_k3d_name_xlat_##dst,_k3d_name_xlat_##src) + +/* Operand defines for prefetch and prefetchw */ + +#define _k3d_pref_eax 0x00 +#define _k3d_pref_ecx 0x01 +#define _k3d_pref_edx 0x02 +#define _k3d_pref_ebx 0x03 +#define _k3d_pref_esi 0x06 +#define _k3d_pref_edi 0x07 +#define _k3d_pref_EAX 0x00 +#define _k3d_pref_ECX 0x01 +#define _k3d_pref_EDX 0x02 +#define _k3d_pref_EBX 0x03 +#define _k3d_pref_ESI 0x06 +#define _k3d_pref_EDI 0x07 +#define _k3d_prefw_eax 0x08 +#define _k3d_prefw_ecx 0x09 +#define _k3d_prefw_edx 0x0A +#define _k3d_prefw_ebx 0x0B +#define _k3d_prefw_esi 0x0E +#define _k3d_prefw_edi 0x0F +#define _k3d_prefw_EAX 0x08 +#define _k3d_prefw_ECX 0x09 +#define _k3d_prefw_EDX 0x0A +#define _k3d_prefw_EBX 0x0B +#define _k3d_prefw_ESI 0x0E +#define _k3d_prefw_EDI 0x0F + +/* Defines for 3DNow! instructions */ +#define PF2ID(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x1d +#define PFACC(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xae +#define PFADD(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x9e +#define PFCMPEQ(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb0 +#define PFCMPGE(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x90 +#define PFCMPGT(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa0 +#define PFMAX(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa4 +#define PFMIN(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x94 +#define PFMUL(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb4 +#define PFRCP(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x96 +#define PFRCPIT1(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa6 +#define PFRCPIT2(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb6 +#define PFRSQRT(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x97 +#define PFRSQIT1(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa7 +#define PFSUB(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x9a +#define PFSUBR(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xaa +#define PI2FD(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x0d +#define FEMMS db 0x0f, 0x0e +#define PAVGUSB(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xbf +#define PMULHRW(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb7 +#define PREFETCH(src) db 0x0f, 0x0d, _k3d_pref_##src +#define PREFETCHW(src) db 0x0f, 0x0d, _k3d_prefw_##src +#define CPUID db 0x0f, 0xa2 + +/* Defines for new, K7 opcodes */ +#define PFNACC(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0x8a +#define FPPNACC(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0x8e +#define PSWAPD(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0xbb +#define PMINUB(dst,src) db 0x0f, 0xda, _k3d_MODRM(dst,src) +#define PMAXUB(dst,src) db 0x0f, 0xde, _k3d_MODRM(dst,src) +#define PMINSW(dst,src) db 0x0f, 0xea, _k3d_MODRM(dst,src) +#define PMAXSW(dst,src) db 0x0f, 0xee, _k3d_MODRM(dst,src) +#define PMULHUW(dst,src) db 0x0f, 0xe4, _k3d_MODRM(dst,src) +#define PAVGB(dst,src) db 0x0f, 0xe0, _k3d_MODRM(dst,src) +#define PAVGW(dst,src) db 0x0f, 0xe3, _k3d_MODRM(dst,src) +#define PSADBW(dst,src) db 0x0f, 0xf6, _k3d_MODRM(dst,src) +#define PMOVMSKB(dst,src) db 0x0f, 0xd7, _k3d_MODRM(dst,src) +#define PMASKMOVQ(dst,src) db 0x0f, 0xf7, _k3d_MODRM(dst,src) +#define PINSRW(dst,src,msk) db 0x0f, 0xc4, _k3d_MODRM(dst,src), msk +#define PEXTRW(dst,src,msk) db 0x0f, 0xc5, _k3d_MODRM(dst,src), msk +#define PSHUFW(dst,src,msk) db 0x0f, 0x70, _k3d_MODRM(dst,src), msk +#define MOVNTQ(dst,src) db 0x0f, 0xe7, _k3d_MODRM(src,dst) +#define SFENCE db 0x0f, 0xae, 0xf8 + +/* Memory/offset versions of the opcodes */ +#define PF2IDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x1d +#define PFACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xae +#define PFADDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x9e +#define PFCMPEQM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb0 +#define PFCMPGEM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x90 +#define PFCMPGTM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa0 +#define PFMAXM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa4 +#define PFMINM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x94 +#define PFMULM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb4 +#define PFRCPM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x96 +#define PFRCPIT1M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa6 +#define PFRCPIT2M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb6 +#define PFRSQRTM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x97 +#define PFRSQIT1M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa7 +#define PFSUBM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x9a +#define PFSUBRM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xaa +#define PI2FDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x0d +#define PAVGUSBM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xbf +#define PMULHRWM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb7 + + +/* Memory/offset versions of the new, K7 opcodes */ +#define PFNACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x8a +#define FPPNACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x8e +#define PSWAPDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xbb +#define PMINUBM(dst,src,off) db 0x0f, 0xda, _k3d_MODRM(dst,src) | 0x40, off +#define PMAXUBM(dst,src,off) db 0x0f, 0xde, _k3d_MODRM(dst,src) | 0x40, off +#define PMINSWM(dst,src,off) db 0x0f, 0xea, _k3d_MODRM(dst,src) | 0x40, off +#define PMAXSWM(dst,src,off) db 0x0f, 0xee, _k3d_MODRM(dst,src) | 0x40, off +#define PMULHUWM(dst,src,off) db 0x0f, 0xe4, _k3d_MODRM(dst,src) | 0x40, off +#define PAVGBM(dst,src,off) db 0x0f, 0xe0, _k3d_MODRM(dst,src) | 0x40, off +#define PAVGWM(dst,src,off) db 0x0f, 0xe3, _k3d_MODRM(dst,src) | 0x40, off +#define PSADBWM(dst,src,off) db 0x0f, 0xf6, _k3d_MODRM(dst,src) | 0x40, off +#define PMOVMSKBM(dst,src,off) db 0x0f, 0xd7, _k3d_MODRM(dst,src) | 0x40, off +#define PMASKMOVQM(dst,src,off) db 0x0f, 0xf7, _k3d_MODRM(dst,src) | 0x40, off +#define MOVNTQM(dst,src,off) db 0x0f, 0xe7, _k3d_MODRM(src,dst) | 0x40, off +#define PINSRWM(dst,src,off,msk) db 0x0f, 0xc4, _k3d_MODRM(dst,src) | 0x40, off, msk +#define PSHUFWM(dst,src,off,msk) db 0x0f, 0x70, _k3d_MODRM(dst,src) | 0x40, off, msk + + +/* Defines for 3DNow! instructions for use in pragmas */ +#define p_pf2id(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x1d +#define p_pfacc(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xae +#define p_pfadd(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x9e +#define p_pfcmpeq(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb0 +#define p_pfcmpge(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x90 +#define p_pfcmpgt(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa0 +#define p_pfmax(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa4 +#define p_pfmin(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x94 +#define p_pfmul(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb4 +#define p_pfrcp(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x96 +#define p_pfrcpit1(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa6 +#define p_pfrcpit2(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb6 +#define p_pfrsqrt(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x97 +#define p_pfrsqit1(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa7 +#define p_pfsub(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x9a +#define p_pfsubr(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xaa +#define p_pi2fd(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x0d +#define p_femms 0x0f 0x0e +#define p_pavgusb(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xbf +#define p_pmulhrw(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb7 +#define p_prefetch(src) 0x0f 0x0d _k3d_pref_##src +#define p_prefetchw(src) 0x0f 0x0d _k3d_prefw_##src +#define P_PFNACC(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8a +#define P_FPPNACC(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8e +#define P_PSWAPD(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbb +#define P_PMINUB(dst,src) 0x0f 0xda (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXUB(dst,src) 0x0f 0xde (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMINSW(dst,src) 0x0f 0xea (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXSW(dst,src) 0x0f 0xee (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMULHUW(dst,src) 0x0f 0xe4 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGB(dst,src) 0x0f 0xe0 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGW(dst,src) 0x0f 0xe3 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PSADBW(dst,src) 0x0f 0xf6 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMOVMSKB(dst,src) 0x0f 0xd7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMASKMOVQ(dst,src) 0x0f 0xf7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PINSRW(dst,src,msk) 0x0f 0xc4 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_PEXTRW(dst,src,msk) 0x0f 0xc5 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_PSHUFW(dst,src,msk) 0x0f 0x70 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_MOVNTQ(dst,src) 0x0f 0xe7 (_k3d_MODRM(src,dst) | 0x40) off + +#define P_PF2IDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x1d +#define P_PFACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xae +#define P_PFADDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x9e +#define P_PFCMPEQM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb0 +#define P_PFCMPGEM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x90 +#define P_PFCMPGTM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa0 +#define P_PFMAXM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa4 +#define P_PFMINM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x94 +#define P_PFMULM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb4 +#define P_PFRCPM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x96 +#define P_PFRCPIT1M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa6 +#define P_PFRCPIT2M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb6 +#define P_PFRSQRTM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x97 +#define P_PFRSQIT1M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa7 +#define P_PFSUBM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x9a +#define P_PFSUBRM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xaa +#define P_PI2FDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x0d +#define P_PAVGUSBM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbf +#define P_PMULHRWM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb7 +#define P_PFNACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8a +#define P_FPPNACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8e +#define P_PSWAPDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbb +#define P_PMINUBM(dst,src,off) 0x0f 0xda (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXUBM(dst,src,off) 0x0f 0xde (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMINSWM(dst,src,off) 0x0f 0xea (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXSWM(dst,src,off) 0x0f 0xee (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMULHUWM(dst,src,off) 0x0f 0xe4 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGBM(dst,src,off) 0x0f 0xe0 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGWM(dst,src,off) 0x0f 0xe3 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PSADBWM(dst,src,off) 0x0f 0xf6 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMOVMSKBM(dst,src,off) 0x0f 0xd7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_MOVNTQM(dst,src,off) 0x0f 0xe7 (_k3d_MODRM(src,dst) | 0x40) off +#define P_PMASKMOVQM(dst,src,off) 0x0f 0xf7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PINSRWM(dst,src,off,msk) 0x0f 0xc4 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_PSHUFWM(dst,src,off,msk) 0x0f 0x70 (_k3d_MODRM(dst,src) | 0x40) off msk + + +#define P_PF2ID(dst,src) p_pf2id(dst,src) +#define P_PFACC(dst,src) p_pfacc(dst,src) +#define P_PFADD(dst,src) p_pfadd(dst,src) +#define P_PFCMPEQ(dst,src) p_pfcmpeq(dst,src) +#define P_PFCMPGE(dst,src) p_pfcmpge(dst,src) +#define P_PFCMPGT(dst,src) p_pfcmpgt(dst,src) +#define P_PFMAX(dst,src) p_pfmax(dst,src) +#define P_PFMIN(dst,src) p_pfmin(dst,src) +#define P_PFMUL(dst,src) p_pfmul(dst,src) +#define P_PFRCP(dst,src) p_pfrcp(dst,src) +#define P_PFRCPIT1(dst,src) p_pfrcpit1(dst,src) +#define P_PFRCPIT2(dst,src) p_pfrcpit2(dst,src) +#define P_PFRSQRT(dst,src) p_pfrsqrt(dst,src) +#define P_PFRSQIT1(dst,src) p_pfrsqit1(dst,src) +#define P_PFSUB(dst,src) p_pfsub(dst,src) +#define P_PFSUBR(dst,src) p_pfsubr(dst,src) +#define P_PI2FD(dst,src) p_pi2fd(dst,src) +#define P_FEMMS p_femms +#define P_PAVGUSB(dst,src) p_pavgusb(dst,src) +#define P_PMULHRW(dst,src) p_pmulhrw(dst,src) +#define P_PREFETCH(src) p_prefetch(src) +#define P_PREFETCHW(src) p_prefetchw(src) +#define p_CPUID 0x0f 0xa2 +#define p_pf2idm(dst,src,off) P_PF2IDM(dst,src,off) +#define p_pfaccm(dst,src,off) P_PFACCM(dst,src,off) +#define p_pfaddm(dst,src,off) P_PFADDM(dst,src,off) +#define p_pfcmpeqm(dst,src,off) P_PFCMPEQM(dst,src,off) +#define p_pfcmpgem(dst,src,off) P_PFCMPGEM(dst,src,off) +#define p_pfcmpgtm(dst,src,off) P_PFCMPGTM(dst,src,off) +#define p_pfmaxm(dst,src,off) P_PFMAXM(dst,src,off) +#define p_pfminm(dst,src,off) P_PFMINM(dst,src,off) +#define p_pfmulm(dst,src,off) P_PFMULM(dst,src,off) +#define p_pfrcpm(dst,src,off) P_PFRCPM(dst,src,off) +#define p_pfrcpit1m(dst,src,off) P_PFRCPIT1M(dst,src,off) +#define p_pfrcpit2m(dst,src,off) P_PFRCPIT2M(dst,src,off) +#define p_pfrsqrtm(dst,src,off) P_PFRSQRTM(dst,src,off) +#define p_pfrsqit1m(dst,src,off) P_PFRSQIT1M(dst,src,off) +#define p_pfsubm(dst,src,off) P_PFSUBM(dst,src,off) +#define p_pfsubrm(dst,src,off) P_PFSUBRM(dst,src,off) +#define p_pi2fdm(dst,src,off) P_PI2FDM(dst,src,off) +#define p_pavgusbm(dst,src,off) P_PAVGUSBM(dst,src,off) +#define p_pmulhrwm(dst,src,off) P_PMULHRWM(dst,src,off) + +#define P_PFNACC(dst,src) p_pfnacc(dst,src) +#define P_FPPNACC(dst,src) p_pfpnacc(dst,src) +#define P_PSWAPD(dst,src) p_pswapd(dst,src) +#define P_PMINUB(dst,src) p_pminub(dst,src) +#define P_PMAXUB(dst,src) p_pmaxub(dst,src) +#define P_PMINSW(dst,src) p_pminsw(dst,src) +#define P_PMAXSW(dst,src) p_pmaxsw(dst,src) +#define P_PMULHUW(dst,src) p_pmulhuw(dst,src) +#define P_PAVGB(dst,src) p_pavgb(dst,src) +#define P_PAVGW(dst,src) p_avgw(dst,src) +#define P_PSADBW(dst,src) p_psadbw(dst,src) +#define P_PMOVMSKB(dst,src) p_pmovmskb(dst,src) +#define P_PMASKMOVQ(dst,src) p_pmaskmovq(dst,src) +#define P_PINSRW(dst,src,msk) p_pinsrw(dst,src) +#define P_PEXTRW(dst,src,msk) p_pextrw(dst,src) +#define P_PSHUFW(dst,src,msk) p_pshufw(dst,src) +#define P_MOVNTQ(dst,src) p_movntq(dst,src) + +#define P_PFNACCM(dst,src,off) p_pfnaccm(dst,src,off) +#define P_FPPNACCM(dst,src,off) p_pfpnaccm(dst,src,off) +#define P_PSWAPDM(dst,src,off) p_pswapdm(dst,src,off) +#define P_PMINUBM(dst,src,off) p_pminubm(dst,src,off) +#define P_PMAXUBM(dst,src,off) p_pmaxubm(dst,src,off) +#define P_PMINSWM(dst,src,off) p_pminswm(dst,src,off) +#define P_PMAXSWM(dst,src,off) p_pmaxswm(dst,src,off) +#define P_PMULHUWM(dst,src,off) p_pmulhuwm(dst,src,off) +#define P_PAVGBM(dst,src,off) p_pavgbm(dst,src,off) +#define P_PAVGWM(dst,src,off) p_avgwm(dst,src,off) +#define P_PSADBWM(dst,src,off) p_psadbwm(dst,src,off) +#define P_PMOVMSKBM(dst,src,off) p_pmovmskbm(dst,src,off) +#define P_PMASKMOVQM(dst,src,off) p_pmaskmovqm(dst,src,off) +#define P_PINSRWM(dst,src,off,msk) p_pinsrwm(dst,src,off,msk) +#define P_PSHUFWM(dst,src,off,msk) p_pshufwm(dst,src,off,msk) +#define P_MOVNTQM(dst,src,off) p_movntqm(dst,src,off) + +#elif defined (_MSC_VER) && !defined (__MWERKS__) +// The Microsoft Visual C++ version of the 3DNow! macros. + +// Stop the "no EMMS" warning, since it doesn't detect FEMMS properly +#ifdef _WIN32 +#pragma warning(disable:4799) +#endif + +// Defines for operands. +#define _K3D_MM0 0xc0 +#define _K3D_MM1 0xc1 +#define _K3D_MM2 0xc2 +#define _K3D_MM3 0xc3 +#define _K3D_MM4 0xc4 +#define _K3D_MM5 0xc5 +#define _K3D_MM6 0xc6 +#define _K3D_MM7 0xc7 +#define _K3D_mm0 0xc0 +#define _K3D_mm1 0xc1 +#define _K3D_mm2 0xc2 +#define _K3D_mm3 0xc3 +#define _K3D_mm4 0xc4 +#define _K3D_mm5 0xc5 +#define _K3D_mm6 0xc6 +#define _K3D_mm7 0xc7 +#define _K3D_EAX 0x00 +#define _K3D_ECX 0x01 +#define _K3D_EDX 0x02 +#define _K3D_EBX 0x03 +#define _K3D_ESI 0x06 +#define _K3D_EDI 0x07 +#define _K3D_eax 0x00 +#define _K3D_ecx 0x01 +#define _K3D_edx 0x02 +#define _K3D_ebx 0x03 +#define _K3D_esi 0x06 +#define _K3D_edi 0x07 + +// These defines are for compatibility with the previous version of the header file. +#define _K3D_M0 0xc0 +#define _K3D_M1 0xc1 +#define _K3D_M2 0xc2 +#define _K3D_M3 0xc3 +#define _K3D_M4 0xc4 +#define _K3D_M5 0xc5 +#define _K3D_M6 0xc6 +#define _K3D_M7 0xc7 +#define _K3D_m0 0xc0 +#define _K3D_m1 0xc1 +#define _K3D_m2 0xc2 +#define _K3D_m3 0xc3 +#define _K3D_m4 0xc4 +#define _K3D_m5 0xc5 +#define _K3D_m6 0xc6 +#define _K3D_m7 0xc7 +#define _K3D__EAX 0x00 +#define _K3D__ECX 0x01 +#define _K3D__EDX 0x02 +#define _K3D__EBX 0x03 +#define _K3D__ESI 0x06 +#define _K3D__EDI 0x07 +#define _K3D__eax 0x00 +#define _K3D__ecx 0x01 +#define _K3D__edx 0x02 +#define _K3D__ebx 0x03 +#define _K3D__esi 0x06 +#define _K3D__edi 0x07 + +// General 3DNow! instruction format that is supported by +// these macros. Note that only the most basic form of memory +// operands are supported by these macros. + +#define InjK3DOps(dst,src,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0f \ + _asm _emit ((_K3D_##dst & 0x3f) << 3) | _K3D_##src \ + _asm _emit _3DNowOpcode##inst \ +} + +#define InjK3DMOps(dst,src,off,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0f \ + _asm _emit (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40) \ + _asm _emit off \ + _asm _emit _3DNowOpcode##inst \ +} + +#define InjMMXOps(dst,src,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit _3DNowOpcode##inst \ + _asm _emit ((_K3D_##dst & 0x3f) << 3) | _K3D_##src \ +} + +#define InjMMXMOps(dst,src,off,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit _3DNowOpcode##inst \ + _asm _emit (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40) \ + _asm _emit off \ +} + +#define _3DNowOpcodePF2ID 0x1d +#define _3DNowOpcodePFACC 0xae +#define _3DNowOpcodePFADD 0x9e +#define _3DNowOpcodePFCMPEQ 0xb0 +#define _3DNowOpcodePFCMPGE 0x90 +#define _3DNowOpcodePFCMPGT 0xa0 +#define _3DNowOpcodePFMAX 0xa4 +#define _3DNowOpcodePFMIN 0x94 +#define _3DNowOpcodePFMUL 0xb4 +#define _3DNowOpcodePFRCP 0x96 +#define _3DNowOpcodePFRCPIT1 0xa6 +#define _3DNowOpcodePFRCPIT2 0xb6 +#define _3DNowOpcodePFRSQRT 0x97 +#define _3DNowOpcodePFRSQIT1 0xa7 +#define _3DNowOpcodePFSUB 0x9a +#define _3DNowOpcodePFSUBR 0xaa +#define _3DNowOpcodePI2FD 0x0d +#define _3DNowOpcodePAVGUSB 0xbf +#define _3DNowOpcodePMULHRW 0xb7 +#define _3DNowOpcodePFNACC 0x8a +#define _3DNowOpcodeFPPNACC 0x8e +#define _3DNowOpcodePSWAPD 0xbb +#define _3DNowOpcodePMINUB 0xda +#define _3DNowOpcodePMAXUB 0xde +#define _3DNowOpcodePMINSW 0xea +#define _3DNowOpcodePMAXSW 0xee +#define _3DNowOpcodePMULHUW 0xe4 +#define _3DNowOpcodePAVGB 0xe0 +#define _3DNowOpcodePAVGW 0xe3 +#define _3DNowOpcodePSADBW 0xf6 +#define _3DNowOpcodePMOVMSKB 0xd7 +#define _3DNowOpcodePMASKMOVQ 0xf7 +#define _3DNowOpcodePINSRW 0xc4 +#define _3DNowOpcodePEXTRW 0xc5 +#define _3DNowOpcodePSHUFW 0x70 +#define _3DNowOpcodeMOVNTQ 0xe7 +#define _3DNowOpcodePREFETCHT 0x18 + + +#define PF2ID(dst,src) InjK3DOps(dst, src, PF2ID) +#define PFACC(dst,src) InjK3DOps(dst, src, PFACC) +#define PFADD(dst,src) InjK3DOps(dst, src, PFADD) +#define PFCMPEQ(dst,src) InjK3DOps(dst, src, PFCMPEQ) +#define PFCMPGE(dst,src) InjK3DOps(dst, src, PFCMPGE) +#define PFCMPGT(dst,src) InjK3DOps(dst, src, PFCMPGT) +#define PFMAX(dst,src) InjK3DOps(dst, src, PFMAX) +#define PFMIN(dst,src) InjK3DOps(dst, src, PFMIN) +#define PFMUL(dst,src) InjK3DOps(dst, src, PFMUL) +#define PFRCP(dst,src) InjK3DOps(dst, src, PFRCP) +#define PFRCPIT1(dst,src) InjK3DOps(dst, src, PFRCPIT1) +#define PFRCPIT2(dst,src) InjK3DOps(dst, src, PFRCPIT2) +#define PFRSQRT(dst,src) InjK3DOps(dst, src, PFRSQRT) +#define PFRSQIT1(dst,src) InjK3DOps(dst, src, PFRSQIT1) +#define PFSUB(dst,src) InjK3DOps(dst, src, PFSUB) +#define PFSUBR(dst,src) InjK3DOps(dst, src, PFSUBR) +#define PI2FD(dst,src) InjK3DOps(dst, src, PI2FD) +#define PAVGUSB(dst,src) InjK3DOps(dst, src, PAVGUSB) +#define PMULHRW(dst,src) InjK3DOps(dst, src, PMULHRW) + +#define FEMMS \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0e \ +} + +#define PREFETCH(src) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (_K3D_##src & 0x07) \ +} + +/* Prefetch with a short offset, < 127 or > -127 + Carefull! Doesn't check for your offset being + in range. */ + +#define PREFETCHM(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (0x40 | (_K3D_##src & 0x07)) \ + _asm _emit off \ +} + +/* Prefetch with a long offset */ + +#define PREFETCHMLONG(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (0x80 | (_K3D_##src & 0x07)) \ + _asm _emit (off & 0x000000ff) \ + _asm _emit (off & 0x0000ff00) >> 8 \ + _asm _emit (off & 0x00ff0000) >> 16 \ + _asm _emit (off & 0xff000000) >> 24 \ +} + +#define PREFETCHW(src) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (0x08 | (_K3D_##src & 0x07)) \ +} + +#define PREFETCHWM(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit 0x48 | (_K3D_##src & 0x07) \ + _asm _emit off \ +} + +#define PREFETCHWMLONG(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit 0x88 | (_K3D_##src & 0x07) \ + _asm _emit (off & 0x000000ff) \ + _asm _emit (off & 0x0000ff00) >> 8 \ + _asm _emit (off & 0x00ff0000) >> 16 \ + _asm _emit (off & 0xff000000) >> 24 \ +} + +#define CPUID \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0xa2 \ +} + + +/* Defines for new, K7 opcodes */ +#define SFENCE \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0xae \ + _asm _emit 0xf8 \ +} + +#define PFNACC(dst,src) InjK3DOps(dst,src,PFNACC) +#define PFPNACC(dst,src) InjK3DOps(dst,src,PFPNACC) +#define PSWAPD(dst,src) InjK3DOps(dst,src,PSWAPD) +#define PMINUB(dst,src) InjMMXOps(dst,src,PMINUB) +#define PMAXUB(dst,src) InjMMXOps(dst,src,PMAXUB) +#define PMINSW(dst,src) InjMMXOps(dst,src,PMINSW) +#define PMAXSW(dst,src) InjMMXOps(dst,src,PMAXSW) +#define PMULHUW(dst,src) InjMMXOps(dst,src,PMULHUW) +#define PAVGB(dst,src) InjMMXOps(dst,src,PAVGB) +#define PAVGW(dst,src) InjMMXOps(dst,src,PAVGW) +#define PSADBW(dst,src) InjMMXOps(dst,src,PSADBW) +#define PMOVMSKB(dst,src) InjMMXOps(dst,src,PMOVMSKB) +#define PMASKMOVQ(dst,src) InjMMXOps(dst,src,PMASKMOVQ) +#define PINSRW(dst,src,msk) InjMMXOps(dst,src,PINSRW) _asm _emit msk +#define PEXTRW(dst,src,msk) InjMMXOps(dst,src,PEXTRW) _asm _emit msk +#define PSHUFW(dst,src,msk) InjMMXOps(dst,src,PSHUFW) _asm _emit msk +#define MOVNTQ(dst,src) InjMMXOps(src,dst,MOVNTQ) +#define PREFETCHNTA(mem) InjMMXOps(mm0,mem,PREFETCHT) +#define PREFETCHT0(mem) InjMMXOps(mm1,mem,PREFETCHT) +#define PREFETCHT1(mem) InjMMXOps(mm2,mem,PREFETCHT) +#define PREFETCHT2(mem) InjMMXOps(mm3,mem,PREFETCHT) + + +/* Memory/offset versions of the opcodes */ +#define PAVGUSBM(dst,src,off) InjK3DMOps(dst,src,off,PAVGUSB) +#define PF2IDM(dst,src,off) InjK3DMOps(dst,src,off,PF2ID) +#define PFACCM(dst,src,off) InjK3DMOps(dst,src,off,PFACC) +#define PFADDM(dst,src,off) InjK3DMOps(dst,src,off,PFADD) +#define PFCMPEQM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPEQ) +#define PFCMPGEM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPGE) +#define PFCMPGTM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPGT) +#define PFMAXM(dst,src,off) InjK3DMOps(dst,src,off,PFMAX) +#define PFMINM(dst,src,off) InjK3DMOps(dst,src,off,PFMIN) +#define PFMULM(dst,src,off) InjK3DMOps(dst,src,off,PFMUL) +#define PFRCPM(dst,src,off) InjK3DMOps(dst,src,off,PFRCP) +#define PFRCPIT1M(dst,src,off) InjK3DMOps(dst,src,off,PFRCPIT1) +#define PFRCPIT2M(dst,src,off) InjK3DMOps(dst,src,off,PFRCPIT2) +#define PFRSQRTM(dst,src,off) InjK3DMOps(dst,src,off,PFRSQRT) +#define PFRSQIT1M(dst,src,off) InjK3DMOps(dst,src,off,PFRSQIT1) +#define PFSUBM(dst,src,off) InjK3DMOps(dst,src,off,PFSUB) +#define PFSUBRM(dst,src,off) InjK3DMOps(dst,src,off,PFSUBR) +#define PI2FDM(dst,src,off) InjK3DMOps(dst,src,off,PI2FD) +#define PMULHRWM(dst,src,off) InjK3DMOps(dst,src,off,PMULHRW) + + +/* Memory/offset versions of the K7 opcodes */ +#define PFNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFNACC) +#define PFPNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFPNACC) +#define PSWAPDM(dst,src,off) InjK3DMOps(dst,src,off,PSWAPD) +#define PMINUBM(dst,src,off) InjMMXMOps(dst,src,off,PMINUB) +#define PMAXUBM(dst,src,off) InjMMXMOps(dst,src,off,PMAXUB) +#define PMINSWM(dst,src,off) InjMMXMOps(dst,src,off,PMINSW) +#define PMAXSWM(dst,src,off) InjMMXMOps(dst,src,off,PMAXSW) +#define PMULHUWM(dst,src,off) InjMMXMOps(dst,src,off,PMULHUW) +#define PAVGBM(dst,src,off) InjMMXMOps(dst,src,off,PAVGB) +#define PAVGWM(dst,src,off) InjMMXMOps(dst,src,off,PAVGW) +#define PSADBWM(dst,src,off) InjMMXMOps(dst,src,off,PSADBW) +#define PMOVMSKBM(dst,src,off) InjMMXMOps(dst,src,off,PMOVMSKB) +#define PMASKMOVQM(dst,src,off) InjMMXMOps(dst,src,off,PMASKMOVQ) +#define PINSRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PINSRW) _asm _emit msk +#define PSHUFWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PSHUFW) _asm _emit msk +#define MOVNTQM(dst,src,off) InjMMXMOps(src,dst,off,MOVNTQ) +#define PREFETCHNTAM(mem,off) InjMMXMOps(mm0,mem,off,PREFETCHT) +#define PREFETCHT0M(mem,off) InjMMXMOps(mm1,mem,off,PREFETCHT) +#define PREFETCHT1M(mem,off) InjMMXMOps(mm2,mem,off,PREFETCHT) +#define PREFETCHT2M(mem,off) InjMMXMOps(mm3,mem,off,PREFETCHT) + + +#else + +/* Assume built-in support for 3DNow! opcodes, replace macros with opcodes */ +#define PAVGUSB(dst,src) pavgusb dst,src +#define PF2ID(dst,src) pf2id dst,src +#define PFACC(dst,src) pfacc dst,src +#define PFADD(dst,src) pfadd dst,src +#define PFCMPEQ(dst,src) pfcmpeq dst,src +#define PFCMPGE(dst,src) pfcmpge dst,src +#define PFCMPGT(dst,src) pfcmpgt dst,src +#define PFMAX(dst,src) pfmax dst,src +#define PFMIN(dst,src) pfmin dst,src +#define PFMUL(dst,src) pfmul dst,src +#define PFRCP(dst,src) pfrcp dst,src +#define PFRCPIT1(dst,src) pfrcpit1 dst,src +#define PFRCPIT2(dst,src) pfrcpit2 dst,src +#define PFRSQRT(dst,src) pfrsqrt dst,src +#define PFRSQIT1(dst,src) pfrsqit1 dst,src +#define PFSUB(dst,src) pfsub dst,src +#define PFSUBR(dst,src) pfsubr dst,src +#define PI2FD(dst,src) pi2fd dst,src +#define PMULHRW(dst,src) pmulhrw dst,src +#define PREFETCH(src) prefetch src +#define PREFETCHW(src) prefetchw src + +#define PAVGUSBM(dst,src,off) pavgusb dst,[src+off] +#define PF2IDM(dst,src,off) PF2ID dst,[src+off] +#define PFACCM(dst,src,off) PFACC dst,[src+off] +#define PFADDM(dst,src,off) PFADD dst,[src+off] +#define PFCMPEQM(dst,src,off) PFCMPEQ dst,[src+off] +#define PFCMPGEM(dst,src,off) PFCMPGE dst,[src+off] +#define PFCMPGTM(dst,src,off) PFCMPGT dst,[src+off] +#define PFMAXM(dst,src,off) PFMAX dst,[src+off] +#define PFMINM(dst,src,off) PFMIN dst,[src+off] +#define PFMULM(dst,src,off) PFMUL dst,[src+off] +#define PFRCPM(dst,src,off) PFRCP dst,[src+off] +#define PFRCPIT1M(dst,src,off) PFRCPIT1 dst,[src+off] +#define PFRCPIT2M(dst,src,off) PFRCPIT2 dst,[src+off] +#define PFRSQRTM(dst,src,off) PFRSQRT dst,[src+off] +#define PFRSQIT1M(dst,src,off) PFRSQIT1 dst,[src+off] +#define PFSUBM(dst,src,off) PFSUB dst,[src+off] +#define PFSUBRM(dst,src,off) PFSUBR dst,[src+off] +#define PI2FDM(dst,src,off) PI2FD dst,[src+off] +#define PMULHRWM(dst,src,off) PMULHRW dst,[src+off] + + +#if defined (__MWERKS__) +// At the moment, CodeWarrior does not support these opcodes, so hand-assemble them + +// Defines for operands. +#define _K3D_MM0 0xc0 +#define _K3D_MM1 0xc1 +#define _K3D_MM2 0xc2 +#define _K3D_MM3 0xc3 +#define _K3D_MM4 0xc4 +#define _K3D_MM5 0xc5 +#define _K3D_MM6 0xc6 +#define _K3D_MM7 0xc7 +#define _K3D_mm0 0xc0 +#define _K3D_mm1 0xc1 +#define _K3D_mm2 0xc2 +#define _K3D_mm3 0xc3 +#define _K3D_mm4 0xc4 +#define _K3D_mm5 0xc5 +#define _K3D_mm6 0xc6 +#define _K3D_mm7 0xc7 +#define _K3D_EAX 0x00 +#define _K3D_ECX 0x01 +#define _K3D_EDX 0x02 +#define _K3D_EBX 0x03 +#define _K3D_ESI 0x06 +#define _K3D_EDI 0x07 +#define _K3D_eax 0x00 +#define _K3D_ecx 0x01 +#define _K3D_edx 0x02 +#define _K3D_ebx 0x03 +#define _K3D_esi 0x06 +#define _K3D_edi 0x07 +#define _K3D_EAX 0x00 +#define _K3D_ECX 0x01 +#define _K3D_EDX 0x02 +#define _K3D_EBX 0x03 +#define _K3D_ESI 0x06 +#define _K3D_EDI 0x07 +#define _K3D_eax 0x00 +#define _K3D_ecx 0x01 +#define _K3D_edx 0x02 +#define _K3D_ebx 0x03 +#define _K3D_esi 0x06 +#define _K3D_edi 0x07 + +#define InjK3DOps(dst,src,inst) \ + db 0x0f, 0x0f, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src), _3DNowOpcode##inst + +#define InjK3DMOps(dst,src,off,inst) \ + db 0x0f, 0x0f, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40), off, _3DNowOpcode##inst + +#define InjMMXOps(dst,src,inst) \ + db 0x0f, _3DNowOpcode##inst, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src) + +#define InjMMXMOps(dst,src,off,inst) \ + db 0x0f, _3DNowOpcode##inst, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40), off + +#define PFNACC(dst,src) InjK3DOps(dst,src,PFNACC) +#define PFPNACC(dst,src) InjK3DOps(dst,src,PFPNACC) +#define PSWAPD(dst,src) InjK3DOps(dst,src,PSWAPD) +#define PMINUB(dst,src) InjMMXOps(dst,src,PMINUB) +#define PMAXUB(dst,src) InjMMXOps(dst,src,PMAXUB) +#define PMINSW(dst,src) InjMMXOps(dst,src,PMINSW) +#define PMAXSW(dst,src) InjMMXOps(dst,src,PMAXSW) +#define PMULHUW(dst,src) InjMMXOps(dst,src,PMULHUW) +#define PAVGB(dst,src) InjMMXOps(dst,src,PAVGB) +#define PAVGW(dst,src) InjMMXOps(dst,src,PAVGW) +#define PSADBW(dst,src) InjMMXOps(dst,src,PSADBW) +#define PMOVMSKB(dst,src) InjMMXOps(dst,src,PMOVMSKB) +#define PMASKMOVQ(dst,src) InjMMXOps(dst,src,PMASKMOVQ) +#define PINSRW(dst,src,msk) InjMMXOps(dst,src,PINSRW) db msk +#define PEXTRW(dst,src,msk) InjMMXOps(dst,src,PEXTRW) db msk +#define PSHUFW(dst,src,msk) InjMMXOps(dst,src,PSHUFW) db msk +#define MOVNTQ(dst,src) InjMMXOps(src,dst,MOVNTQ) +#define PREFETCHNTA(mem) InjMMXOps(mm0,mem,PREFETCHT) +#define PREFETCHT0(mem) InjMMXOps(mm1,mem,PREFETCHT) +#define PREFETCHT1(mem) InjMMXOps(mm2,mem,PREFETCHT) +#define PREFETCHT2(mem) InjMMXOps(mm3,mem,PREFETCHT) + + +/* Memory/offset versions of the K7 opcodes */ +#define PFNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFNACC) +#define PFPNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFPNACC) +#define PSWAPDM(dst,src,off) InjK3DMOps(dst,src,off,PSWAPD) +#define PMINUBM(dst,src,off) InjMMXMOps(dst,src,off,PMINUB) +#define PMAXUBM(dst,src,off) InjMMXMOps(dst,src,off,PMAXUB) +#define PMINSWM(dst,src,off) InjMMXMOps(dst,src,off,PMINSW) +#define PMAXSWM(dst,src,off) InjMMXMOps(dst,src,off,PMAXSW) +#define PMULHUWM(dst,src,off) InjMMXMOps(dst,src,off,PMULHUW) +#define PAVGBM(dst,src,off) InjMMXMOps(dst,src,off,PAVGB) +#define PAVGWM(dst,src,off) InjMMXMOps(dst,src,off,PAVGW) +#define PSADBWM(dst,src,off) InjMMXMOps(dst,src,off,PSADBW) +#define PMOVMSKBM(dst,src,off) InjMMXMOps(dst,src,off,PMOVMSKB) +#define PMASKMOVQM(dst,src,off) InjMMXMOps(dst,src,off,PMASKMOVQ) +#define PINSRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PINSRW), msk +#define PEXTRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PEXTRW), msk +#define PSHUFWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PSHUFW), msk +#define MOVNTQM(dst,src,off) InjMMXMOps(src,dst,off,MOVNTQ) +#define PREFETCHNTAM(mem,off) InjMMXMOps(mm0,mem,off,PREFETCHT) +#define PREFETCHT0M(mem,off) InjMMXMOps(mm1,mem,off,PREFETCHT) +#define PREFETCHT1M(mem,off) InjMMXMOps(mm2,mem,off,PREFETCHT) +#define PREFETCHT2M(mem,off) InjMMXMOps(mm3,mem,off,PREFETCHT) + + +#else + +#define PFNACC(dst,src) PFNACC dst,src +#define PFPNACC(dst,src) PFPNACC dst,src +#define PSWAPD(dst,src) PSWAPD dst,src +#define PMINUB(dst,src) PMINUB dst,src +#define PMAXUB(dst,src) PMAXUB dst,src +#define PMINSW(dst,src) PMINSW dst,src +#define PMAXSW(dst,src) PMAXSW dst,src +#define PMULHUW(dst,src) PMULHUW dst,src +#define PAVGB(dst,src) PAVGB dst,src +#define PAVGW(dst,src) PAVGW dst,src +#define PSADBW(dst,src) PSADBW dst,src +#define PMOVMSKB(dst,src) PMOVMSKB dst,src +#define PMASKMOVQ(dst,src) PMASKMOVQ dst,src +#define PINSRW(dst,src,msk) PINSRW dst,src,msk +#define PEXTRW(dst,src,msk) PEXTRW dst,src,msk +#define PSHUFW(dst,src,msk) PSHUFW dst,src,msk +#define MOVNTQ(dst,src) MOVNTQ dst,src + +#define PFNACCM(dst,src,off) PFNACC dst,[src+off] +#define PFPNACCM(dst,src,off) PFPNACC dst,[src+off] +#define PSWAPDM(dst,src,off) PSWAPD dst,[src+off] +#define PMINUBM(dst,src,off) PMINUB dst,[src+off] +#define PMAXUBM(dst,src,off) PMAXUB dst,[src+off] +#define PMINSWM(dst,src,off) PMINSW dst,[src+off] +#define PMAXSWM(dst,src,off) PMAXSW dst,[src+off] +#define PMULHUWM(dst,src,off) PMULHUW dst,[src+off] +#define PAVGBM(dst,src,off) PAVGB dst,[src+off] +#define PAVGWM(dst,src,off) PAVGW dst,[src+off] +#define PSADBWM(dst,src,off) PSADBW dst,[src+off] +#define PMOVMSKBM(dst,src,off) PMOVMSKB dst,[src+off] +#define PMASKMOVQM(dst,src,off) PMASKMOVQ dst,[src+off] +#define PINSRWM(dst,src,off,msk) PINSRW dst,[src+off],msk +#define PEXTRWM(dst,src,off,msk) PEXTRW dst,[src+off],msk +#define PSHUFWM(dst,src,off,msk) PSHUFW dst,[src+off],msk +#define MOVNTQM(dst,src,off) MOVNTQ dst,[src+off] + +#endif + +#endif + +/* Just to deal with lower case. */ +#define pf2id(dst,src) PF2ID(dst,src) +#define pfacc(dst,src) PFACC(dst,src) +#define pfadd(dst,src) PFADD(dst,src) +#define pfcmpeq(dst,src) PFCMPEQ(dst,src) +#define pfcmpge(dst,src) PFCMPGE(dst,src) +#define pfcmpgt(dst,src) PFCMPGT(dst,src) +#define pfmax(dst,src) PFMAX(dst,src) +#define pfmin(dst,src) PFMIN(dst,src) +#define pfmul(dst,src) PFMUL(dst,src) +#define pfrcp(dst,src) PFRCP(dst,src) +#define pfrcpit1(dst,src) PFRCPIT1(dst,src) +#define pfrcpit2(dst,src) PFRCPIT2(dst,src) +#define pfrsqrt(dst,src) PFRSQRT(dst,src) +#define pfrsqit1(dst,src) PFRSQIT1(dst,src) +#define pfsub(dst,src) PFSUB(dst,src) +#define pfsubr(dst,src) PFSUBR(dst,src) +#define pi2fd(dst,src) PI2FD(dst,src) +#define femms FEMMS +#define pavgusb(dst,src) PAVGUSB(dst,src) +#define pmulhrw(dst,src) PMULHRW(dst,src) +#define prefetch(src) PREFETCH(src) +#define prefetchw(src) PREFETCHW(src) + +#define prefetchm(src,off) PREFETCHM(src,off) +#define prefetchmlong(src,off) PREFETCHMLONG(src,off) +#define prefetchwm(src,off) PREFETCHWM(src,off) +#define prefetchwmlong(src,off) PREFETCHWMLONG(src,off) + +#define pfnacc(dst,src) PFNACC(dst,src) +#define pfpnacc(dst,src) PFPNACC(dst,src) +#define pswapd(dst,src) PSWAPD(dst,src) +#define pminub(dst,src) PMINUB(dst,src) +#define pmaxub(dst,src) PMAXUB(dst,src) +#define pminsw(dst,src) PMINSW(dst,src) +#define pmaxsw(dst,src) PMAXSW(dst,src) +#define pmulhuw(dst,src) PMULHUW(dst,src) +#define pavgb(dst,src) PAVGB(dst,src) +#define pavgw(dst,src) PAVGW(dst,src) +#define psadbw(dst,src) PSADBW(dst,src) +#define pmovmskb(dst,src) PMOVMSKB(dst,src) +#define pmaskmovq(dst,src) PMASKMOVQ(dst,src) +#define pinsrw(dst,src,msk) PINSRW(dst,src,msk) +#define pextrw(dst,src,msk) PEXTRW(dst,src,msk) +#define pshufw(dst,src,msk) PSHUFW(dst,src,msk) +#define movntq(dst,src) MOVNTQ(dst,src) +#define prefetchnta(mem) PREFETCHNTA(mem) +#define prefetcht0(mem) PREFETCHT0(mem) +#define prefetcht1(mem) PREFETCHT1(mem) +#define prefetcht2(mem) PREFETCHT2(mem) + + +#define pavgusbm(dst,src,off) PAVGUSBM(dst,src,off) +#define pf2idm(dst,src,off) PF2IDM(dst,src,off) +#define pfaccm(dst,src,off) PFACCM(dst,src,off) +#define pfaddm(dst,src,off) PFADDM(dst,src,off) +#define pfcmpeqm(dst,src,off) PFCMPEQM(dst,src,off) +#define pfcmpgem(dst,src,off) PFCMPGEM(dst,src,off) +#define pfcmpgtm(dst,src,off) PFCMPGTM(dst,src,off) +#define pfmaxm(dst,src,off) PFMAXM(dst,src,off) +#define pfminm(dst,src,off) PFMINM(dst,src,off) +#define pfmulm(dst,src,off) PFMULM(dst,src,off) +#define pfrcpm(dst,src,off) PFRCPM(dst,src,off) +#define pfrcpit1m(dst,src,off) PFRCPIT1M(dst,src,off) +#define pfrcpit2m(dst,src,off) PFRCPIT2M(dst,src,off) +#define pfrsqrtm(dst,src,off) PFRSQRTM(dst,src,off) +#define pfrsqit1m(dst,src,off) PFRSQIT1M(dst,src,off) +#define pfsubm(dst,src,off) PFSUBM(dst,src,off) +#define pfsubrm(dst,src,off) PFSUBRM(dst,src,off) +#define pi2fdm(dst,src,off) PI2FDM(dst,src,off) +#define pmulhrwm(dst,src,off) PMULHRWM(dst,src,off) +#define cpuid CPUID +#define sfence SFENCE + +#define pfnaccm(dst,src,off) PFNACCM(dst,src,off) +#define pfpnaccm(dst,src,off) PFPNACCM(dst,src,off) +#define pswapdm(dst,src,off) PSWAPDM(dst,src,off) +#define pminubm(dst,src,off) PMINUBM(dst,src,off) +#define pmaxubm(dst,src,off) PMAXUBM(dst,src,off) +#define pminswm(dst,src,off) PMINSWM(dst,src,off) +#define pmaxswm(dst,src,off) PMAXSWM(dst,src,off) +#define pmulhuwm(dst,src,off) PMULHUWM(dst,src,off) +#define pavgbm(dst,src,off) PAVGBM(dst,src,off) +#define pavgwm(dst,src,off) PAVGWM(dst,src,off) +#define psadbwm(dst,src,off) PSADBWM(dst,src,off) +#define pmovmskbm(dst,src,off) PMOVMSKBM(dst,src,off) +#define pmaskmovqm(dst,src,off) PMASKMOVQM(dst,src,off) +#define pinsrwm(dst,src,off,msk) PINSRWM(dst,src,off,msk) +#define pextrwm(dst,src,off,msk) PEXTRWM(dst,src,off,msk) +#define pshufwm(dst,src,off,msk) PSHUFWM(dst,src,off,msk) +#define movntqm(dst,src,off) MOVNTQM(dst,src,off) +#define prefetchntam(mem,off) PREFETCHNTA(mem,off) +#define prefetcht0m(mem,off) PREFETCHT0(mem,off) +#define prefetcht1m(mem,off) PREFETCHT1(mem,off) +#define prefetcht2m(mem,off) PREFETCHT2(mem,off) + +#endif diff --git a/public/mathlib/compressed_3d_unitvec.h b/public/mathlib/compressed_3d_unitvec.h index f118ae17..daffd943 100644 --- a/public/mathlib/compressed_3d_unitvec.h +++ b/public/mathlib/compressed_3d_unitvec.h @@ -8,6 +8,7 @@ #ifndef _3D_UNITVEC_H #define _3D_UNITVEC_H +#include #define UNITVEC_DECLARE_STATICS \ float cUnitVector::mUVAdjustment[0x2000]; \ @@ -75,8 +76,8 @@ public: // a little slower... old pack was 4 multiplies and 2 adds. // This is 2 multiplies, 2 adds, and a divide.... float w = 126.0f / ( tmp.x + tmp.y + tmp.z ); - long xbits = (long)( tmp.x * w ); - long ybits = (long)( tmp.y * w ); + int32_t xbits = (int32_t)( tmp.x * w ); + int32_t ybits = (int32_t)( tmp.y * w ); Assert( xbits < 127 ); Assert( xbits >= 0 ); @@ -110,8 +111,8 @@ public: // multiplication // get the x and y bits - long xbits = (( mVec & TOP_MASK ) >> 7 ); - long ybits = ( mVec & BOTTOM_MASK ); + int32_t xbits = (( mVec & TOP_MASK ) >> 7 ); + int32_t ybits = ( mVec & BOTTOM_MASK ); // map the numbers back to the triangle (0,0)-(0,126)-(126,0) if (( xbits + ybits ) >= 127 ) @@ -139,8 +140,8 @@ public: { for ( int idx = 0; idx < 0x2000; idx++ ) { - long xbits = idx >> 7; - long ybits = idx & BOTTOM_MASK; + int32_t xbits = idx >> 7; + int32_t ybits = idx & BOTTOM_MASK; // map the numbers back to the triangle (0,0)-(0,127)-(127,0) if (( xbits + ybits ) >= 127 ) diff --git a/public/mathlib/compressed_vector.h b/public/mathlib/compressed_vector.h index a33601ae..cec37f41 100644 --- a/public/mathlib/compressed_vector.h +++ b/public/mathlib/compressed_vector.h @@ -58,8 +58,8 @@ inline Vector32& Vector32::operator=(const Vector &vOther) static float expScale[4] = { 4.0f, 16.0f, 32.f, 64.f }; - float fmax = MAX( fabs( vOther.x ), fabs( vOther.y ) ); - fmax = fpmax( fmax, fabs( vOther.z ) ); + float fmax = Max( fabs( vOther.x ), fabs( vOther.y ) ); + fmax = Max( fmax, (float)fabs( vOther.z ) ); for (exp = 0; exp < 3; exp++) { @@ -70,9 +70,9 @@ inline Vector32& Vector32::operator=(const Vector &vOther) float fexp = 512.0f / expScale[exp]; - x = clamp( (int)(vOther.x * fexp) + 512, 0, 1023 ); - y = clamp( (int)(vOther.y * fexp) + 512, 0, 1023 ); - z = clamp( (int)(vOther.z * fexp) + 512, 0, 1023 ); + x = Clamp( (int)(vOther.x * fexp) + 512, 0, 1023 ); + y = Clamp( (int)(vOther.y * fexp) + 512, 0, 1023 ); + z = Clamp( (int)(vOther.z * fexp) + 512, 0, 1023 ); return *this; } @@ -118,8 +118,8 @@ inline Normal32& Normal32::operator=(const Vector &vOther) { CHECK_VALID(vOther); - x = clamp( (int)(vOther.x * 16384) + 16384, 0, 32767 ); - y = clamp( (int)(vOther.y * 16384) + 16384, 0, 32767 ); + x = Clamp( (int)(vOther.x * 16384) + 16384, 0, 32767 ); + y = Clamp( (int)(vOther.y * 16384) + 16384, 0, 32767 ); zneg = (vOther.z < 0); //x = vOther.x; //y = vOther.y; @@ -182,9 +182,9 @@ inline Quaternion64& Quaternion64::operator=(const Quaternion &vOther) { CHECK_VALID(vOther); - x = clamp( (int)(vOther.x * 1048576) + 1048576, 0, 2097151 ); - y = clamp( (int)(vOther.y * 1048576) + 1048576, 0, 2097151 ); - z = clamp( (int)(vOther.z * 1048576) + 1048576, 0, 2097151 ); + x = Clamp( (int)(vOther.x * 1048576) + 1048576, 0, 2097151 ); + y = Clamp( (int)(vOther.y * 1048576) + 1048576, 0, 2097151 ); + z = Clamp( (int)(vOther.z * 1048576) + 1048576, 0, 2097151 ); wneg = (vOther.w < 0); return *this; } @@ -229,9 +229,9 @@ inline Quaternion48& Quaternion48::operator=(const Quaternion &vOther) { CHECK_VALID(vOther); - x = clamp( (int)(vOther.x * 32768) + 32768, 0, 65535 ); - y = clamp( (int)(vOther.y * 32768) + 32768, 0, 65535 ); - z = clamp( (int)(vOther.z * 16384) + 16384, 0, 32767 ); + x = Clamp( (int)(vOther.x * 32768) + 32768, 0, 65535 ); + y = Clamp( (int)(vOther.y * 32768) + 32768, 0, 65535 ); + z = Clamp( (int)(vOther.z * 16384) + 16384, 0, 32767 ); wneg = (vOther.w < 0); return *this; } @@ -276,9 +276,9 @@ inline Quaternion32& Quaternion32::operator=(const Quaternion &vOther) { CHECK_VALID(vOther); - x = clamp( (int)(vOther.x * 1024) + 1024, 0, 2047 ); - y = clamp( (int)(vOther.y * 512) + 512, 0, 1023 ); - z = clamp( (int)(vOther.z * 512) + 512, 0, 1023 ); + x = Clamp( (int)(vOther.x * 1024) + 1024, 0, 2047 ); + y = Clamp( (int)(vOther.y * 512) + 512, 0, 1023 ); + z = Clamp( (int)(vOther.z * 512) + 512, 0, 1023 ); wneg = (vOther.w < 0); return *this; } diff --git a/public/mathlib/lightdesc.h b/public/mathlib/lightdesc.h index 4ac74a43..d050dbc5 100644 --- a/public/mathlib/lightdesc.h +++ b/public/mathlib/lightdesc.h @@ -28,6 +28,7 @@ enum LightType_OptimizationFlags_t LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 = 1, LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 = 2, LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 = 4, + LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED = 8, }; struct LightDesc_t @@ -102,6 +103,11 @@ public: { return ((m_Type!=MATERIAL_LIGHT_SPOT) || (rdir.Dot(m_Direction)>=m_PhiDot)); } + + float OneOverThetaDotMinusPhiDot() const + { + return OneOver_ThetaDot_Minus_PhiDot; + } }; diff --git a/public/mathlib/math_pfns.h b/public/mathlib/math_pfns.h index 2fa0abfb..13bd3796 100644 --- a/public/mathlib/math_pfns.h +++ b/public/mathlib/math_pfns.h @@ -28,6 +28,14 @@ extern float (*pfFastCos)(float x); #define FastSinCos(x,s,c) (*pfFastSinCos)(x,s,c) #define FastCos(x) (*pfFastCos)(x) +#if defined(__i386__) || defined(_M_IX86) +// On x86, the inline FPU or SSE sqrt instruction is faster than +// the overhead of setting up a function call and saving/restoring +// the FPU or SSE register state and can be scheduled better, too. +#undef FastSqrt +#define FastSqrt(x) ::sqrtf(x) +#endif + #endif // !_X360 #if defined( _X360 ) diff --git a/public/mathlib/mathlib.h b/public/mathlib/mathlib.h index 4769bbab..e16bea59 100644 --- a/public/mathlib/mathlib.h +++ b/public/mathlib/mathlib.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -7,6 +7,7 @@ #ifndef MATH_LIB_H #define MATH_LIB_H +#include #include #include "tier0/basetypes.h" #include "mathlib/vector.h" @@ -15,6 +16,61 @@ #include "mathlib/math_pfns.h" +#if defined(__i386__) || defined(_M_IX86) +// For MMX intrinsics +#include +#endif + +// XXX remove me +#undef clamp + +#ifdef DEBUG // stop crashing edit-and-continue +FORCEINLINE float clamp( float val, float minVal, float maxVal ) +{ + if ( maxVal < minVal ) + return maxVal; + else if( val < minVal ) + return minVal; + else if( val > maxVal ) + return maxVal; + else + return val; +} +#else // DEBUG +FORCEINLINE float clamp( float val, float minVal, float maxVal ) +{ +#if defined(__i386__) || defined(_M_IX86) + _mm_store_ss( &val, + _mm_min_ss( + _mm_max_ss( + _mm_load_ss(&val), + _mm_load_ss(&minVal) ), + _mm_load_ss(&maxVal) ) ); +#else + val = fpmax(minVal, val); + val = fpmin(maxVal, val); +#endif + return val; +} +#endif // DEBUG + +// +// Returns a clamped value in the range [min, max]. +// +template< class T > +inline T clamp( T const &val, T const &minVal, T const &maxVal ) +{ + if ( maxVal < minVal ) + return maxVal; + else if( val < minVal ) + return minVal; + else if( val > maxVal ) + return maxVal; + else + return val; +} + + // plane_t structure // !!! if this is changed, it must be changed in asm code too !!! // FIXME: does the asm code even exist anymore? @@ -224,12 +280,12 @@ FORCEINLINE void VectorClear(vec_t *a) FORCEINLINE float VectorMaximum(const vec_t *v) { - return MAX( v[0], MAX( v[1], v[2] ) ); + return V_max( v[0], V_max( v[1], v[2] ) ); } FORCEINLINE float VectorMaximum(const Vector& v) { - return MAX( v.x, MAX( v.y, v.z ) ); + return V_max( v.x, V_max( v.y, v.z ) ); } FORCEINLINE void VectorScale (const float* in, vec_t scale, float* out) @@ -254,7 +310,7 @@ inline void VectorNegate(vec_t *a) } -//#define VectorMaximum(a) ( MAX( (a)[0], MAX( (a)[1], (a)[2] ) ) ) +//#define VectorMaximum(a) ( V_max( (a)[0], V_max( (a)[1], (a)[2] ) ) ) #define Vector2Clear(x) {(x)[0]=(x)[1]=0;} #define Vector2Negate(x) {(x)[0]=-((x)[0]);(x)[1]=-((x)[1]);} #define Vector2Copy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];} @@ -281,10 +337,10 @@ FORCEINLINE void VectorMAInline( const Vector& start, float scale, const Vector& dest.z=start.z+direction.z*scale; } -//FORCEINLINE void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ) -//{ -// VectorMAInline(start, scale, direction, dest); -//} +FORCEINLINE void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ) +{ + VectorMAInline(start, scale, direction, dest); +} FORCEINLINE void VectorMA( const float * start, float scale, const float *direction, float *dest ) { @@ -315,7 +371,7 @@ void inline SinCos( float radians, float *sine, float *cosine ) { #if defined( _X360 ) XMScalarSinCos( sine, cosine, radians ); -#elif defined( _WIN32 ) +#elif defined( PLATFORM_WINDOWS_PC32 ) _asm { fld DWORD PTR [radians] @@ -327,11 +383,12 @@ void inline SinCos( float radians, float *sine, float *cosine ) fstp DWORD PTR [edx] fstp DWORD PTR [eax] } -#elif defined( _LINUX ) || defined ( __APPLE__ ) - register double __cosr, __sinr; - __asm __volatile__ - ("fsincos" - : "=t" (__cosr), "=u" (__sinr) : "0" (radians)); +#elif defined( PLATFORM_WINDOWS_PC64 ) + *sine = sin( radians ); + *cosine = cos( radians ); +#elif defined( POSIX ) + double __cosr, __sinr; + __asm ("fsincos" : "=t" (__cosr), "=u" (__sinr) : "0" (radians)); *sine = __sinr; *cosine = __cosr; @@ -375,11 +432,6 @@ FORCEINLINE T Square( T const &a ) } -FORCEINLINE bool IsPowerOfTwo( uint x ) -{ - return ( x & ( x - 1 ) ) == 0; -} - // return the smallest power of two >= x. // returns 0 if x == 0 or x > 0x80000000 (ie numbers that would be negative if x was signed) // NOTE: the old code took an int, and if you pass in an int of 0x80000000 casted to a uint, @@ -446,6 +498,19 @@ bool MatricesAreEqual( const matrix3x4_t &src1, const matrix3x4_t &src2, float f void MatrixGetColumn( const matrix3x4_t &in, int column, Vector &out ); void MatrixSetColumn( const Vector &in, int column, matrix3x4_t &out ); +inline void MatrixGetTranslation( const matrix3x4_t &in, Vector &out ) +{ + MatrixGetColumn ( in, 3, out ); +} + +inline void MatrixSetTranslation( const Vector &in, matrix3x4_t &out ) +{ + MatrixSetColumn ( in, 3, out ); +} + +void MatrixScaleBy ( const float flScale, matrix3x4_t &out ); +void MatrixScaleByZero ( matrix3x4_t &out ); + //void DecomposeRotation( const matrix3x4_t &mat, float *out ); void ConcatRotations (const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out); void ConcatTransforms (const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out); @@ -606,7 +671,7 @@ template<> FORCEINLINE QAngleByValue Lerp( float flPercent, const #endif // VECTOR_NO_SLOW_OPERATIONS -// Swap two of anything. +/// Same as swap(), but won't cause problems with std::swap template FORCEINLINE void V_swap( T& x, T& y ) { @@ -621,15 +686,11 @@ template FORCEINLINE T AVG(T a, T b) } // number of elements in an array of static size -#define NELEMS(x) ((sizeof(x))/sizeof(x[0])) +#define NELEMS(x) ARRAYSIZE(x) // XYZ macro, for printf type functions - ex printf("%f %f %f",XYZ(myvector)); #define XYZ(v) (v).x,(v).y,(v).z -// -// Returns a clamped value in the range [min, max]. -// -#define V_clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val))) inline float Sign( float x ) { @@ -1066,13 +1127,15 @@ inline float SimpleSplineRemapValClamped( float val, float A, float B, float C, if ( A == B ) return val >= B ? D : C; float cVal = (val - A) / (B - A); - cVal = V_clamp( cVal, 0.0f, 1.0f ); + cVal = clamp( cVal, 0.0f, 1.0f ); return C + (D - C) * SimpleSpline( cVal ); } FORCEINLINE int RoundFloatToInt(float f) { -#if defined( _X360 ) +#if defined(__i386__) || defined(_M_IX86) || defined( PLATFORM_WINDOWS_PC64 ) || defined(__x86_64__) + return _mm_cvtss_si32(_mm_load_ss(&f)); +#elif defined( _X360 ) #ifdef Assert Assert( IsFPUControlWordSet() ); #endif @@ -1083,63 +1146,18 @@ FORCEINLINE int RoundFloatToInt(float f) }; flResult = __fctiw( f ); return pResult[1]; -#else // !X360 - int nResult; -#if defined( _WIN32 ) - __asm - { - fld f - fistp nResult - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - __asm __volatile__ ( - "fistpl %0;": "=m" (nResult): "t" (f) : "st" - ); -#endif - return nResult; +#else +#error Unknown architecture #endif } FORCEINLINE unsigned char RoundFloatToByte(float f) { -#if defined( _X360 ) + int nResult = RoundFloatToInt(f); #ifdef Assert - Assert( IsFPUControlWordSet() ); -#endif - union - { - double flResult; - int pIntResult[2]; - unsigned char pResult[8]; - }; - flResult = __fctiw( f ); -#ifdef Assert - Assert( pIntResult[1] >= 0 && pIntResult[1] <= 255 ); -#endif - return pResult[8]; - -#else // !X360 - - int nResult; - -#if defined( _WIN32 ) - __asm - { - fld f - fistp nResult - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - __asm __volatile__ ( - "fistpl %0;": "=m" (nResult): "t" (f) : "st" - ); -#endif - -#ifdef Assert - Assert( nResult >= 0 && nResult <= 255 ); -#endif - return nResult; - + Assert( (nResult & ~0xFF) == 0 ); #endif + return (unsigned char) nResult; } FORCEINLINE unsigned long RoundFloatToUnsignedLong(float f) @@ -1159,22 +1177,41 @@ FORCEINLINE unsigned long RoundFloatToUnsignedLong(float f) return pResult[1]; #else // !X360 +#if defined( PLATFORM_WINDOWS_PC64 ) + uint nRet = ( uint ) f; + if ( nRet & 1 ) + { + if ( ( f - floor( f ) >= 0.5 ) ) + { + nRet++; + } + } + else + { + if ( ( f - floor( f ) > 0.5 ) ) + { + nRet++; + } + } + return nRet; +#else // PLATFORM_WINDOWS_PC64 unsigned char nResult[8]; -#if defined( _WIN32 ) - __asm - { - fld f - fistp qword ptr nResult - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - __asm __volatile__ ( - "fistpl %0;": "=m" (nResult): "t" (f) : "st" - ); -#endif + #if defined( _WIN32 ) + __asm + { + fld f + fistp qword ptr nResult + } + #elif POSIX + __asm __volatile__ ( + "fistpl %0;": "=m" (nResult): "t" (f) : "st" + ); + #endif - return *((unsigned long*)nResult); -#endif + return *((unsigned long*)nResult); +#endif // PLATFORM_WINDOWS_PC64 +#endif // !X360 } FORCEINLINE bool IsIntegralValue( float flValue, float flTolerance = 0.001f ) @@ -1194,76 +1231,54 @@ FORCEINLINE int Float2Int( float a ) flResult = __fctiwz( a ); return pResult[1]; #else // !X360 - - int RetVal; - -#if defined( _WIN32 ) - int CtrlwdHolder; - int CtrlwdSetter; - __asm - { - fld a // push 'a' onto the FP stack - fnstcw CtrlwdHolder // store FPU control word - movzx eax, CtrlwdHolder // move and zero extend word into eax - and eax, 0xFFFFF3FF // set all bits except rounding bits to 1 - or eax, 0x00000C00 // set rounding mode bits to round towards zero - mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid! - fldcw CtrlwdSetter // Entering plaid! - fistp RetVal // Store and converted (to int) result - fldcw CtrlwdHolder // Restore control word - } -#elif defined( _LINUX ) || defined ( __APPLE__ ) - RetVal = static_cast( a ); -#endif - - return RetVal; + // Rely on compiler to generate CVTTSS2SI on x86 + return (int) a; #endif } // Over 15x faster than: (int)floor(value) inline int Floor2Int( float a ) { - int RetVal; - -#if defined( _X360 ) - RetVal = (int)floor( a ); -#elif defined( _WIN32 ) - int CtrlwdHolder; - int CtrlwdSetter; - __asm - { - fld a // push 'a' onto the FP stack - fnstcw CtrlwdHolder // store FPU control word - movzx eax, CtrlwdHolder // move and zero extend word into eax - and eax, 0xFFFFF3FF // set all bits except rounding bits to 1 - or eax, 0x00000400 // set rounding mode bits to round down - mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid! - fldcw CtrlwdSetter // Entering plaid! - fistp RetVal // Store floored and converted (to int) result - fldcw CtrlwdHolder // Restore control word - } -#elif defined( _LINUX ) || defined( __APPLE__ ) + int RetVal; +#if defined( __i386__ ) + // Convert to int and back, compare, subtract one if too big + __m128 a128 = _mm_set_ss(a); + RetVal = _mm_cvtss_si32(a128); + __m128 rounded128 = _mm_cvt_si2ss(_mm_setzero_ps(), RetVal); + RetVal -= _mm_comigt_ss( rounded128, a128 ); +#else RetVal = static_cast( floor(a) ); #endif - return RetVal; } //----------------------------------------------------------------------------- // Fast color conversion from float to unsigned char //----------------------------------------------------------------------------- -FORCEINLINE unsigned char FastFToC( float c ) +FORCEINLINE unsigned int FastFToC( float c ) { - volatile float dc; - - // ieee trick - dc = c * 255.0f + (float)(1 << 23); - - // return the lsb -#if defined( _X360 ) - return ((unsigned char*)&dc)[3]; +#if defined( __i386__ ) + // IEEE float bit manipulation works for values between [0, 1<<23) + union { float f; int i; } convert = { c*255.0f + (float)(1<<23) }; + return convert.i & 255; #else - return *(unsigned char*)&dc; + // consoles CPUs suffer from load-hit-store penalty + return Float2Int( c * 255.0f ); +#endif +} + +//----------------------------------------------------------------------------- +// Fast conversion from float to integer with magnitude less than 2**22 +//----------------------------------------------------------------------------- +FORCEINLINE int FastFloatToSmallInt( float c ) +{ +#if defined( __i386__ ) + // IEEE float bit manipulation works for values between [-1<<22, 1<<22) + union { float f; int i; } convert = { c + (float)(3<<22) }; + return (convert.i & ((1<<23)-1)) - (1<<22); +#else + // consoles CPUs suffer from load-hit-store penalty + return Float2Int( c ); #endif } @@ -1275,35 +1290,22 @@ FORCEINLINE unsigned char FastFToC( float c ) inline float ClampToMsec( float in ) { int msec = Floor2Int( in * 1000.0f + 0.5f ); - return msec / 1000.0f; + return 0.001f * msec; } // Over 15x faster than: (int)ceil(value) inline int Ceil2Int( float a ) { int RetVal; - -#if defined( _X360 ) - RetVal = (int)ceil( a ); -#elif defined( _WIN32 ) - int CtrlwdHolder; - int CtrlwdSetter; - __asm - { - fld a // push 'a' onto the FP stack - fnstcw CtrlwdHolder // store FPU control word - movzx eax, CtrlwdHolder // move and zero extend word into eax - and eax, 0xFFFFF3FF // set all bits except rounding bits to 1 - or eax, 0x00000800 // set rounding mode bits to round down - mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid! - fldcw CtrlwdSetter // Entering plaid! - fistp RetVal // Store floored and converted (to int) result - fldcw CtrlwdHolder // Restore control word - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - RetVal = static_cast( ceil(a) ); +#if defined( __i386__ ) + // Convert to int and back, compare, add one if too small + __m128 a128 = _mm_load_ss(&a); + RetVal = _mm_cvtss_si32(a128); + __m128 rounded128 = _mm_cvt_si2ss(_mm_setzero_ps(), RetVal); + RetVal += _mm_comilt_ss( rounded128, a128 ); +#else + RetVal = static_cast( ceil(a) ); #endif - return RetVal; } @@ -1419,7 +1421,7 @@ FORCEINLINE unsigned char LinearToLightmap( float f ) FORCEINLINE void ColorClamp( Vector& color ) { - float maxc = MAX( color.x, MAX( color.y, color.z ) ); + float maxc = V_max( color.x, V_max( color.y, color.z ) ); if ( maxc > 1.0f ) { float ooMax = 1.0f / maxc; @@ -1915,10 +1917,10 @@ FORCEINLINE unsigned int * PackNormal_SHORT2( float nx, float ny, float nz, unsi ny *= 16384.0f; // '0' and '32768' values are invalid encodings - nx = MAX( nx, 1.0f ); // Make sure there are no zero values - ny = MAX( ny, 1.0f ); - nx = MIN( nx, 32767.0f ); // Make sure there are no 32768 values - ny = MIN( ny, 32767.0f ); + nx = V_max( nx, 1.0f ); // Make sure there are no zero values + ny = V_max( ny, 1.0f ); + nx = V_min( nx, 32767.0f ); // Make sure there are no 32768 values + ny = V_min( ny, 32767.0f ); if ( nz < 0.0f ) nx = -nx; // Set the sign bit for z @@ -2068,6 +2070,46 @@ void RGBtoHSV( const Vector &rgb, Vector &hsv ); void HSVtoRGB( const Vector &hsv, Vector &rgb ); +//----------------------------------------------------------------------------- +// Fast version of pow and log +//----------------------------------------------------------------------------- + +float FastLog2(float i); // log2( i ) +float FastPow2(float i); // 2^i +float FastPow(float a, float b); // a^b +float FastPow10( float i ); // 10^i + +//----------------------------------------------------------------------------- +// For testing float equality +//----------------------------------------------------------------------------- + +inline bool CloseEnough( float a, float b, float epsilon = EQUAL_EPSILON ) +{ + return fabs( a - b ) <= epsilon; +} + +inline bool CloseEnough( const Vector &a, const Vector &b, float epsilon = EQUAL_EPSILON ) +{ + return fabs( a.x - b.x ) <= epsilon && + fabs( a.y - b.y ) <= epsilon && + fabs( a.z - b.z ) <= epsilon; +} + +// Fast compare +// maxUlps is the maximum error in terms of Units in the Last Place. This +// specifies how big an error we are willing to accept in terms of the value +// of the least significant digit of the floating point number’s +// representation. maxUlps can also be interpreted in terms of how many +// representable floats we are willing to accept between A and B. +// This function will allow maxUlps-1 floats between A and B. +bool AlmostEqual(float a, float b, int maxUlps = 10); + +inline bool AlmostEqual( const Vector &a, const Vector &b, int maxUlps = 10) +{ + return AlmostEqual( a.x, b.x, maxUlps ) && + AlmostEqual( a.y, b.y, maxUlps ) && + AlmostEqual( a.z, b.z, maxUlps ); +} #endif // MATH_BASE_H diff --git a/public/mathlib/matrixmath.h b/public/mathlib/matrixmath.h new file mode 100644 index 00000000..40de0c02 --- /dev/null +++ b/public/mathlib/matrixmath.h @@ -0,0 +1,385 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// A set of generic, template-based matrix functions. +//===========================================================================// + +#ifndef MATRIXMATH_H +#define MATRIXMATH_H + +#include + +// The operations in this file can perform basic matrix operations on matrices represented +// using any class that supports the necessary operations: +// +// .Element( row, col ) - return the element at a given matrox position +// .SetElement( row, col, val ) - modify an element +// .Width(), .Height() - get dimensions +// .SetDimensions( nrows, ncols) - set a matrix to be un-initted and the appropriate size +// +// Generally, vectors can be used with these functions by using N x 1 matrices to represent them. +// Matrices are addressed as row, column, and indices are 0-based +// +// +// Note that the template versions of these routines are defined for generality - it is expected +// that template specialization is used for common high performance cases. + +namespace MatrixMath +{ + /// M *= flScaleValue + template + void ScaleMatrix( MATRIXCLASS &matrix, float flScaleValue ) + { + for( int i = 0; i < matrix.Height(); i++ ) + { + for( int j = 0; j < matrix.Width(); j++ ) + { + matrix.SetElement( i, j, flScaleValue * matrix.Element( i, j ) ); + } + } + } + + /// AppendElementToMatrix - same as setting the element, except only works when all calls + /// happen in top to bottom left to right order, end you have to call FinishedAppending when + /// done. For normal matrix classes this is not different then SetElement, but for + /// CSparseMatrix, it is an accelerated way to fill a matrix from scratch. + template + FORCEINLINE void AppendElement( MATRIXCLASS &matrix, int nRow, int nCol, float flValue ) + { + matrix.SetElement( nRow, nCol, flValue ); // default implementation + } + + template + FORCEINLINE void FinishedAppending( MATRIXCLASS &matrix ) {} // default implementation + + /// M += fl + template + void AddToMatrix( MATRIXCLASS &matrix, float flAddend ) + { + for( int i = 0; i < matrix.Height(); i++ ) + { + for( int j = 0; j < matrix.Width(); j++ ) + { + matrix.SetElement( i, j, flAddend + matrix.Element( i, j ) ); + } + } + } + + /// transpose + template + void TransposeMatrix( MATRIXCLASSIN const &matrixIn, MATRIXCLASSOUT *pMatrixOut ) + { + pMatrixOut->SetDimensions( matrixIn.Width(), matrixIn.Height() ); + for( int i = 0; i < pMatrixOut->Height(); i++ ) + { + for( int j = 0; j < pMatrixOut->Width(); j++ ) + { + AppendElement( *pMatrixOut, i, j, matrixIn.Element( j, i ) ); + } + } + FinishedAppending( *pMatrixOut ); + } + + /// copy + template + void CopyMatrix( MATRIXCLASSIN const &matrixIn, MATRIXCLASSOUT *pMatrixOut ) + { + pMatrixOut->SetDimensions( matrixIn.Height(), matrixIn.Width() ); + for( int i = 0; i < matrixIn.Height(); i++ ) + { + for( int j = 0; j < matrixIn.Width(); j++ ) + { + AppendElement( *pMatrixOut, i, j, matrixIn.Element( i, j ) ); + } + } + FinishedAppending( *pMatrixOut ); + } + + + + /// M+=M + template + void AddMatrixToMatrix( MATRIXCLASSIN const &matrixIn, MATRIXCLASSOUT *pMatrixOut ) + { + for( int i = 0; i < matrixIn.Height(); i++ ) + { + for( int j = 0; j < matrixIn.Width(); j++ ) + { + pMatrixOut->SetElement( i, j, pMatrixOut->Element( i, j ) + matrixIn.Element( i, j ) ); + } + } + } + + // M += scale * M + template + void AddScaledMatrixToMatrix( float flScale, MATRIXCLASSIN const &matrixIn, MATRIXCLASSOUT *pMatrixOut ) + { + for( int i = 0; i < matrixIn.Height(); i++ ) + { + for( int j = 0; j < matrixIn.Width(); j++ ) + { + pMatrixOut->SetElement( i, j, pMatrixOut->Element( i, j ) + flScale * matrixIn.Element( i, j ) ); + } + } + } + + + // simple way to initialize a matrix with constants from code. + template + void SetMatrixToIdentity( MATRIXCLASSOUT *pMatrixOut, float flDiagonalValue = 1.0 ) + { + for( int i = 0; i < pMatrixOut->Height(); i++ ) + { + for( int j = 0; j < pMatrixOut->Width(); j++ ) + { + AppendElement( *pMatrixOut, i, j, ( i == j ) ? flDiagonalValue : 0 ); + } + } + FinishedAppending( *pMatrixOut ); + } + + //// simple way to initialize a matrix with constants from code + template + void SetMatrixValues( MATRIXCLASSOUT *pMatrix, int nRows, int nCols, ... ) + { + va_list argPtr; + va_start( argPtr, nCols ); + + pMatrix->SetDimensions( nRows, nCols ); + for( int nRow = 0; nRow < nRows; nRow++ ) + { + for( int nCol = 0; nCol < nCols; nCol++ ) + { + double flNewValue = va_arg( argPtr, double ); + pMatrix->SetElement( nRow, nCol, flNewValue ); + } + } + va_end( argPtr ); + } + + + /// row and colum accessors. treat a row or a column as a column vector + template class MatrixRowAccessor + { + public: + FORCEINLINE MatrixRowAccessor( MATRIXTYPE const &matrix, int nRow ) + { + m_pMatrix = &matrix; + m_nRow = nRow; + } + + FORCEINLINE float Element( int nRow, int nCol ) const + { + Assert( nCol == 0 ); + return m_pMatrix->Element( m_nRow, nRow ); + } + + FORCEINLINE int Width( void ) const { return 1; }; + FORCEINLINE int Height( void ) const { return m_pMatrix->Width(); } + + private: + MATRIXTYPE const *m_pMatrix; + int m_nRow; + }; + + template class MatrixColumnAccessor + { + public: + FORCEINLINE MatrixColumnAccessor( MATRIXTYPE const &matrix, int nColumn ) + { + m_pMatrix = &matrix; + m_nColumn = nColumn; + } + + FORCEINLINE float Element( int nRow, int nColumn ) const + { + Assert( nColumn == 0 ); + return m_pMatrix->Element( nRow, m_nColumn ); + } + + FORCEINLINE int Width( void ) const { return 1; } + FORCEINLINE int Height( void ) const { return m_pMatrix->Height(); } + private: + MATRIXTYPE const *m_pMatrix; + int m_nColumn; + }; + + /// this translator acts as a proxy for the transposed matrix + template class MatrixTransposeAccessor + { + public: + FORCEINLINE MatrixTransposeAccessor( MATRIXTYPE const & matrix ) + { + m_pMatrix = &matrix; + } + + FORCEINLINE float Element( int nRow, int nColumn ) const + { + return m_pMatrix->Element( nColumn, nRow ); + } + + FORCEINLINE int Width( void ) const { return m_pMatrix->Height(); } + FORCEINLINE int Height( void ) const { return m_pMatrix->Width(); } + private: + MATRIXTYPE const *m_pMatrix; + }; + + /// this tranpose returns a wrapper around it's argument, allowing things like AddMatrixToMatrix( Transpose( matA ), &matB ) without an extra copy + template + MatrixTransposeAccessor TransposeMatrix( MATRIXCLASSIN const &matrixIn ) + { + return MatrixTransposeAccessor( matrixIn ); + } + + + /// retrieve rows and columns + template + FORCEINLINE MatrixColumnAccessor MatrixColumn( MATRIXTYPE const &matrix, int nColumn ) + { + return MatrixColumnAccessor( matrix, nColumn ); + } + + template + FORCEINLINE MatrixRowAccessor MatrixRow( MATRIXTYPE const &matrix, int nRow ) + { + return MatrixRowAccessor( matrix, nRow ); + } + + //// dot product between vectors (or rows and/or columns via accessors) + template + float InnerProduct( MATRIXACCESSORATYPE const &vecA, MATRIXACCESSORBTYPE const &vecB ) + { + Assert( vecA.Width() == 1 ); + Assert( vecB.Width() == 1 ); + Assert( vecA.Height() == vecB.Height() ); + double flResult = 0; + for( int i = 0; i < vecA.Height(); i++ ) + { + flResult += vecA.Element( i, 0 ) * vecB.Element( i, 0 ); + } + return flResult; + } + + + + /// matrix x matrix multiplication + template + void MatrixMultiply( MATRIXATYPE const &matA, MATRIXBTYPE const &matB, MATRIXOUTTYPE *pMatrixOut ) + { + Assert( matA.Width() == matB.Height() ); + pMatrixOut->SetDimensions( matA.Height(), matB.Width() ); + for( int i = 0; i < matA.Height(); i++ ) + { + for( int j = 0; j < matB.Width(); j++ ) + { + pMatrixOut->SetElement( i, j, InnerProduct( MatrixRow( matA, i ), MatrixColumn( matB, j ) ) ); + } + } + } + + /// solve Ax=B via the conjugate graident method. Code and naming conventions based on the + /// wikipedia article. + template + void ConjugateGradient( ATYPE const &matA, BTYPE const &vecB, XTYPE &vecX, float flTolerance = 1.0e-20 ) + { + XTYPE vecR; + vecR.SetDimensions( vecX.Height(), 1 ); + MatrixMultiply( matA, vecX, &vecR ); + ScaleMatrix( vecR, -1 ); + AddMatrixToMatrix( vecB, &vecR ); + XTYPE vecP; + CopyMatrix( vecR, &vecP ); + float flRsOld = InnerProduct( vecR, vecR ); + for( int nIter = 0; nIter < 100; nIter++ ) + { + XTYPE vecAp; + MatrixMultiply( matA, vecP, &vecAp ); + float flDivisor = InnerProduct( vecAp, vecP ); + float flAlpha = flRsOld / flDivisor; + AddScaledMatrixToMatrix( flAlpha, vecP, &vecX ); + AddScaledMatrixToMatrix( -flAlpha, vecAp, &vecR ); + float flRsNew = InnerProduct( vecR, vecR ); + if ( flRsNew < flTolerance ) + { + break; + } + ScaleMatrix( vecP, flRsNew / flRsOld ); + AddMatrixToMatrix( vecR, &vecP ); + flRsOld = flRsNew; + } + } + + /// solve (A'*A) x=B via the conjugate gradient method. Code and naming conventions based on + /// the wikipedia article. Same as Conjugate gradient but allows passing in two matrices whose + /// product is used as the A matrix (in order to preserve sparsity) + template + void ConjugateGradient( ATYPE const &matA, APRIMETYPE const &matAPrime, BTYPE const &vecB, XTYPE &vecX, float flTolerance = 1.0e-20 ) + { + XTYPE vecR1; + vecR1.SetDimensions( vecX.Height(), 1 ); + MatrixMultiply( matA, vecX, &vecR1 ); + XTYPE vecR; + vecR.SetDimensions( vecR1.Height(), 1 ); + MatrixMultiply( matAPrime, vecR1, &vecR ); + ScaleMatrix( vecR, -1 ); + AddMatrixToMatrix( vecB, &vecR ); + XTYPE vecP; + CopyMatrix( vecR, &vecP ); + float flRsOld = InnerProduct( vecR, vecR ); + for( int nIter = 0; nIter < 100; nIter++ ) + { + XTYPE vecAp1; + MatrixMultiply( matA, vecP, &vecAp1 ); + XTYPE vecAp; + MatrixMultiply( matAPrime, vecAp1, &vecAp ); + float flDivisor = InnerProduct( vecAp, vecP ); + float flAlpha = flRsOld / flDivisor; + AddScaledMatrixToMatrix( flAlpha, vecP, &vecX ); + AddScaledMatrixToMatrix( -flAlpha, vecAp, &vecR ); + float flRsNew = InnerProduct( vecR, vecR ); + if ( flRsNew < flTolerance ) + { + break; + } + ScaleMatrix( vecP, flRsNew / flRsOld ); + AddMatrixToMatrix( vecR, &vecP ); + flRsOld = flRsNew; + } + } + + + template + void LeastSquaresFit( ATYPE const &matA, BTYPE const &vecB, XTYPE &vecX ) + { + // now, generate the normal equations + BTYPE vecBeta; + MatrixMath::MatrixMultiply( MatrixMath::TransposeMatrix( matA ), vecB, &vecBeta ); + + vecX.SetDimensions( matA.Width(), 1 ); + MatrixMath::SetMatrixToIdentity( &vecX ); + + ATYPE matATransposed; + TransposeMatrix( matA, &matATransposed ); + ConjugateGradient( matA, matATransposed, vecBeta, vecX, 1.0e-20 ); + } + +}; + +/// a simple fixed-size matrix class +template class CFixedMatrix +{ +public: + FORCEINLINE int Width( void ) const { return NUMCOLS; } + FORCEINLINE int Height( void ) const { return NUMROWS; } + FORCEINLINE float Element( int nRow, int nCol ) const { return m_flValues[nRow][nCol]; } + FORCEINLINE void SetElement( int nRow, int nCol, float flValue ) { m_flValues[nRow][nCol] = flValue; } + FORCEINLINE void SetDimensions( int nNumRows, int nNumCols ) { Assert( ( nNumRows == NUMROWS ) && ( nNumCols == NUMCOLS ) ); } + +private: + float m_flValues[NUMROWS][NUMCOLS]; +}; + + + +#endif //matrixmath_h diff --git a/public/mathlib/ssemath.h b/public/mathlib/ssemath.h index 8e3fc233..e9f8705f 100644 --- a/public/mathlib/ssemath.h +++ b/public/mathlib/ssemath.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: - defines SIMD "structure of arrays" classes and functions. // @@ -15,7 +15,7 @@ #include #include -#if defined(_LINUX) || defined(__APPLE__) +#if defined(GNUC) #define USE_STDC_FOR_SIMD 0 #else #define USE_STDC_FOR_SIMD 0 @@ -108,7 +108,7 @@ struct ALIGN16 intx4 m_i32[2] == other.m_i32[2] && m_i32[3] == other.m_i32[3] ; } -}; +} ALIGN16_POST; #if defined( _DEBUG ) && defined( _X360 ) @@ -136,13 +136,13 @@ FORCEINLINE void TestVPUFlags() {} // miss.) #ifndef _X360 extern const fltx4 Four_Zeros; // 0 0 0 0 -extern const fltx4 Four_Ones; // 1 1 1 1 -extern const fltx4 Four_Twos; // 2 2 2 2 +extern const fltx4 Four_Ones; // 1 1 1 1 +extern const fltx4 Four_Twos; // 2 2 2 2 extern const fltx4 Four_Threes; // 3 3 3 3 extern const fltx4 Four_Fours; // guess. extern const fltx4 Four_Point225s; // .225 .225 .225 .225 extern const fltx4 Four_PointFives; // .5 .5 .5 .5 -extern const fltx4 Four_Epsilons; // FLT_EPSILON FLT_EPSILON FLT_EPSILON FLT_EPSILON +extern const fltx4 Four_Epsilons; // FLT_EPSILON FLT_EPSILON FLT_EPSILON FLT_EPSILON extern const fltx4 Four_2ToThe21s; // (1<<21).. extern const fltx4 Four_2ToThe22s; // (1<<22).. extern const fltx4 Four_2ToThe23s; // (1<<23).. @@ -157,7 +157,7 @@ extern const fltx4 Four_Threes; // 3 3 3 3 extern const fltx4 Four_Fours; // guess. extern const fltx4 Four_Point225s; // .225 .225 .225 .225 extern const fltx4 Four_PointFives; // .5 .5 .5 .5 -extern const fltx4 Four_Epsilons; // FLT_EPSILON FLT_EPSILON FLT_EPSILON FLT_EPSILON +extern const fltx4 Four_Epsilons; // FLT_EPSILON FLT_EPSILON FLT_EPSILON FLT_EPSILON extern const fltx4 Four_2ToThe21s; // (1<<21).. extern const fltx4 Four_2ToThe22s; // (1<<22).. extern const fltx4 Four_2ToThe23s; // (1<<23).. @@ -167,20 +167,20 @@ extern const fltx4 Four_NegativeOnes; // -1 -1 -1 -1 #endif extern const fltx4 Four_FLT_MAX; // FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX extern const fltx4 Four_Negative_FLT_MAX; // -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX -extern const fltx4 g_SIMD_0123; // 0 1 2 3 as float +extern const fltx4 g_SIMD_0123; // 0 1 2 3 as float // external aligned integer constants -extern const ALIGN16 int32 g_SIMD_clear_signmask[]; // 0x7fffffff x 4 -extern const ALIGN16 int32 g_SIMD_signmask[]; // 0x80000000 x 4 -extern const ALIGN16 int32 g_SIMD_lsbmask[]; // 0xfffffffe x 4 -extern const ALIGN16 int32 g_SIMD_clear_wmask[]; // -1 -1 -1 0 -extern const ALIGN16 int32 g_SIMD_ComponentMask[4][4]; // [0xFFFFFFFF 0 0 0], [0 0xFFFFFFFF 0 0], [0 0 0xFFFFFFFF 0], [0 0 0 0xFFFFFFFF] -extern const ALIGN16 int32 g_SIMD_AllOnesMask[]; // ~0,~0,~0,~0 -extern const ALIGN16 int32 g_SIMD_Low16BitsMask[]; // 0xffff x 4 +extern const ALIGN16 int32 g_SIMD_clear_signmask[] ALIGN16_POST; // 0x7fffffff x 4 +extern const ALIGN16 int32 g_SIMD_signmask[] ALIGN16_POST; // 0x80000000 x 4 +extern const ALIGN16 int32 g_SIMD_lsbmask[] ALIGN16_POST; // 0xfffffffe x 4 +extern const ALIGN16 int32 g_SIMD_clear_wmask[] ALIGN16_POST; // -1 -1 -1 0 +extern const ALIGN16 int32 g_SIMD_ComponentMask[4][4] ALIGN16_POST; // [0xFFFFFFFF 0 0 0], [0 0xFFFFFFFF 0 0], [0 0 0xFFFFFFFF 0], [0 0 0 0xFFFFFFFF] +extern const ALIGN16 int32 g_SIMD_AllOnesMask[] ALIGN16_POST; // ~0,~0,~0,~0 +extern const ALIGN16 int32 g_SIMD_Low16BitsMask[] ALIGN16_POST; // 0xffff x 4 // this mask is used for skipping the tail of things. If you have N elements in an array, and wish // to mask out the tail, g_SIMD_SkipTailMask[N & 3] what you want to use for the last iteration. -extern const int32 ALIGN16 g_SIMD_SkipTailMask[4][4]; +extern const int32 ALIGN16 g_SIMD_SkipTailMask[4][4] ALIGN16_POST; // Define prefetch macros. // The characteristics of cache and prefetch are completely @@ -436,23 +436,23 @@ FORCEINLINE fltx4 ArcTan2SIMD( const fltx4 &a, const fltx4 &b ) return result; } -FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // MAX(a,b) +FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // max(a,b) { fltx4 retVal; - SubFloat( retVal, 0 ) = MAX( SubFloat( a, 0 ), SubFloat( b, 0 ) ); - SubFloat( retVal, 1 ) = MAX( SubFloat( a, 1 ), SubFloat( b, 1 ) ); - SubFloat( retVal, 2 ) = MAX( SubFloat( a, 2 ), SubFloat( b, 2 ) ); - SubFloat( retVal, 3 ) = MAX( SubFloat( a, 3 ), SubFloat( b, 3 ) ); + SubFloat( retVal, 0 ) = max( SubFloat( a, 0 ), SubFloat( b, 0 ) ); + SubFloat( retVal, 1 ) = max( SubFloat( a, 1 ), SubFloat( b, 1 ) ); + SubFloat( retVal, 2 ) = max( SubFloat( a, 2 ), SubFloat( b, 2 ) ); + SubFloat( retVal, 3 ) = max( SubFloat( a, 3 ), SubFloat( b, 3 ) ); return retVal; } -FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // MIN(a,b) +FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // min(a,b) { fltx4 retVal; - SubFloat( retVal, 0 ) = MIN( SubFloat( a, 0 ), SubFloat( b, 0 ) ); - SubFloat( retVal, 1 ) = MIN( SubFloat( a, 1 ), SubFloat( b, 1 ) ); - SubFloat( retVal, 2 ) = MIN( SubFloat( a, 2 ), SubFloat( b, 2 ) ); - SubFloat( retVal, 3 ) = MIN( SubFloat( a, 3 ), SubFloat( b, 3 ) ); + SubFloat( retVal, 0 ) = min( SubFloat( a, 0 ), SubFloat( b, 0 ) ); + SubFloat( retVal, 1 ) = min( SubFloat( a, 1 ), SubFloat( b, 1 ) ); + SubFloat( retVal, 2 ) = min( SubFloat( a, 2 ), SubFloat( b, 2 ) ); + SubFloat( retVal, 3 ) = min( SubFloat( a, 3 ), SubFloat( b, 3 ) ); return retVal; } @@ -858,7 +858,7 @@ FORCEINLINE void TransposeSIMD( fltx4 & x, fltx4 & y, fltx4 & z, fltx4 & w ) // and replicate it to the whole return value. FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 & a ) { - float lowest = MIN( MIN( SubFloat(a, 0), SubFloat(a, 1) ), SubFloat(a, 2)); + float lowest = min( min( SubFloat(a, 0), SubFloat(a, 1) ), SubFloat(a, 2)); return ReplicateX4(lowest); } @@ -866,7 +866,7 @@ FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 & a ) // and replicate it to the whole return value. FORCEINLINE fltx4 FindHighestSIMD3( const fltx4 & a ) { - float highest = MAX( MAX( SubFloat(a, 0), SubFloat(a, 1) ), SubFloat(a, 2)); + float highest = max( max( SubFloat(a, 0), SubFloat(a, 1) ), SubFloat(a, 2)); return ReplicateX4(highest); } @@ -1067,12 +1067,12 @@ FORCEINLINE fltx4 ArcTan2SIMD( const fltx4 &a, const fltx4 &b ) // DivSIMD defined further down, since it uses ReciprocalSIMD -FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // MAX(a,b) +FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // max(a,b) { return __vmaxfp( a, b ); } -FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // MIN(a,b) +FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // min(a,b) { return __vminfp( a, b ); } @@ -1520,11 +1520,11 @@ FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 & a ) compareOne = __vrlimi( compareOne, a, 8 | 4 , 1 ); // compareOne is [y,z,G,G] fltx4 retval = MinSIMD( a, compareOne ); - // retVal is [MIN(x,y), MIN(y,z), G, G] + // retVal is [min(x,y), min(y,z), G, G] compareOne = __vrlimi( compareOne, a, 8 , 2); // compareOne is [z, G, G, G] retval = MinSIMD( retval, compareOne ); - // retVal = [ MIN(MIN(x,y),z), G, G, G ] + // retVal = [ min(min(x,y),z), G, G, G ] // splat the x component out to the whole vector and return return SplatXSIMD( retval ); @@ -1544,11 +1544,11 @@ FORCEINLINE fltx4 FindHighestSIMD3( const fltx4 & a ) compareOne = __vrlimi( compareOne, a, 8 | 4 , 1 ); // compareOne is [y,z,G,G] fltx4 retval = MaxSIMD( a, compareOne ); - // retVal is [MAX(x,y), MAX(y,z), G, G] + // retVal is [max(x,y), max(y,z), G, G] compareOne = __vrlimi( compareOne, a, 8 , 2); // compareOne is [z, G, G, G] retval = MaxSIMD( retval, compareOne ); - // retVal = [ MAX(MAX(x,y),z), G, G, G ] + // retVal = [ max(max(x,y),z), G, G, G ] // splat the x component out to the whole vector and return return SplatXSIMD( retval ); @@ -1757,7 +1757,7 @@ FORCEINLINE fltx4 AndSIMD( const fltx4 & a, const fltx4 & b ) // a & b return _mm_and_ps( a, b ); } -FORCEINLINE fltx4 AndNotSIMD( const fltx4 & a, const fltx4 & b ) // a & ~b +FORCEINLINE fltx4 AndNotSIMD( const fltx4 & a, const fltx4 & b ) // ~a & b { return _mm_andnot_ps( a, b ); } @@ -1813,7 +1813,7 @@ FORCEINLINE fltx4 ReplicateX4( float flValue ) FORCEINLINE float SubFloat( const fltx4 & a, int idx ) { // NOTE: if the output goes into a register, this causes a Load-Hit-Store stall (don't mix fpu/vpu math!) -#if !defined _LINUX && !defined __APPLE__ +#ifndef POSIX return a.m128_f32[ idx ]; #else return (reinterpret_cast(&a))[idx]; @@ -1822,7 +1822,7 @@ FORCEINLINE float SubFloat( const fltx4 & a, int idx ) FORCEINLINE float & SubFloat( fltx4 & a, int idx ) { -#if !defined _LINUX && !defined __APPLE__ +#ifndef POSIX return a.m128_f32[ idx ]; #else return (reinterpret_cast(&a))[idx]; @@ -1836,7 +1836,7 @@ FORCEINLINE uint32 SubFloatConvertToInt( const fltx4 & a, int idx ) FORCEINLINE uint32 SubInt( const fltx4 & a, int idx ) { -#if !defined _LINUX && !defined __APPLE__ +#ifndef POSIX return a.m128_u32[idx]; #else return (reinterpret_cast(&a))[idx]; @@ -1845,7 +1845,7 @@ FORCEINLINE uint32 SubInt( const fltx4 & a, int idx ) FORCEINLINE uint32 & SubInt( fltx4 & a, int idx ) { -#if !defined _LINUX && !defined __APPLE__ +#ifndef POSIX return a.m128_u32[idx]; #else return (reinterpret_cast(&a))[idx]; @@ -2120,12 +2120,12 @@ FORCEINLINE fltx4 CmpInBoundsSIMD( const fltx4 & a, const fltx4 & b ) // (a <= return AndSIMD( CmpLeSIMD(a,b), CmpGeSIMD(a, NegSIMD(b)) ); } -FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // MIN(a,b) +FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // min(a,b) { return _mm_min_ps( a, b ); } -FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // MAX(a,b) +FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // max(a,b) { return _mm_max_ps( a, b ); } @@ -2271,11 +2271,11 @@ FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 &a ) fltx4 compareOne = RotateLeft( a ); // compareOne is [y,z,G,x] fltx4 retval = MinSIMD( a, compareOne ); - // retVal is [MIN(x,y), ... ] + // retVal is [min(x,y), ... ] compareOne = RotateLeft2( a ); // compareOne is [z, G, x, y] retval = MinSIMD( retval, compareOne ); - // retVal = [ MIN(MIN(x,y),z)..] + // retVal = [ min(min(x,y),z)..] // splat the x component out to the whole vector and return return SplatXSIMD( retval ); @@ -2288,11 +2288,11 @@ FORCEINLINE fltx4 FindHighestSIMD3( const fltx4 &a ) fltx4 compareOne = RotateLeft( a ); // compareOne is [y,z,G,x] fltx4 retval = MaxSIMD( a, compareOne ); - // retVal is [MAX(x,y), ... ] + // retVal is [max(x,y), ... ] compareOne = RotateLeft2( a ); // compareOne is [z, G, x, y] retval = MaxSIMD( retval, compareOne ); - // retVal = [ MAX(MAX(x,y),z)..] + // retVal = [ max(max(x,y),z)..] // splat the x component out to the whole vector and return return SplatXSIMD( retval ); @@ -2407,6 +2407,12 @@ FORCEINLINE i32x4 IntShiftLeftWordSIMD(const i32x4 &vSrcA, const i32x4 &vSrcB) // like this. FORCEINLINE void ConvertStoreAsIntsSIMD(intx4 * RESTRICT pDest, const fltx4 &vSrc) { +#ifdef COMPILER_MSVC64 + (*pDest)[0] = SubFloat(vSrc, 0); + (*pDest)[1] = SubFloat(vSrc, 1); + (*pDest)[2] = SubFloat(vSrc, 2); + (*pDest)[3] = SubFloat(vSrc, 3); +#else __m64 bottom = _mm_cvttps_pi32( vSrc ); __m64 top = _mm_cvttps_pi32( _mm_movehl_ps(vSrc,vSrc) ); @@ -2414,6 +2420,7 @@ FORCEINLINE void ConvertStoreAsIntsSIMD(intx4 * RESTRICT pDest, const fltx4 &vSr *reinterpret_cast<__m64 *>(&(*pDest)[2]) = top; _mm_empty(); +#endif } diff --git a/public/mathlib/ssequaternion.h b/public/mathlib/ssequaternion.h index 5021c315..d38c3c09 100644 --- a/public/mathlib/ssequaternion.h +++ b/public/mathlib/ssequaternion.h @@ -233,7 +233,7 @@ FORCEINLINE fltx4 QuaternionScaleSIMD( const fltx4 &p, float t ) // FIXME: nick, this isn't overly sensitive to accuracy, and it may be faster to // use the cos part (w) of the quaternion (sin(omega)*N,cos(omega)) to figure the new scale. float sinom = sqrt( SubFloat( p, 0 ) * SubFloat( p, 0 ) + SubFloat( p, 1 ) * SubFloat( p, 1 ) + SubFloat( p, 2 ) * SubFloat( p, 2 ) ); - sinom = MIN( sinom, 1.f ); + sinom = min( sinom, 1.f ); float sinsom = sin( asin( sinom ) * t ); diff --git a/public/mathlib/vector.h b/public/mathlib/vector.h index 6b332b56..6ec3bde3 100644 --- a/public/mathlib/vector.h +++ b/public/mathlib/vector.h @@ -1,4 +1,4 @@ -//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// // // Purpose: // @@ -31,6 +31,7 @@ #include "tier0/threadtools.h" #include "mathlib/vector2d.h" #include "mathlib/math_pfns.h" +#include "minmax.h" // Uncomment this to add extra Asserts to check for NANs, uninitialized vecs, etc. //#define VECTOR_PARANOIA 1 @@ -48,7 +49,11 @@ #ifdef VECTOR_PARANOIA #define CHECK_VALID( _v) Assert( (_v).IsValid() ) #else +#ifdef GNUC #define CHECK_VALID( _v) +#else +#define CHECK_VALID( _v) 0 +#endif #endif #define VecToString(v) (static_cast(CFmtStr("(%f, %f, %f)", (v).x, (v).y, (v).z))) // ** Note: this generates a temporary, don't hold reference! @@ -67,7 +72,7 @@ public: // Construction/destruction: Vector(void); Vector(vec_t X, vec_t Y, vec_t Z); - Vector(vec_t XYZ); // TODO (Ilya): is this potentially a bad idea? + explicit Vector(vec_t XYZ); ///< broadcast initialize // Initialization void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f); @@ -129,6 +134,7 @@ public: } vec_t NormalizeInPlace(); + Vector Normalized() const; bool IsLengthGreaterThan( float val ) const; bool IsLengthLessThan( float val ) const; @@ -202,9 +208,11 @@ private: #endif }; +FORCEINLINE void NetworkVarConstruct( Vector &v ) { v.Zero(); } - -#define USE_M64S ( ( !defined( _X360 ) ) && ( ! defined( _LINUX) ) ) +#if ( ( !defined( _X360 ) ) && ( ! defined( _LINUX) ) ) + #define USE_M64S 1 +#endif @@ -259,7 +267,7 @@ private: // No assignment operators either... // ShortVector& operator=( ShortVector const& src ); -}; +} ALIGN8_POST; @@ -395,7 +403,7 @@ public: #endif float w; // this space is used anyway -}; +} ALIGN16_POST; //----------------------------------------------------------------------------- // Vector related operations @@ -415,7 +423,9 @@ FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& resul FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& result ); FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& result ); inline void VectorScale ( const Vector& in, vec_t scale, Vector& result ); -inline void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ); +// Don't mark this as inline in its function declaration. That's only necessary on its +// definition, and 'inline' here leads to gcc warnings. +void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ); // Vector equality with tolerance bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance = 0.0f ); @@ -442,6 +452,31 @@ void VectorMax( const Vector &a, const Vector &b, Vector &result ); // Linearly interpolate between two vectors void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest ); +Vector VectorLerp(const Vector& src1, const Vector& src2, vec_t t ); + +FORCEINLINE Vector ReplicateToVector( float x ) +{ + return Vector( x, x, x ); +} + +// check if a point is in the field of a view of an object. supports up to 180 degree fov. +FORCEINLINE bool PointWithinViewAngle( Vector const &vecSrcPosition, + Vector const &vecTargetPosition, + Vector const &vecLookDirection, float flCosHalfFOV ) +{ + Vector vecDelta = vecTargetPosition - vecSrcPosition; + float cosDiff = DotProduct( vecLookDirection, vecDelta ); + + if ( cosDiff < 0 ) + return false; + + float flLen2 = vecDelta.LengthSqr(); + + // a/sqrt(b) > c == a^2 > b * c ^2 + return ( cosDiff * cosDiff > flLen2 * flCosHalfFOV * flCosHalfFOV ); + +} + #ifndef VECTOR_NO_SLOW_OPERATIONS @@ -453,6 +488,10 @@ Vector RandomVector( vec_t minVal, vec_t maxVal ); #endif +float RandomVectorInUnitSphere( Vector *pVector ); +float RandomVectorInUnitCircle( Vector2D *pVector ); + + //----------------------------------------------------------------------------- // // Inlined Vector methods @@ -516,9 +555,9 @@ inline void Vector::Init( vec_t ix, vec_t iy, vec_t iz ) inline void Vector::Random( vec_t minVal, vec_t maxVal ) { - x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - z = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); + x = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + y = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + z = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); CHECK_VALID(*this); } @@ -1081,14 +1120,6 @@ inline void VectorScale ( const Vector& in, vec_t scale, Vector& result ) VectorMultiply( in, scale, result ); } -inline void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ) -{ - CHECK_VALID(start); - CHECK_VALID(direction); - dest.x = start.x + scale * direction.x; - dest.y = start.y + scale * direction.y; - dest.z = start.z + scale * direction.z; -} FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& c ) { @@ -1130,6 +1161,12 @@ inline void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest.z = src1.z + (src2.z - src1.z) * t; } +inline Vector VectorLerp(const Vector& src1, const Vector& src2, vec_t t ) +{ + Vector result; + VectorLerp( src1, src2, t, result ); + return result; +} //----------------------------------------------------------------------------- // Temporary storage for vector results so const Vector& results can be returned @@ -1430,6 +1467,13 @@ inline void VectorMax( const Vector &a, const Vector &b, Vector &result ) result.z = fpmax(a.z, b.z); } +inline float ComputeVolume( const Vector &vecMins, const Vector &vecMaxs ) +{ + Vector vecDelta; + VectorSubtract( vecMaxs, vecMins, vecDelta ); + return DotProduct( vecDelta, vecDelta ); +} + // Get a random vector. inline Vector RandomVector( float minVal, float maxVal ) { @@ -1609,7 +1653,7 @@ public: } #endif -}; +} ALIGN16_POST; //----------------------------------------------------------------------------- @@ -1642,6 +1686,9 @@ public: extern void AngleQuaternion( RadianEuler const &angles, Quaternion &qt ); extern void QuaternionAngles( Quaternion const &q, RadianEuler &angles ); + +FORCEINLINE void NetworkVarConstruct( Quaternion &q ) { q.x = q.y = q.z = q.w = 0.0f; } + inline Quaternion::Quaternion(RadianEuler const &angle) { AngleQuaternion( angle, *this ); @@ -1789,6 +1836,8 @@ private: #endif }; +FORCEINLINE void NetworkVarConstruct( QAngle &q ) { q.x = q.y = q.z = 0.0f; } + //----------------------------------------------------------------------------- // Allows us to specifically pass the vector by value when we need to //----------------------------------------------------------------------------- @@ -1852,9 +1901,9 @@ inline void QAngle::Init( vec_t ix, vec_t iy, vec_t iz ) inline void QAngle::Random( vec_t minVal, vec_t maxVal ) { - x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - z = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); + x = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + y = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + z = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); CHECK_VALID(*this); } @@ -2127,11 +2176,16 @@ inline void AngularImpulseToQAngle( const AngularImpulse &impulse, QAngle &angle } #if !defined( _X360 ) -extern float (*pfInvRSquared)( const float *v ); FORCEINLINE vec_t InvRSquared( float const *v ) { - return (*pfInvRSquared)(v); +#if defined(__i386__) || defined(_M_IX86) + float sqrlen = v[0]*v[0]+v[1]*v[1]+v[2]*v[2] + 1.0e-10f, result; + _mm_store_ss(&result, _mm_rcp_ss( _mm_max_ss( _mm_set_ss(1.0f), _mm_load_ss(&sqrlen) ) )); + return result; +#else + return 1.f/fpmax(1.f, v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); +#endif } FORCEINLINE vec_t InvRSquared( const Vector &v ) @@ -2139,36 +2193,63 @@ FORCEINLINE vec_t InvRSquared( const Vector &v ) return InvRSquared(&v.x); } -#else - -// call directly -FORCEINLINE float _VMX_InvRSquared( const Vector &v ) +#if defined(__i386__) || defined(_M_IX86) +inline void _SSE_RSqrtInline( float a, float* out ) { - XMVECTOR xmV = XMVector3ReciprocalLength( XMLoadVector3( v.Base() ) ); - xmV = XMVector3Dot( xmV, xmV ); - return xmV.x; + __m128 xx = _mm_load_ss( &a ); + __m128 xr = _mm_rsqrt_ss( xx ); + __m128 xt; + xt = _mm_mul_ss( xr, xr ); + xt = _mm_mul_ss( xt, xx ); + xt = _mm_sub_ss( _mm_set_ss(3.f), xt ); + xt = _mm_mul_ss( xt, _mm_set_ss(0.5f) ); + xr = _mm_mul_ss( xr, xt ); + _mm_store_ss( out, xr ); } - -#define InvRSquared(x) _VMX_InvRSquared(x) - -#endif // _X360 - -#if !defined( _X360 ) -extern float (FASTCALL *pfVectorNormalize)(Vector& v); +#endif // FIXME: Change this back to a #define once we get rid of the vec_t version -FORCEINLINE float VectorNormalize( Vector& v ) +FORCEINLINE float VectorNormalize( Vector& vec ) { - return (*pfVectorNormalize)(v); +#ifndef DEBUG // stop crashing my edit-and-continue! + #if defined(__i386__) || defined(_M_IX86) + #define DO_SSE_OPTIMIZATION + #endif +#endif + +#if defined( DO_SSE_OPTIMIZATION ) + float sqrlen = vec.LengthSqr() + 1.0e-10f, invlen; + _SSE_RSqrtInline(sqrlen, &invlen); + vec.x *= invlen; + vec.y *= invlen; + vec.z *= invlen; + return sqrlen * invlen; +#else + extern float (FASTCALL *pfVectorNormalize)(Vector& v); + return (*pfVectorNormalize)(vec); +#endif } + // FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s FORCEINLINE float VectorNormalize( float * v ) { return VectorNormalize(*(reinterpret_cast(v))); } +FORCEINLINE void VectorNormalizeFast( Vector &vec ) +{ + VectorNormalize(vec); +} + #else +FORCEINLINE float _VMX_InvRSquared( const Vector &v ) +{ + XMVECTOR xmV = XMVector3ReciprocalLength( XMLoadVector3( v.Base() ) ); + xmV = XMVector3Dot( xmV, xmV ); + return xmV.x; +} + // call directly FORCEINLINE float _VMX_VectorNormalize( Vector &vec ) { @@ -2179,6 +2260,9 @@ FORCEINLINE float _VMX_VectorNormalize( Vector &vec ) vec.z *= den; return mag; } + +#define InvRSquared(x) _VMX_InvRSquared(x) + // FIXME: Change this back to a #define once we get rid of the vec_t version FORCEINLINE float VectorNormalize( Vector& v ) { @@ -2190,18 +2274,6 @@ FORCEINLINE float VectorNormalize( float *pV ) return _VMX_VectorNormalize(*(reinterpret_cast(pV))); } -#endif // _X360 - -#if !defined( _X360 ) -extern void (FASTCALL *pfVectorNormalizeFast)(Vector& v); - -FORCEINLINE void VectorNormalizeFast( Vector& v ) -{ - (*pfVectorNormalizeFast)(v); -} - -#else - // call directly FORCEINLINE void VectorNormalizeFast( Vector &vec ) { @@ -2214,11 +2286,19 @@ FORCEINLINE void VectorNormalizeFast( Vector &vec ) #endif // _X360 + inline vec_t Vector::NormalizeInPlace() { return VectorNormalize( *this ); } +inline Vector Vector::Normalized() const +{ + Vector norm = *this; + VectorNormalize( norm ); + return norm; +} + inline bool Vector::IsLengthGreaterThan( float val ) const { return LengthSqr() > val*val; diff --git a/public/mathlib/vector2d.h b/public/mathlib/vector2d.h index 35ed31e6..4de33424 100644 --- a/public/mathlib/vector2d.h +++ b/public/mathlib/vector2d.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -239,8 +239,8 @@ inline void Vector2D::Init( vec_t ix, vec_t iy ) inline void Vector2D::Random( float minVal, float maxVal ) { - x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); + x = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + y = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal); } inline void Vector2DClear( Vector2D& a ) diff --git a/public/mathlib/vector4d.h b/public/mathlib/vector4d.h index 91044a91..ade2c8ab 100644 --- a/public/mathlib/vector4d.h +++ b/public/mathlib/vector4d.h @@ -132,11 +132,7 @@ const Vector4D vec4_invalid( FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX ); // SSE optimized routines //----------------------------------------------------------------------------- -#ifdef _WIN32 -class __declspec(align(16)) Vector4DAligned : public Vector4D -#elif defined _LINUX || defined __APPLE__ -class __attribute__((aligned(16))) Vector4DAligned : public Vector4D -#endif +class ALIGN16 Vector4DAligned : public Vector4D { public: Vector4DAligned(void) {} @@ -154,7 +150,7 @@ private: // No assignment operators either... Vector4DAligned& operator=( Vector4DAligned const& src ); -}; +} ALIGN16_POST; //----------------------------------------------------------------------------- // Vector4D related operations @@ -249,10 +245,10 @@ inline void Vector4D::Init( vec_t ix, vec_t iy, vec_t iz, vec_t iw ) inline void Vector4D::Random( vec_t minVal, vec_t maxVal ) { - x = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); - z = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); - w = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); + x = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + y = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + z = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal); + w = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal); } inline void Vector4DClear( Vector4D& a ) diff --git a/public/mathlib/vmatrix.h b/public/mathlib/vmatrix.h index 6915e81d..07d6de2a 100644 --- a/public/mathlib/vmatrix.h +++ b/public/mathlib/vmatrix.h @@ -54,6 +54,7 @@ public: // Creates a matrix where the X axis = forward // the Y axis = left, and the Z axis = up VMatrix( const Vector& forward, const Vector& left, const Vector& up ); + VMatrix( const Vector& forward, const Vector& left, const Vector& up, const Vector& translation ); // Construct from a 3x4 matrix VMatrix( const matrix3x4_t& matrix3x4 ); @@ -106,7 +107,6 @@ public: void PreTranslate(const Vector &vTrans); void PostTranslate(const Vector &vTrans); - matrix3x4_t& As3x4(); const matrix3x4_t& As3x4() const; void CopyFrom3x4( const matrix3x4_t &m3x4 ); void Set3x4( matrix3x4_t& matrix3x4 ) const; @@ -199,6 +199,9 @@ public: // Setup a matrix for origin and angles. void SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles ); + // Setup a matrix for angles and no translation. + void SetupMatrixAngles( const QAngle &vAngles ); + // General inverse. This may fail so check the return! bool InverseGeneral(VMatrix &vInverse) const; @@ -457,6 +460,16 @@ inline VMatrix::VMatrix( const Vector& xAxis, const Vector& yAxis, const Vector& ); } +inline VMatrix::VMatrix( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector& translation ) +{ + Init( + xAxis.x, yAxis.x, zAxis.x, translation.x, + xAxis.y, yAxis.y, zAxis.y, translation.y, + xAxis.z, yAxis.z, zAxis.z, translation.z, + 0.0f, 0.0f, 0.0f, 1.0f + ); +} + inline void VMatrix::Init( vec_t m00, vec_t m01, vec_t m02, vec_t m03, @@ -616,11 +629,6 @@ inline const matrix3x4_t& VMatrix::As3x4() const return *((const matrix3x4_t*)this); } -inline matrix3x4_t& VMatrix::As3x4() -{ - return *((matrix3x4_t*)this); -} - inline void VMatrix::CopyFrom3x4( const matrix3x4_t &m3x4 ) { memcpy( m, m3x4.Base(), sizeof( matrix3x4_t ) ); @@ -902,6 +910,7 @@ inline bool MatricesAreEqual( const VMatrix &src1, const VMatrix &src2, float fl void MatrixBuildOrtho( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar ); void MatrixBuildPerspectiveX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar ); void MatrixBuildPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right ); +void MatrixBuildPerspectiveZRange( VMatrix& dst, double flZNear, double flZFar ); inline void MatrixOrtho( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar ) { diff --git a/public/mdllib/mdllib.h b/public/mdllib/mdllib.h index 40794e32..057c4458 100644 --- a/public/mdllib/mdllib.h +++ b/public/mdllib/mdllib.h @@ -72,7 +72,7 @@ public: // Returns the checksums that the stripping info was generated for: // plChecksumOriginal if non-NULL will hold the checksum of the original model submitted for stripping // plChecksumStripped if non-NULL will hold the resulting checksum of the stripped model - virtual bool GetCheckSum( long *plChecksumOriginal, long *plChecksumStripped ) const = 0; + virtual bool GetCheckSum( int32_t *plChecksumOriginal, int32_t *plChecksumStripped ) const = 0; // // Stripping diff --git a/public/minmax.h b/public/minmax.h new file mode 100644 index 00000000..c302e4cd --- /dev/null +++ b/public/minmax.h @@ -0,0 +1,18 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MINMAX_H +#define MINMAX_H + +#ifndef V_min +#define V_min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef V_max +#define V_max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#endif // MINMAX_H diff --git a/public/networkvar.h b/public/networkvar.h index cc04351d..eb59eadd 100644 --- a/public/networkvar.h +++ b/public/networkvar.h @@ -22,7 +22,7 @@ #pragma warning( disable : 4284 ) // warning C4284: return type for 'CNetworkVarT::operator ->' is 'int *' (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) #endif -#define MyOffsetOf( type, var ) ( (int)&((type*)0)->var ) +#define MyOffsetOf( type, var ) ( (intptr_t)&((type*)0)->var ) #ifdef _DEBUG extern bool g_bUseNetworkVars; diff --git a/public/optimize.h b/public/optimize.h index b7c857cf..644c11f5 100644 --- a/public/optimize.h +++ b/public/optimize.h @@ -226,7 +226,7 @@ struct FileHeader_t int maxBonesPerVert; // must match checkSum in the .mdl - long checkSum; + int32_t checkSum; int numLODs; // garymcthack - this is also specified in ModelHeader_t and should match diff --git a/public/phyfile.h b/public/phyfile.h index 8cf782dc..472250ca 100644 --- a/public/phyfile.h +++ b/public/phyfile.h @@ -17,7 +17,7 @@ typedef struct phyheader_s int size; int id; int solidCount; - long checkSum; // checksum of source .mdl file + int32_t checkSum; // checksum of source .mdl file } phyheader_t; #endif // PHYFILE_H diff --git a/public/saverestoretypes.h b/public/saverestoretypes.h index e7725af0..78a90087 100644 --- a/public/saverestoretypes.h +++ b/public/saverestoretypes.h @@ -105,7 +105,7 @@ struct levellist_t struct EHandlePlaceholder_t // Engine does some of the game writing (alas, probably shouldn't), but can't see ehandle.h { - unsigned long i; + uint32_t i; }; //------------------------------------- diff --git a/public/scratchpad3d.cpp b/public/scratchpad3d.cpp index 6747834c..f1cae56e 100644 --- a/public/scratchpad3d.cpp +++ b/public/scratchpad3d.cpp @@ -219,7 +219,7 @@ bool CScratchPad3D::LoadCommandsFromFile( ) if( !fp ) return false; - long fileEndPos = m_pFileSystem->Size( fp ); + int32_t fileEndPos = m_pFileSystem->Size( fp ); CFileRead fileRead( m_pFileSystem, fp ); while( fileRead.m_Pos != fileEndPos ) @@ -352,12 +352,12 @@ void CScratchPad3D::DrawRectXY( float zPos, const Vector2D &vMin, const Vector2D DrawRectGeneric( 2, 0, 1, zPos, vMin, vMax, vColor ); } -void CScratchPad3D::SetRenderState( RenderState state, unsigned long val ) +void CScratchPad3D::SetRenderState( RenderState state, uint32_t val ) { CCommand_RenderState *cmd = new CCommand_RenderState; m_Commands.AddToTail( cmd ); - cmd->m_State = (unsigned long)state; + cmd->m_State = (uint32_t)state; cmd->m_Val = val; } diff --git a/public/scratchpad3d.h b/public/scratchpad3d.h index 661de7be..5453cc00 100644 --- a/public/scratchpad3d.h +++ b/public/scratchpad3d.h @@ -132,8 +132,8 @@ public: virtual void Read( CFileRead *pFile ); virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - unsigned long m_State; // One of the RS_ enums. - unsigned long m_Val; + uint32_t m_State; // One of the RS_ enums. + uint32_t m_Val; }; class CCommand_Text : public CBaseCommand @@ -180,7 +180,7 @@ public: virtual void DrawRectXY( float zPos, Vector2D const &vMin, Vector2D const &vMax, CSPColor const &vColor ); virtual void DrawWireframeBox( Vector const &vMin, Vector const &vMax, Vector const &vColor ); virtual void DrawText( const char *pStr, const CTextParams ¶ms ); - virtual void SetRenderState( RenderState state, unsigned long val ); + virtual void SetRenderState( RenderState state, uint32_t val ); virtual void Clear(); virtual void Flush(); virtual void DrawImageBW( diff --git a/public/soundcombiner.cpp b/public/soundcombiner.cpp index 396e0e11..2432c134 100644 --- a/public/soundcombiner.cpp +++ b/public/soundcombiner.cpp @@ -189,7 +189,7 @@ unsigned int CSoundCombiner::ComputeChecksum() // Msg( " %i -> sentence %u, startoffset %f fn %s\n", // i, chk, curitem->entry->startoffset, curitem->entry->wavefile ); - CRC32_ProcessBuffer( &crc, &chk, sizeof( unsigned long ) ); + CRC32_ProcessBuffer( &crc, &chk, sizeof( uint32_t ) ); CRC32_ProcessBuffer( &crc, &curitem->entry->startoffset, sizeof( float ) ); CRC32_ProcessBuffer( &crc, curitem->entry->wavefile, Q_strlen( curitem->entry->wavefile ) ); } diff --git a/public/steam/steamtypes.h b/public/steam/steamtypes.h index 960a2710..10248902 100644 --- a/public/steam/steamtypes.h +++ b/public/steam/steamtypes.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2004, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2004, Valve LLC, All rights reserved. ============ // // Purpose: // @@ -18,8 +18,10 @@ typedef unsigned char uint8; #if defined(__x86_64__) || defined(_WIN64) +#ifndef X64BITS #define X64BITS #endif +#endif typedef unsigned char uint8; typedef signed char int8; @@ -47,14 +49,14 @@ typedef short int16; typedef unsigned short uint16; typedef int int32; typedef unsigned int uint32; -typedef long long int64; -typedef unsigned long long uint64; +typedef int64_t int64; +typedef uint64_t uint64; #ifdef X64BITS -typedef long long intp; -typedef unsigned long long uintp; +typedef int64_t intp; +typedef uint64_t uintp; #else -typedef int intp; -typedef unsigned int uintp; +typedef int32_t intp; +typedef uint32_t uintp; #endif #endif // else _WIN32 diff --git a/public/studio.h b/public/studio.h index 848b967f..ac3b153b 100644 --- a/public/studio.h +++ b/public/studio.h @@ -1796,7 +1796,7 @@ struct vertexFileHeader_t DECLARE_BYTESWAP_DATADESC(); int id; // MODEL_VERTEX_FILE_ID int version; // MODEL_VERTEX_FILE_VERSION - long checksum; // same as studiohdr_t, ensures sync + int32_t checksum; // same as studiohdr_t, ensures sync int numLODs; // num of valid lods int numLODVertexes[MAX_NUM_LODS]; // num verts for desired root lod int numFixups; // num of vertexFileFixup_t @@ -1964,7 +1964,7 @@ struct studiohdr_t int id; int version; - long checksum; // this has to be the same in the phy and vtx files to load! + int32_t checksum; // this has to be the same in the phy and vtx files to load! inline const char * pszName( void ) const { return name; } char name[64]; diff --git a/public/surfinfo.h b/public/surfinfo.h index 3aceff08..46b43895 100644 --- a/public/surfinfo.h +++ b/public/surfinfo.h @@ -19,7 +19,7 @@ class SurfInfo public: // Shape of the surface. Vector m_Verts[ MAX_SURFINFO_VERTS ]; - unsigned long m_nVerts; + uint32_t m_nVerts; // Plane of the surface. VPlane m_Plane; diff --git a/public/tier0/afxmem_override.cpp b/public/tier0/afxmem_override.cpp index c1abbd23..1c898f8d 100644 --- a/public/tier0/afxmem_override.cpp +++ b/public/tier0/afxmem_override.cpp @@ -137,10 +137,10 @@ AFX_STATIC_DATA AFX_ALLOC_HOOK pfnAllocHook = _AfxDefaultAllocHook; AFX_STATIC_DATA _CRT_ALLOC_HOOK pfnCrtAllocHook = NULL; #if _MSC_VER >= 1200 int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize, - int nBlockUse, long lRequest, const unsigned char * szFilename, int nLine) + int nBlockUse, int32_t lRequest, const unsigned char * szFilename, int nLine) #else int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize, - int nBlockUse, long lRequest, const char * szFilename, int nLine) + int nBlockUse, int32_t lRequest, const char * szFilename, int nLine) #endif { #if _MSC_VER >= 1200 diff --git a/public/tier0/annotations.h b/public/tier0/annotations.h new file mode 100644 index 00000000..ecc9dae7 --- /dev/null +++ b/public/tier0/annotations.h @@ -0,0 +1,84 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef ANALYSIS_ANNOTATIONS_H +#define ANALYSIS_ANNOTATIONS_H + +#if _MSC_VER >= 1600 // VS 2010 and above. +//----------------------------------------------------------------------------- +// Upgrading important helpful warnings to errors +//----------------------------------------------------------------------------- +#pragma warning(error : 4789 ) // warning C4789: destination of memory copy is too small + +// Suppress some code analysis warnings +#ifdef _PREFAST_ +// Include the annotation header file. +#include + +// For temporarily suppressing warnings -- the warnings are suppressed for the next source line. +#define ANALYZE_SUPPRESS(wnum) __pragma(warning(suppress: wnum)) +#define ANALYZE_SUPPRESS2(wnum1, wnum2) __pragma(warning(supress: wnum1 wnum2)) +#define ANALYZE_SUPPRESS3(wnum1, wnum2, wnum3) __pragma(warning(suppress: wnum1 wnum2 wnum3)) +#define ANALYZE_SUPPRESS4(wnum1, wnum2, wnum3, wnum4) __pragma(warning(suppress: wnum1 wnum2 wnum3 wnum4)) + +// Tag all printf style format strings with this +#define PRINTF_FORMAT_STRING _Printf_format_string_ +#define SCANF_FORMAT_STRING _Scanf_format_string_impl_ +// Various macros for specifying the capacity of the buffer pointed +// to by a function parameter. Variations include in/out/inout, +// CAP (elements) versus BYTECAP (bytes), and null termination or +// not (_Z). +#define IN_Z _In_z_ +#define IN_CAP(x) _In_count_(x) +#define IN_BYTECAP(x) _In_bytecount_(x) +#define OUT_Z_CAP(x) _Out_z_cap_(x) +#define OUT_CAP(x) _Out_cap_(x) +#define OUT_CAP_C(x) _Out_cap_c_(x) // Output buffer with specified *constant* capacity in elements +#define OUT_BYTECAP(x) _Out_bytecap_(x) +#define OUT_Z_BYTECAP(x) _Out_z_bytecap_(x) +#define INOUT_BYTECAP(x) _Inout_bytecap_(x) +#define INOUT_Z_CAP(x) _Inout_z_cap_(x) +#define INOUT_Z_BYTECAP(x) _Inout_z_bytecap_(x) +// These macros are use for annotating array reference parameters, typically used in functions +// such as V_strcpy_safe. Because they are array references the capacity is already known. +#if _MSC_VER >= 1700 +#define IN_Z_ARRAY _Pre_z_ +#define OUT_Z_ARRAY _Post_z_ +#define INOUT_Z_ARRAY _Prepost_z_ +#else +#define IN_Z_ARRAY _Deref_pre_z_ +#define OUT_Z_ARRAY _Deref_post_z_ +#define INOUT_Z_ARRAY _Deref_prepost_z_ +#endif // _MSC_VER >= 1700 +// Used for annotating functions to describe their return types. +#define MUST_CHECK_RETURN _Check_return_ +// Use the macros above to annotate string functions that fill buffers as shown here, +// in order to give VS's /analyze more opportunities to find bugs. +// void V_wcsncpy( OUT_Z_BYTECAP(maxLenInBytes) wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ); +// int V_snwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, ... ); + +#endif // _PREFAST_ +#endif // _MSC_VER >= 1600 // VS 2010 and above. + +#ifndef ANALYZE_SUPPRESS +#define ANALYZE_SUPPRESS(wnum) +#define ANALYZE_SUPPRESS2(wnum1, wnum2) +#define ANALYZE_SUPPRESS3(wnum1, wnum2, wnum3) +#define ANALYZE_SUPPRESS4(wnum1, wnum2, wnum3, wnum4) +#define PRINTF_FORMAT_STRING +#define SCANF_FORMAT_STRING +#define IN_Z +#define IN_CAP(x) +#define IN_BYTECAP(x) +#define OUT_Z_CAP(x) +#define OUT_CAP(x) +#define OUT_CAP_C(x) +#define OUT_BYTECAP(x) +#define OUT_Z_BYTECAP(x) +#define INOUT_BYTECAP(x) +#define INOUT_Z_CAP(x) +#define INOUT_Z_BYTECAP(x) +#define OUT_Z_ARRAY +#define INOUT_Z_ARRAY +#define MUST_CHECK_RETURN +#endif + +#endif // ANALYSIS_ANNOTATIONS_H diff --git a/public/tier0/basetypes.h b/public/tier0/basetypes.h index d488c12f..729dacb7 100644 --- a/public/tier0/basetypes.h +++ b/public/tier0/basetypes.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -8,6 +8,7 @@ #ifndef BASETYPES_H #define BASETYPES_H +#include #include "tier0/platform.h" #include "commonmacros.h" #include "wchartypes.h" @@ -19,6 +20,12 @@ #endif +// This is a trick to get the DLL extension off the -D option on the command line. +#define DLLExtTokenPaste(x) #x +#define DLLExtTokenPaste2(x) DLLExtTokenPaste(x) +#define DLL_EXT_STRING DLLExtTokenPaste2( _DLL_EXT ) + + #include "protected_things.h" // There's a different version of this file in the xbox codeline @@ -37,12 +44,6 @@ #define NULL 0 #endif -#if defined _LINUX && !defined __APPLE__ -typedef unsigned int uintptr_t; -#elif defined __APPLE__ -#include -#endif - #define ExecuteNTimes( nTimes, x ) \ { \ static int __executeCount=0;\ @@ -60,7 +61,16 @@ typedef unsigned int uintptr_t; template inline T AlignValue( T val, unsigned alignment ) { - return (T)( ( (uintptr_t)val + alignment - 1 ) & ~( alignment - 1 ) ); + uintp align = alignment; + return (T)( ( (uintp)val + align - 1 ) & ~( align - 1 ) ); +} + +// Tell MSVC to shut the hell up +template<> +inline char* AlignValue( char* val, unsigned alignment ) +{ + uintptr_t align = alignment; + return (char *)( ( reinterpret_cast(val) + align - 1 ) & ~( align - 1 ) ); } @@ -99,16 +109,38 @@ FORCEINLINE float fpmax( float a, float b ) #endif #ifdef __cplusplus - template< class T > - inline T clamp( T const &val, T const &minVal, T const &maxVal ) - { - if( val < minVal ) - return minVal; - else if( val > maxVal ) - return maxVal; - else - return val; - } + +// This is the preferred clamp operator. Using the clamp macro can lead to +// unexpected side-effects or more expensive code. Even the clamp (all +// lower-case) function can generate more expensive code because of the +// mixed types involved. +template< class T > +T Clamp( T const &val, T const &minVal, T const &maxVal ) +{ + if( val < minVal ) + return minVal; + else if( val > maxVal ) + return maxVal; + else + return val; +} + +// This is the preferred Min operator. Using the MIN macro can lead to unexpected +// side-effects or more expensive code. +template< class T > +T Min( T const &val1, T const &val2 ) +{ + return val1 < val2 ? val1 : val2; +} + +// This is the preferred Max operator. Using the MAX macro can lead to unexpected +// side-effects or more expensive code. +template< class T > +T Max( T const &val1, T const &val2 ) +{ + return val1 > val2 ? val1 : val2; +} + #endif #ifndef FALSE @@ -116,18 +148,7 @@ FORCEINLINE float fpmax( float a, float b ) #define TRUE (!FALSE) #endif - -typedef int BOOL; typedef int qboolean; -typedef unsigned long ULONG; -typedef unsigned char BYTE; -typedef unsigned char byte; -typedef unsigned short word; - -#if !defined __APPLE__ -typedef unsigned int uintptr_t; -#endif - enum ThreeState_t { @@ -152,17 +173,17 @@ typedef float vec_t; #ifdef __cplusplus -inline unsigned long& FloatBits( vec_t& f ) +inline uint32_t& FloatBits( vec_t& f ) { - return *reinterpret_cast(&f); + return *reinterpret_cast(&f); } -inline unsigned long const& FloatBits( vec_t const& f ) +inline uint32_t const& FloatBits( vec_t const& f ) { - return *reinterpret_cast(&f); + return *reinterpret_cast(&f); } -inline vec_t BitsToFloat( unsigned long i ) +inline vec_t BitsToFloat( uint32_t i ) { return *reinterpret_cast(&i); } @@ -172,7 +193,7 @@ inline bool IsFinite( vec_t f ) return ((FloatBits(f) & 0x7F800000) != 0x7F800000); } -inline unsigned long FloatAbsBits( vec_t f ) +inline uint32_t FloatAbsBits( vec_t f ) { return FloatBits(f) & 0x7FFFFFFF; } @@ -216,7 +237,7 @@ inline float FloatNegate( vec_t f ) } -#define FLOAT32_NAN_BITS (unsigned long)0x7FC00000 // not a number! +#define FLOAT32_NAN_BITS (uint32_t)0x7FC00000 // not a number! #define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS ) #define VEC_T_NAN FLOAT32_NAN @@ -248,7 +269,7 @@ struct colorVec #ifndef NOTE_UNUSED -#define NOTE_UNUSED(x) (x = x) // for pesky compiler / lint warnings +#define NOTE_UNUSED(x) (void)(x) // for pesky compiler / lint warnings #endif #ifdef __cplusplus @@ -328,7 +349,7 @@ protected: template< class DummyType > -class CIntHandle32 : public CBaseIntHandle< unsigned long > +class CIntHandle32 : public CBaseIntHandle< uint32_t > { public: inline CIntHandle32() {} diff --git a/public/tier0/commonmacros.h b/public/tier0/commonmacros.h index f67b5915..708443bb 100644 --- a/public/tier0/commonmacros.h +++ b/public/tier0/commonmacros.h @@ -32,11 +32,12 @@ #define SETBITS(iBitVector, bits) ((iBitVector) |= (bits)) #define CLEARBITS(iBitVector, bits) ((iBitVector) &= ~(bits)) -#define FBitSet(iBitVector, bit) ((iBitVector) & (bit)) +#define FBitSet(iBitVector, bits) ((iBitVector) & (bits)) -inline bool IsPowerOfTwo( int value ) +template +inline bool IsPowerOfTwo( T value ) { - return (value & ( value - 1 )) == 0; + return (value & ( value - (T)1 )) == (T)0; } #define CONST_INTEGER_AS_STRING(x) #x //Wraps the integer in quotes, allowing us to form constant strings with it diff --git a/public/tier0/dbg.h b/public/tier0/dbg.h index 150ec659..3c5d722a 100644 --- a/public/tier0/dbg.h +++ b/public/tier0/dbg.h @@ -306,7 +306,7 @@ DBG_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar #ifdef DBGFLAG_ASSERT #define Assert( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false ) -#define AssertMsg( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false ) +#define AssertMsg( _exp, _msg, ... ) _AssertMsg( _exp, (const tchar *)CDbgFmtMsg( _msg, ##__VA_ARGS__ ), ((void)0), false ) #define AssertOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), false ) #define AssertMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, false ) #define AssertFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), _f, false ) @@ -329,7 +329,7 @@ DBG_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar #define Assert( _exp ) ((void)0) #define AssertOnce( _exp ) ((void)0) -#define AssertMsg( _exp, _msg ) ((void)0) +#define AssertMsg( _exp, _msg, ... ) ((void)0) #define AssertMsgOnce( _exp, _msg ) ((void)0) #define AssertFunc( _exp, _f ) ((void)0) #define AssertEquals( _exp, _expectedValue ) ((void)0) @@ -576,7 +576,7 @@ public: va_list arg_ptr; va_start(arg_ptr, pszFormat); - _vsntprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr); + _vsnprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr); va_end(arg_ptr); m_szBuf[sizeof(m_szBuf)-1] = 0; diff --git a/public/tier0/fasttimer.h b/public/tier0/fasttimer.h index d59a93a5..7780c049 100644 --- a/public/tier0/fasttimer.h +++ b/public/tier0/fasttimer.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -11,13 +11,16 @@ #pragma once #endif +#ifdef _WIN32 +#include +#endif + #include #include "tier0/platform.h" -PLATFORM_INTERFACE int64 g_ClockSpeed; -PLATFORM_INTERFACE unsigned long g_dwClockSpeed; +PLATFORM_INTERFACE uint64 g_ClockSpeed; #if defined( _X360 ) && defined( _CERT ) -PLATFORM_INTERFACE unsigned long g_dwFakeFastCounter; +PLATFORM_INTERFACE uint32_t g_dwFakeFastCounter; #endif PLATFORM_INTERFACE double g_ClockSpeedMicrosecondsMultiplier; @@ -30,27 +33,27 @@ friend class CFastTimer; public: CCycleCount(); - CCycleCount( int64 cycles ); + CCycleCount( uint64 cycles ); void Sample(); // Sample the clock. This takes about 34 clocks to execute (or 26,000 calls per millisecond on a P900). void Init(); // Set to zero. void Init( float initTimeMsec ); void Init( double initTimeMsec ) { Init( (float)initTimeMsec ); } - void Init( int64 cycles ); + void Init( uint64 cycles ); bool IsLessThan( CCycleCount const &other ) const; // Compare two counts. // Convert to other time representations. These functions are slow, so it's preferable to call them // during display rather than inside a timing block. - unsigned long GetCycles() const; - int64 GetLongCycles() const; + uint32_t GetCycles() const; + uint64 GetLongCycles() const; - unsigned long GetMicroseconds() const; + uint32_t GetMicroseconds() const; uint64 GetUlMicroseconds() const; double GetMicrosecondsF() const; - void SetMicroseconds( unsigned long nMicroseconds ); + void SetMicroseconds( uint32_t nMicroseconds ); - unsigned long GetMilliseconds() const; + uint32_t GetMilliseconds() const; double GetMillisecondsF() const; double GetSeconds() const; @@ -63,12 +66,12 @@ public: // dest = rSrc1 - rSrc2 static void Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together. - static int64 GetTimestamp(); + static uint64 GetTimestamp(); - int64 m_Int64; + uint64 m_Int64; }; -class CClockSpeedInit +class PLATFORM_CLASS CClockSpeedInit { public: CClockSpeedInit() @@ -76,21 +79,7 @@ public: Init(); } - static void Init() - { -#if defined( _X360 ) && !defined( _CERT ) - PMCStart(); - PMCInitIntervalTimer( 0 ); -#endif - const CPUInformation& pi = GetCPUInformation(); - - g_ClockSpeed = pi.m_Speed; - g_dwClockSpeed = (unsigned long)g_ClockSpeed; - - g_ClockSpeedMicrosecondsMultiplier = 1000000.0 / (double)g_ClockSpeed; - g_ClockSpeedMillisecondsMultiplier = 1000.0 / (double)g_ClockSpeed; - g_ClockSpeedSecondsMultiplier = 1.0f / (double)g_ClockSpeed; - } + static void Init(); }; class CFastTimer @@ -104,7 +93,7 @@ public: CCycleCount GetDurationInProgress() const; // Call without ending. Not that cheap. // Return number of cycles per second on this processor. - static inline unsigned long GetClockSpeed(); + static inline int64 GetClockSpeed(); private: CCycleCount m_Duration; @@ -233,8 +222,6 @@ private: unsigned m_nIters; CCycleCount m_Total; CCycleCount m_Peak; -// bool m_fReport; -// const tchar *m_pszName; }; // -------------------------------------------------------------------------- // @@ -257,87 +244,37 @@ private: inline CCycleCount::CCycleCount() { - Init( (int64)0 ); + Init( (uint64)0 ); } -inline CCycleCount::CCycleCount( int64 cycles ) +inline CCycleCount::CCycleCount( uint64 cycles ) { Init( cycles ); } inline void CCycleCount::Init() { - Init( (int64)0 ); + Init( (uint64)0 ); } inline void CCycleCount::Init( float initTimeMsec ) { if ( g_ClockSpeedMillisecondsMultiplier > 0 ) - Init( (int64)(initTimeMsec / g_ClockSpeedMillisecondsMultiplier) ); + Init( (uint64)(initTimeMsec / g_ClockSpeedMillisecondsMultiplier) ); else - Init( (int64)0 ); + Init( (uint64)0 ); } -inline void CCycleCount::Init( int64 cycles ) +inline void CCycleCount::Init( uint64 cycles ) { m_Int64 = cycles; } -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4189) // warning C4189: local variable is initialized but not referenced -#endif - inline void CCycleCount::Sample() { -#if defined( _X360 ) -#if !defined( _CERT ) - // read the highest resolution timer directly (ticks at native 3.2GHz), bypassing any calls into PMC - // can only resolve 32 bits, rollover is ~1.32 secs - // based on PMCGetIntervalTimer() from the April 2007 XDK - int64 temp; - __asm - { - lis r11,08FFFh - ld r11,011E0h(r11) - rldicl r11,r11,32,32 - // unforunate can't get the inline assembler to write directly into desired target - std r11,temp - } - m_Int64 = temp; -#else - m_Int64 = ++g_dwFakeFastCounter; -#endif -#elif defined( _WIN32 ) - unsigned long* pSample = (unsigned long *)&m_Int64; - __asm - { - // force the cpu to synchronize the instruction queue - // NJS: CPUID can really impact performance in tight loops. - //cpuid - //cpuid - //cpuid - mov ecx, pSample - rdtsc - mov [ecx], eax - mov [ecx+4], edx - } -#elif defined( _LINUX ) - unsigned long* pSample = (unsigned long *)&m_Int64; - __asm__ __volatile__ ( - "rdtsc\n\t" - "movl %%eax, (%0)\n\t" - "movl %%edx, 4(%0)\n\t" - : /* no output regs */ - : "D" (pSample) - : "%eax", "%edx" ); -#endif + m_Int64 = Plat_Rdtsc(); } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - inline CCycleCount& CCycleCount::operator+=( CCycleCount const &other ) { m_Int64 += other.m_Int64; @@ -355,7 +292,7 @@ inline void CCycleCount::Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2 dest.m_Int64 = rSrc1.m_Int64 - rSrc2.m_Int64; } -inline int64 CCycleCount::GetTimestamp() +inline uint64 CCycleCount::GetTimestamp() { CCycleCount c; c.Sample(); @@ -368,19 +305,19 @@ inline bool CCycleCount::IsLessThan(CCycleCount const &other) const } -inline unsigned long CCycleCount::GetCycles() const +inline uint32_t CCycleCount::GetCycles() const { - return (unsigned long)m_Int64; + return (uint32_t)m_Int64; } -inline int64 CCycleCount::GetLongCycles() const +inline uint64 CCycleCount::GetLongCycles() const { return m_Int64; } -inline unsigned long CCycleCount::GetMicroseconds() const +inline uint32_t CCycleCount::GetMicroseconds() const { - return (unsigned long)((m_Int64 * 1000000) / g_ClockSpeed); + return (uint32_t)((m_Int64 * 1000000) / g_ClockSpeed); } inline uint64 CCycleCount::GetUlMicroseconds() const @@ -395,15 +332,15 @@ inline double CCycleCount::GetMicrosecondsF() const } -inline void CCycleCount::SetMicroseconds( unsigned long nMicroseconds ) +inline void CCycleCount::SetMicroseconds( uint32_t nMicroseconds ) { - m_Int64 = ((int64)nMicroseconds * g_ClockSpeed) / 1000000; + m_Int64 = ((uint64)nMicroseconds * g_ClockSpeed) / 1000000; } -inline unsigned long CCycleCount::GetMilliseconds() const +inline uint32_t CCycleCount::GetMilliseconds() const { - return (unsigned long)((m_Int64 * 1000) / g_ClockSpeed); + return (uint32_t)((m_Int64 * 1000) / g_ClockSpeed); } @@ -438,10 +375,10 @@ inline void CFastTimer::End() if ( IsX360() ) { // have to handle rollover, hires timer is only accurate to 32 bits - // more than one overflow should not have occured, otherwise caller should use a slower timer + // more than one overflow should not have occurred, otherwise caller should use a slower timer if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 ) { - // rollover occured + // rollover occurred cnt.m_Int64 += 0x100000000LL; } } @@ -460,10 +397,10 @@ inline CCycleCount CFastTimer::GetDurationInProgress() const if ( IsX360() ) { // have to handle rollover, hires timer is only accurate to 32 bits - // more than one overflow should not have occured, otherwise caller should use a slower timer + // more than one overflow should not have occurred, otherwise caller should use a slower timer if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 ) { - // rollover occured + // rollover occurred cnt.m_Int64 += 0x100000000LL; } } @@ -475,9 +412,9 @@ inline CCycleCount CFastTimer::GetDurationInProgress() const } -inline unsigned long CFastTimer::GetClockSpeed() +inline int64 CFastTimer::GetClockSpeed() { - return g_dwClockSpeed; + return g_ClockSpeed; } @@ -553,15 +490,20 @@ inline CAverageTimeMarker::~CAverageTimeMarker() // CLimitTimer // Use this to time whether a desired interval of time has passed. It's extremely fast -// to check while running. +// to check while running. NOTE: CMicroSecOverage() and CMicroSecLeft() are not as fast to check. class CLimitTimer { public: + CLimitTimer() {} + CLimitTimer( uint64 cMicroSecDuration ) { SetLimit( cMicroSecDuration ); } void SetLimit( uint64 m_cMicroSecDuration ); - bool BLimitReached( void ); + bool BLimitReached() const; + + int CMicroSecOverage() const; + uint64 CMicroSecLeft() const; private: - int64 m_lCycleLimit; + uint64 m_lCycleLimit; }; @@ -569,9 +511,9 @@ private: // Purpose: Initializes the limit timer with a period of time to measure. // Input : cMicroSecDuration - How long a time period to measure //----------------------------------------------------------------------------- -inline void CLimitTimer::SetLimit( uint64 m_cMicroSecDuration ) +inline void CLimitTimer::SetLimit( uint64 cMicroSecDuration ) { - int64 dlCycles = ( ( uint64 ) m_cMicroSecDuration * ( int64 ) g_dwClockSpeed ) / ( int64 ) 1000000L; + uint64 dlCycles = ( ( uint64 ) cMicroSecDuration * g_ClockSpeed ) / ( uint64 ) 1000000L; CCycleCount cycleCount; cycleCount.Sample( ); m_lCycleLimit = cycleCount.GetLongCycles( ) + dlCycles; @@ -582,7 +524,7 @@ inline void CLimitTimer::SetLimit( uint64 m_cMicroSecDuration ) // Purpose: Determines whether our specified time period has passed // Output: true if at least the specified time period has passed //----------------------------------------------------------------------------- -inline bool CLimitTimer::BLimitReached( ) +inline bool CLimitTimer::BLimitReached() const { CCycleCount cycleCount; cycleCount.Sample( ); @@ -590,5 +532,38 @@ inline bool CLimitTimer::BLimitReached( ) } +//----------------------------------------------------------------------------- +// Purpose: If we're over our specified time period, return the amount of the overage. +// Output: # of microseconds since we reached our specified time period. +//----------------------------------------------------------------------------- +inline int CLimitTimer::CMicroSecOverage() const +{ + CCycleCount cycleCount; + cycleCount.Sample(); + uint64 lcCycles = cycleCount.GetLongCycles(); + + if ( lcCycles < m_lCycleLimit ) + return 0; + + return( ( int ) ( ( lcCycles - m_lCycleLimit ) * ( uint64 ) 1000000L / g_ClockSpeed ) ); +} + + +//----------------------------------------------------------------------------- +// Purpose: If we're under our specified time period, return the amount under. +// Output: # of microseconds until we reached our specified time period, 0 if we've passed it +//----------------------------------------------------------------------------- +inline uint64 CLimitTimer::CMicroSecLeft() const +{ + CCycleCount cycleCount; + cycleCount.Sample(); + uint64 lcCycles = cycleCount.GetLongCycles(); + + if ( lcCycles >= m_lCycleLimit ) + return 0; + + return( ( uint64 ) ( ( m_lCycleLimit - lcCycles ) * ( uint64 ) 1000000L / g_ClockSpeed ) ); +} + #endif // FASTTIMER_H diff --git a/public/tier0/icommandline.h b/public/tier0/icommandline.h index 556eff86..99924a85 100644 --- a/public/tier0/icommandline.h +++ b/public/tier0/icommandline.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -37,6 +37,12 @@ public: virtual int ParmCount() const = 0; virtual int FindParm( const char *psz ) const = 0; // Returns 0 if not found. virtual const char* GetParm( int nIndex ) const = 0; + + virtual bool HasParm( const char *parm ) = 0; + + // Additions in 9247927 (2024-10-11) + virtual void CreateCmdLine1( const char *commandline, bool unknown ) = 0; + virtual void CreateCmdLine1( int argc, char **argv, bool unknown ) = 0; }; //----------------------------------------------------------------------------- diff --git a/public/tier0/memalloc.h b/public/tier0/memalloc.h index 2840d095..f0fb983a 100644 --- a/public/tier0/memalloc.h +++ b/public/tier0/memalloc.h @@ -73,7 +73,7 @@ public: // FIXME: Remove when we have our own allocator // these methods of the Crt debug code is used in our codebase currently - virtual long CrtSetBreakAlloc( long lNewBreakAlloc ) = 0; + virtual int32_t CrtSetBreakAlloc( int32_t lNewBreakAlloc ) = 0; virtual int CrtSetReportMode( int nReportType, int nReportMode ) = 0; virtual int CrtIsValidHeapPointer( const void *pMem ) = 0; virtual int CrtIsValidPointer( const void *pMem, unsigned int size, int access ) = 0; @@ -178,7 +178,7 @@ inline void *MemAlloc_AllocAligned( size_t size, size_t align ) { unsigned char *pAlloc, *pResult; - if (!IsPowerOfTwo(align)) + if (!ValueIsPowerOfTwo(align)) return NULL; align = (align > sizeof(void *) ? align : sizeof(void *)) - 1; @@ -196,7 +196,7 @@ inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFi { unsigned char *pAlloc, *pResult; - if (!IsPowerOfTwo(align)) + if (!ValueIsPowerOfTwo(align)) return NULL; align = (align > sizeof(void *) ? align : sizeof(void *)) - 1; @@ -248,7 +248,7 @@ inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const cha inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align ) { - if ( !IsPowerOfTwo( align ) ) + if ( !ValueIsPowerOfTwo( align ) ) return NULL; // Don't change alignment between allocation + reallocation. @@ -382,7 +382,7 @@ public: #pragma warning(disable:4290) #pragma warning(push) - #include + #include // MEM_DEBUG_CLASSNAME is opt-in. // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads diff --git a/public/tier0/memoverride.cpp b/public/tier0/memoverride.cpp index 453ca48b..f7c8f6b9 100644 --- a/public/tier0/memoverride.cpp +++ b/public/tier0/memoverride.cpp @@ -614,8 +614,8 @@ int* AFNAME(_crtDbgFlag)(void) return AFRET(_crtDbgFlag); } -long _crtBreakAlloc; /* Break on this allocation */ -long* AFNAME(_crtBreakAlloc) (void) +int32_t _crtBreakAlloc; /* Break on this allocation */ +int32_t* AFNAME(_crtBreakAlloc) (void) { return AFRET(_crtBreakAlloc); } @@ -631,7 +631,7 @@ _CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook( _CRT_ALLOC_HOOK pfnNewHook ) return NULL; } -long __cdecl _CrtSetBreakAlloc( long lNewBreakAlloc ) +int32_t __cdecl _CrtSetBreakAlloc( int32_t lNewBreakAlloc ) { return g_pMemAlloc->CrtSetBreakAlloc( lNewBreakAlloc ); } @@ -653,7 +653,7 @@ int __cdecl _CrtCheckMemory( void ) } int __cdecl _CrtIsMemoryBlock( const void *pMem, unsigned int nSize, - long *plRequestNumber, char **ppFileName, int *pnLine ) + int32_t *plRequestNumber, char **ppFileName, int *pnLine ) { DebuggerBreak(); return 1; @@ -690,7 +690,7 @@ void __cdecl _CrtDoForAllClientObjects( void (*pfn)(void *, void *), void * pCon //----------------------------------------------------------------------------- // Methods in dbgrpt.cpp //----------------------------------------------------------------------------- -long _crtAssertBusy = -1; +int32_t _crtAssertBusy = -1; int __cdecl _CrtSetReportMode( int nReportType, int nReportMode ) { @@ -1165,7 +1165,7 @@ SIZE_T WINAPI XMemSize( PVOID pAddress, DWORD dwAllocAttributes ) #define MAX_LC_LEN (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3) struct _is_ctype_compatible { - unsigned long id; + uint32_t id; int is_clike; }; typedef struct setloc_struct { @@ -1188,15 +1188,15 @@ typedef struct setloc_struct { } _setloc_struct, *_psetloc_struct; struct _tiddata { - unsigned long _tid; /* thread ID */ + uint32_t _tid; /* thread ID */ uintptr_t _thandle; /* thread handle */ int _terrno; /* errno value */ - unsigned long _tdoserrno; /* _doserrno value */ + uint32_t _tdoserrno; /* _doserrno value */ unsigned int _fpds; /* Floating Point data segment */ - unsigned long _holdrand; /* rand() seed value */ + uint32_t _holdrand; /* rand() seed value */ char * _token; /* ptr to strtok() token */ wchar_t * _wtoken; /* ptr to wcstok() token */ unsigned char * _mtoken; /* ptr to _mbstok() token */ @@ -1235,7 +1235,7 @@ struct _tiddata { int _ownlocale; /* if 1, this thread owns its own locale */ /* following field is needed by NLG routines */ - unsigned long _NLG_dwCode; + uint32_t _NLG_dwCode; /* * Per-Thread data needed by C++ Exception Handling @@ -1272,7 +1272,7 @@ struct _tiddata { int _cxxReThrow; /* Set to True if it's a rethrown C++ Exception */ - unsigned long __initDomain; /* initial domain used by _beginthread[ex] for managed function */ + uint32_t __initDomain; /* initial domain used by _beginthread[ex] for managed function */ }; typedef struct _tiddata * _ptiddata; diff --git a/public/tier0/platform.h b/public/tier0/platform.h index 859ba16e..33811494 100644 --- a/public/tier0/platform.h +++ b/public/tier0/platform.h @@ -9,6 +9,14 @@ #ifndef PLATFORM_H #define PLATFORM_H +#include + +#ifdef PLATFORM_64BITS +typedef uint64_t ThreadId_t; +#else +typedef uint32_t ThreadId_t; +#endif + #if defined( _X360 ) #define NO_STEAM #define NO_VOICE @@ -36,10 +44,11 @@ // feature enables #define NEW_SOFTWARE_LIGHTING -#if defined(_LINUX) || defined(__APPLE__) +#ifdef POSIX // need this for _alloca #include -#endif // _LINUX +#include +#endif #if defined __APPLE__ #include @@ -134,9 +143,11 @@ typedef unsigned char uint8; typedef signed char int8; -#ifdef __x86_64__ +#if defined( __x86_64__ ) || defined( _WIN64 ) +#ifndef X64BITS #define X64BITS #endif +#endif #if defined( _WIN32 ) @@ -168,14 +179,14 @@ typedef short int16; typedef unsigned short uint16; typedef int int32; typedef unsigned int uint32; -typedef long long int64; -typedef unsigned long long uint64; +typedef int64_t int64; +typedef uint64_t uint64; #ifdef X64BITS -typedef long long intp; -typedef unsigned long long uintp; +typedef int64_t intp; +typedef uint64_t uintp; #else -typedef int intp; -typedef unsigned int uintp; +typedef int32_t intp; +typedef uint32_t uintp; #endif #endif // else _WIN32 @@ -224,6 +235,14 @@ typedef unsigned int uint; #define abstract_class class NO_VTABLE #endif + +// MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms +// As a result, we pick the least common denominator here. This should be used anywhere +// you might typically want to use RAND_MAX +#define VALVE_RAND_MAX 0x7fff + + + /* FIXME: Enable this when we no longer fear change =) @@ -232,32 +251,32 @@ FIXME: Enable this when we no longer fear change =) #include // Maximum and minimum representable values -#define INT8_MAX SCHAR_MAX -#define INT16_MAX SHRT_MAX -#define INT32_MAX LONG_MAX -#define INT64_MAX (((int64)~0) >> 1) +#define INT8_MAX SCHAR_MAX +#define INT16_MAX SHRT_MAX +#define INT32_MAX LONG_MAX +#define INT64_MAX (((int64)~0) >> 1) -#define INT8_MIN SCHAR_MIN -#define INT16_MIN SHRT_MIN -#define INT32_MIN LONG_MIN -#define INT64_MIN (((int64)1) << 63) +#define INT8_MIN SCHAR_MIN +#define INT16_MIN SHRT_MIN +#define INT32_MIN LONG_MIN +#define INT64_MIN (((int64)1) << 63) -#define UINT8_MAX ((uint8)~0) -#define UINT16_MAX ((uint16)~0) -#define UINT32_MAX ((uint32)~0) -#define UINT64_MAX ((uint64)~0) +#define UINT8_MAX ((uint8)~0) +#define UINT16_MAX ((uint16)~0) +#define UINT32_MAX ((uint32)~0) +#define UINT64_MAX ((uint64)~0) -#define UINT8_MIN 0 -#define UINT16_MIN 0 -#define UINT32_MIN 0 -#define UINT64_MIN 0 +#define UINT8_MIN 0 +#define UINT16_MIN 0 +#define UINT32_MIN 0 +#define UINT64_MIN 0 #ifndef UINT_MIN -#define UINT_MIN UINT32_MIN +#define UINT_MIN UINT32_MIN #endif -#define FLOAT32_MAX FLT_MAX -#define FLOAT64_MAX DBL_MAX +#define FLOAT32_MAX FLT_MAX +#define FLOAT64_MAX DBL_MAX #define FLOAT32_MIN FLT_MIN #define FLOAT64_MIN DBL_MIN @@ -283,21 +302,12 @@ typedef void * HINSTANCE; #define MAX_PATH 260 #endif - -#ifdef GNUC -#undef offsetof -//#define offsetof( type, var ) __builtin_offsetof( type, var ) -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#else -#undef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif - - #define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression // Used to step into the debugger -#if defined( _WIN32 ) && !defined( _X360 ) +#if defined( _WIN64 ) && !defined( _X360 ) +#define DebuggerBreak() {} +#elif defined( _WIN32 ) && !defined( _X360 ) #define DebuggerBreak() __asm { int 3 } #elif defined( _X360 ) #define DebuggerBreak() DebugBreak() @@ -331,11 +341,58 @@ typedef void * HINSTANCE; #define DECL_ALIGN(x) /* */ #endif +#ifdef _MSC_VER +// MSVC has the align at the start of the struct +#define ALIGN4 DECL_ALIGN(4) #define ALIGN8 DECL_ALIGN(8) #define ALIGN16 DECL_ALIGN(16) #define ALIGN32 DECL_ALIGN(32) #define ALIGN128 DECL_ALIGN(128) +#define ALIGN4_POST +#define ALIGN8_POST +#define ALIGN16_POST +#define ALIGN32_POST +#define ALIGN128_POST +#elif defined( GNUC ) +// gnuc has the align decoration at the end +#define ALIGN4 +#define ALIGN8 +#define ALIGN16 +#define ALIGN32 +#define ALIGN128 + +#define ALIGN4_POST DECL_ALIGN(4) +#define ALIGN8_POST DECL_ALIGN(8) +#define ALIGN16_POST DECL_ALIGN(16) +#define ALIGN32_POST DECL_ALIGN(32) +#define ALIGN128_POST DECL_ALIGN(128) +#else +#error +#endif + +// Pull in the /analyze code annotations. +#include "annotations.h" + + +//----------------------------------------------------------------------------- +// Stack-based allocation related helpers +//----------------------------------------------------------------------------- +#if defined( GNUC ) + #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) ) +#ifdef _LINUX + #define mallocsize( _p ) ( malloc_usable_size( _p ) ) +#elif defined(OSX) + #define mallocsize( _p ) ( malloc_size( _p ) ) +#else +#error +#endif +#elif defined ( _WIN32 ) + #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) ) + #define mallocsize( _p ) ( _msize( _p ) ) +#endif + +#define stackfree( _p ) 0 // Linux had a few areas where it didn't construct objects in the same order that Windows does. // So when CVProfile::CVProfile() would access g_pMemAlloc, it would crash because the allocator wasn't initalized yet. @@ -438,15 +495,6 @@ typedef void * HINSTANCE; // as little code as possible, and throw an assertion in debug. #define NO_DEFAULT default: UNREACHABLE(); -#ifdef _WIN32 -// Alloca defined for this platform -#define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) ) -#define stackfree( _p ) -#elif defined(_LINUX) || defined(__APPLE__) -// Alloca defined for this platform -#define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) ) -#define stackfree( _p ) -#endif #ifdef _WIN32 #define RESTRICT __restrict @@ -497,6 +545,11 @@ typedef void * HINSTANCE; #endif +#ifdef POSIX +typedef uintp HMODULE; +typedef void *HANDLE; +#endif + //----------------------------------------------------------------------------- // fsel //----------------------------------------------------------------------------- @@ -525,6 +578,7 @@ static FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) //----------------------------------------------------------------------------- //#define CHECK_FLOAT_EXCEPTIONS 1 +#if !defined( _WIN64 ) #if !defined( _X360 ) #if defined( _MSC_VER ) @@ -612,6 +666,7 @@ inline void SetupFPUControlWord() } #endif // _X360 +#endif // _WIN64 //----------------------------------------------------------------------------- // Purpose: Standard functions for handling endian-ness @@ -670,7 +725,7 @@ inline T DWordSwap360Intr( T dw ) return output; } -#elif defined( _MSC_VER ) +#elif defined( _MSC_VER ) && !defined( _WIN64 ) #define WordSwap WordSwapAsm #define DWordSwap DWordSwapAsm @@ -770,61 +825,62 @@ inline T DWordSwapAsm( T dw ) // platform/compiler this should be tested. inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; } inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; } -inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; } +inline int32_t BigLong( int32_t val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; } inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; } inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); } inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); } -inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); } +inline int32_t LittleLong( int32_t val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); } inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); } inline short SwapShort( short val ) { return WordSwap( val ); } inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); } -inline long SwapLong( long val ) { return DWordSwap( val ); } +inline int32_t SwapLong( int32_t val ) { return DWordSwap( val ); } inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); } // Pass floats by pointer for swapping to avoid truncation in the fpu inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); } inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); } inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); } - #endif #if _X360 -inline unsigned long LoadLittleDWord( unsigned long *base, unsigned int dwordIndex ) +inline uint32_t LoadLittleDWord( uint32_t *base, unsigned int dwordIndex ) { return __loadwordbytereverse( dwordIndex<<2, base ); } -inline void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword ) +inline void StoreLittleDWord( uint32_t *base, unsigned int dwordIndex, uint32_t dword ) { __storewordbytereverse( dword, dwordIndex<<2, base ); } #else -inline unsigned long LoadLittleDWord( unsigned long *base, unsigned int dwordIndex ) +inline uint32_t LoadLittleDWord( uint32_t *base, unsigned int dwordIndex ) { return LittleDWord( base[dwordIndex] ); } -inline void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword ) +inline void StoreLittleDWord( uint32_t *base, unsigned int dwordIndex, uint32_t dword ) { base[dwordIndex] = LittleDWord(dword); } #endif - #ifndef STATIC_TIER0 #ifdef TIER0_DLL_EXPORT - #define PLATFORM_INTERFACE DLL_EXPORT - #define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT +#define PLATFORM_INTERFACE DLL_EXPORT +#define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT +#define PLATFORM_CLASS DLL_CLASS_EXPORT #else - #define PLATFORM_INTERFACE DLL_IMPORT - #define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT +#define PLATFORM_INTERFACE DLL_IMPORT +#define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT +#define PLATFORM_CLASS DLL_CLASS_IMPORT #endif #else // BUILD_AS_DLL #define PLATFORM_INTERFACE extern #define PLATFORM_OVERLOAD +#define PLATFORM_CLASS #endif // BUILD_AS_DLL @@ -838,7 +894,42 @@ PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode(); PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded. -PLATFORM_INTERFACE unsigned long Plat_MSTime(); // Time in milliseconds. +PLATFORM_INTERFACE uint32_t Plat_MSTime(); // Time in milliseconds. +PLATFORM_INTERFACE char * Plat_ctime( const time_t *timep, char *buf, size_t bufsize ); +PLATFORM_INTERFACE struct tm * Plat_gmtime( const time_t *timep, struct tm *result ); +PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr ); +PLATFORM_INTERFACE struct tm * Plat_localtime( const time_t *timep, struct tm *result ); + +#if defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) + extern "C" unsigned __int64 __rdtsc(); + #pragma intrinsic(__rdtsc) +#endif + +inline uint64 Plat_Rdtsc() +{ +#if defined( _X360 ) + return ( uint64 )__mftb32(); +#elif defined( _WIN64 ) + return ( uint64 )__rdtsc(); +#elif defined( _WIN32 ) + #if defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) + return ( uint64 )__rdtsc(); + #else + __asm rdtsc; + __asm ret; + #endif +#elif defined( __i386__ ) + uint64 val; + __asm__ __volatile__ ( "rdtsc" : "=A" (val) ); + return val; +#elif defined( __x86_64__ ) + uint32 lo, hi; + __asm__ __volatile__ ( "rdtsc" : "=a" (lo), "=d" (hi)); + return ( ( ( uint64 )hi ) << 32 ) | lo; +#else + #error +#endif +} // b/w compatibility #define Sys_FloatTime Plat_FloatTime @@ -860,23 +951,27 @@ struct CPUInformation uint8 m_nLogicalProcessors; // Number op logical processors. uint8 m_nPhysicalProcessors; // Number of physical processors + + bool m_bSSE3 : 1, + m_bSSSE3 : 1, + m_bSSE4a : 1, + m_bSSE41 : 1, + m_bSSE42 : 1; int64 m_Speed; // In cycles per second. tchar* m_szProcessorID; // Processor vendor Identification. + + uint32 m_nModel; + uint32 m_nFeatures[3]; + + CPUInformation(): m_Size(0){} }; -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" -#endif +// Have to return a pointer, not a reference, because references are not compatible with the +// extern "C" implied by PLATFORM_INTERFACE. +PLATFORM_INTERFACE const CPUInformation* GetCPUInformation(); -PLATFORM_INTERFACE const CPUInformation& GetCPUInformation(); - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear ); @@ -891,25 +986,25 @@ PLATFORM_INTERFACE void ShutdownPME(); //----------------------------------------------------------------------------- // Registers the current thread with Tier0's thread management system. // This should be called on every thread created in the game. -PLATFORM_INTERFACE unsigned long Plat_RegisterThread( const tchar *pName = _T("Source Thread")); +PLATFORM_INTERFACE ThreadId_t Plat_RegisterThread( const tchar *pName = _T("Source Thread")); // Registers the current thread as the primary thread. -PLATFORM_INTERFACE unsigned long Plat_RegisterPrimaryThread(); +PLATFORM_INTERFACE ThreadId_t Plat_RegisterPrimaryThread(); // VC-specific. Sets the thread's name so it has a friendly name in the debugger. // This should generally only be handled by Plat_RegisterThread and Plat_RegisterPrimaryThread -PLATFORM_INTERFACE void Plat_SetThreadName( unsigned long dwThreadID, const tchar *pName ); +PLATFORM_INTERFACE void Plat_SetThreadName( ThreadId_t dwThreadID, const tchar *pName ); // These would be private if it were possible to export private variables from a .DLL. // They need to be variables because they are checked by inline functions at performance // critical places. -PLATFORM_INTERFACE unsigned long Plat_PrimaryThreadID; +PLATFORM_INTERFACE ThreadId_t Plat_PrimaryThreadID; // Returns the ID of the currently executing thread. -PLATFORM_INTERFACE unsigned long Plat_GetCurrentThreadID(); +PLATFORM_INTERFACE ThreadId_t Plat_GetCurrentThreadID(); // Returns the ID of the primary thread. -inline unsigned long Plat_GetPrimaryThreadID() +inline ThreadId_t Plat_GetPrimaryThreadID() { return Plat_PrimaryThreadID; } @@ -968,6 +1063,16 @@ PLATFORM_INTERFACE void Plat_DebugString( const char * ); #define Plat_DebugString(s) ((void)0) #endif +#if defined(_WIN32) +PLATFORM_INTERFACE bool Plat_IsChromeOS(); +PLATFORM_INTERFACE bool Plat_IsGamescope(); +PLATFORM_INTERFACE bool Plat_IsSteamConsoleMode(); +PLATFORM_INTERFACE bool Plat_IsSteamDeck(); +PLATFORM_INTERFACE bool Plat_IsSteamOS(); +PLATFORM_INTERFACE bool Plat_IsSteamOS3(); +PLATFORM_INTERFACE bool Plat_IsTesla(); +#endif + //----------------------------------------------------------------------------- // XBOX Components valid in PC compilation space //----------------------------------------------------------------------------- diff --git a/public/tier0/systeminformation.h b/public/tier0/systeminformation.h index a64b13cb..2285edb4 100644 --- a/public/tier0/systeminformation.h +++ b/public/tier0/systeminformation.h @@ -35,15 +35,15 @@ enum SYSTEM_CALL_RESULT_t // struct PAGED_POOL_INFO_t { - unsigned long numPagesUsed; // Number of Paged Pool pages used - unsigned long numPagesFree; // Number of Paged Pool pages free + uint32_t numPagesUsed; // Number of Paged Pool pages used + uint32_t numPagesFree; // Number of Paged Pool pages free }; // // Plat_GetMemPageSize // Returns the size of a memory page in kilobytes. // -PLATFORM_INTERFACE unsigned long Plat_GetMemPageSize(); +PLATFORM_INTERFACE uint32_t Plat_GetMemPageSize(); // // Plat_GetPagedPoolInfo diff --git a/public/tier0/threadtools.h b/public/tier0/threadtools.h index e0c9317b..4e64c550 100644 --- a/public/tier0/threadtools.h +++ b/public/tier0/threadtools.h @@ -1,4 +1,4 @@ -//========== Copyright © 2005, Valve Corporation, All rights reserved. ======== +//========== Copyright � 2005, Valve Corporation, All rights reserved. ======== // // Purpose: A collection of utility classes to simplify thread handling, and // as much as possible contain portability problems. Here avoiding @@ -76,8 +76,6 @@ const unsigned TT_INFINITE = 0xffffffff; #endif // NO_THREAD_LOCAL -typedef unsigned long ThreadId_t; - //----------------------------------------------------------------------------- // // Simple thread creation. Differs from VCR mode/CreateThread/_beginthreadex @@ -94,8 +92,14 @@ TT_INTERFACE bool ReleaseThreadHandle( ThreadHandle_t ); //----------------------------------------------------------------------------- +#if defined( PLATFORM_WINDOWS ) && !defined( PLATFORM_64BITS ) +extern "C" unsigned long __declspec(dllimport) __stdcall GetCurrentThreadId(); +inline ThreadId_t ThreadGetCurrentId() { return GetCurrentThreadId(); }; +#else +TT_INTERFACE ThreadId_t ThreadGetCurrentId(); +#endif + TT_INTERFACE void ThreadSleep(unsigned duration = 0); -TT_INTERFACE uint ThreadGetCurrentId(); TT_INTERFACE ThreadHandle_t ThreadGetCurrentHandle(); TT_INTERFACE int ThreadGetPriority( ThreadHandle_t hThread = NULL ); TT_INTERFACE bool ThreadSetPriority( ThreadHandle_t hThread, int priority ); @@ -108,14 +112,16 @@ typedef int (*ThreadedLoadLibraryFunc_t)(); TT_INTERFACE void SetThreadedLoadLibraryFunc( ThreadedLoadLibraryFunc_t func ); TT_INTERFACE ThreadedLoadLibraryFunc_t GetThreadedLoadLibraryFunc(); -#if defined( _WIN32 ) && !defined( _WIN64 ) && !defined( _X360 ) -extern "C" unsigned long __declspec(dllimport) __stdcall GetCurrentThreadId(); -#define ThreadGetCurrentId GetCurrentThreadId +#if defined( _WIN64 ) +#include +#include #endif inline void ThreadPause() { -#if defined( _WIN32 ) && !defined( _X360 ) +#if defined( _WIN64 ) + _mm_pause(); +#elif defined( _WIN32 ) && !defined( _X360 ) __asm pause; #elif defined _LINUX || defined __APPLE__ __asm __volatile("pause"); @@ -180,28 +186,52 @@ extern "C" #pragma intrinsic( _InterlockedExchangeAdd ) #pragma intrinsic( _InterlockedIncrement ) -inline long ThreadInterlockedIncrement( long volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedIncrement( p ); } -inline long ThreadInterlockedDecrement( long volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedDecrement( p ); } -inline long ThreadInterlockedExchange( long volatile *p, long value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchange( p, value ); } -inline long ThreadInterlockedExchangeAdd( long volatile *p, long value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchangeAdd( p, value ); } -inline long ThreadInterlockedCompareExchange( long volatile *p, long value, long comperand ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedCompareExchange( p, value, comperand ); } -inline bool ThreadInterlockedAssignIf( long volatile *p, long value, long comperand ) { Assert( (size_t)p % 4 == 0 ); return ( _InterlockedCompareExchange( p, value, comperand ) == comperand ); } -#else -TT_INTERFACE long ThreadInterlockedIncrement( long volatile * ); -TT_INTERFACE long ThreadInterlockedDecrement( long volatile * ); -TT_INTERFACE long ThreadInterlockedExchange( long volatile *, long value ); -TT_INTERFACE long ThreadInterlockedExchangeAdd( long volatile *, long value ); -TT_INTERFACE long ThreadInterlockedCompareExchange( long volatile *, long value, long comperand ); -TT_INTERFACE bool ThreadInterlockedAssignIf( long volatile *, long value, long comperand ); +inline int32_t ThreadInterlockedIncrement( int32_t volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedIncrement( (volatile long*)p ); } +inline int32_t ThreadInterlockedDecrement( int32_t volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedDecrement( (volatile long*)p ); } +inline int32_t ThreadInterlockedExchange( int32_t volatile *p, int32_t value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchange( (volatile long*)p, value ); } +inline int32_t ThreadInterlockedExchangeAdd( int32_t volatile *p, int32_t value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchangeAdd( (volatile long*)p, value ); } +inline int32_t ThreadInterlockedCompareExchange( int32_t volatile *p, int32_t value, int32_t comperand ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedCompareExchange( (volatile long*)p, value, comperand ); } +inline bool ThreadInterlockedAssignIf( int32_t volatile *p, int32_t value, int32_t comperand ) { Assert( (size_t)p % 4 == 0 ); return ( _InterlockedCompareExchange( (volatile long*)p, value, comperand ) == comperand ); } + +#ifdef PLATFORM_64BITS +#pragma intrinsic( _InterlockedCompareExchange64 ) +#pragma intrinsic( _InterlockedDecrement64 ) +#pragma intrinsic( _InterlockedExchange64 ) +#pragma intrinsic( _InterlockedExchangeAdd64 ) +#pragma intrinsic( _InterlockedIncrement64 ) + +inline int64 ThreadInterlockedIncrement64( int64 volatile *p ) { Assert( (size_t)p % 8 == 0 ); return _InterlockedIncrement64( p ); } +inline int64 ThreadInterlockedDecrement64( int64 volatile *p ) { Assert( (size_t)p % 8 == 0 ); return _InterlockedDecrement64( p ); } +inline int64 ThreadInterlockedExchange64( int64 volatile *p, int64 value ) { Assert( (size_t)p % 8 == 0 ); return _InterlockedExchange64( p, value ); } +inline int64 ThreadInterlockedExchangeAdd64( int64 volatile *p, int64 value ) { Assert( (size_t)p % 8 == 0 ); return _InterlockedExchangeAdd64( p, value ); } +inline int64 ThreadInterlockedCompareExchange64( int64 volatile *p, int64 value, int64 comperand ) { Assert( (size_t)p % 8 == 0 ); return _InterlockedCompareExchange64( p, value, comperand ); } +inline bool ThreadInterlockedAssignIf64( int64 volatile *p, int64 value, int64 comperand ) { Assert( (size_t)p % 8 == 0 ); return ( _InterlockedCompareExchange64( p, value, comperand ) == comperand ); } #endif -inline unsigned ThreadInterlockedExchangeSubtract( long volatile *p, long value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, -value ); } +#else // USE_INTRINSIC_INTERLOCKED -#if defined( USE_INTRINSIC_INTERLOCKED ) && !defined( _WIN64 ) +inline int32_t ThreadInterlockedIncrement( int32_t volatile * pDest ) { Assert( (size_t)pDest % 4 == 0 ); return __atomic_add_fetch( pDest, 1, __ATOMIC_ACQ_REL ); } +inline int32_t ThreadInterlockedDecrement( int32_t volatile * pDest ) { Assert( (size_t)pDest % 4 == 0 ); return __atomic_sub_fetch( pDest, 1, __ATOMIC_ACQ_REL ); } +inline int32_t ThreadInterlockedExchange( int32_t volatile * pDest, int32_t value ) { Assert( (size_t)pDest % 4 == 0 ); return __atomic_exchange_n( pDest, value, __ATOMIC_ACQ_REL ); } +inline int32_t ThreadInterlockedExchangeAdd( int32_t volatile * pDest, int32_t value ) { Assert( (size_t)pDest % 4 == 0 ); return __atomic_fetch_add( pDest, value, __ATOMIC_ACQ_REL ); } +inline int32_t ThreadInterlockedCompareExchange( int32_t volatile * pDest, int32_t value, int32_t comperand ) { Assert( (size_t)pDest % 4 == 0 ); int32* alignedComperand = (int32*)aligned_alloc(4, sizeof(int32)); *alignedComperand = comperand; auto initial = __atomic_load_n( pDest, __ATOMIC_ACQUIRE ); __atomic_compare_exchange_n( pDest, alignedComperand, value, false, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED ); free(alignedComperand); return initial; } +inline bool ThreadInterlockedAssignIf( int32_t volatile * pDest, int32_t value, int32_t comperand ) { Assert( (size_t)pDest % 4 == 0 ); return __atomic_compare_exchange_n( pDest, &comperand, value, false, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED ); } + +#endif + +inline int32_t ThreadInterlockedExchangeSubtract( int32_t volatile *p, int32_t value ) { return ThreadInterlockedExchangeAdd( (int32_t volatile *)p, -value ); } + +#if defined( USE_INTRINSIC_INTERLOCKED ) #define TIPTR() -inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)_InterlockedExchange( reinterpret_cast(p), reinterpret_cast(value) ); } -inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)_InterlockedCompareExchange( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ); } -inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ( _InterlockedCompareExchange( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ) == reinterpret_cast(comperand) ); } +#ifdef PLATFORM_64BITS +inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)( ThreadInterlockedExchange64( reinterpret_cast(p), reinterpret_cast(value) ) ); } +inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)( ThreadInterlockedCompareExchange64( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ) ); } +inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ThreadInterlockedAssignIf64( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ); } +#else +inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)( ThreadInterlockedExchange( reinterpret_cast(p), reinterpret_cast(value) ) ); } +inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)( ThreadInterlockedCompareExchange( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ) ); } +inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ( ThreadInterlockedCompareExchange( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ) == reinterpret_cast(comperand) ); } +#endif #else TT_INTERFACE void *ThreadInterlockedExchangePointer( void * volatile *, void *value ); TT_INTERFACE void *ThreadInterlockedCompareExchangePointer( void * volatile *, void *value, void *comperand ); @@ -212,28 +242,33 @@ inline void const *ThreadInterlockedExchangePointerToConst( void const * volatil inline void const *ThreadInterlockedCompareExchangePointerToConst( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedCompareExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } inline bool ThreadInterlockedAssignPointerToConstIf( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedAssignPointerIf( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } +#if !defined( USE_INTRINSIC_INTERLOCKED ) || ( defined( _WIN32 ) && !defined( PLATFORM_64BITS ) ) +#if defined( _LINUX ) && defined( PLATFORM_64BITS ) +// http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html#Atomic-Builtins +// https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html +inline int64 ThreadInterlockedIncrement64( int64 volatile * pDest ) { Assert( (size_t)pDest % 8 == 0 ); return __atomic_add_fetch( pDest, 1, __ATOMIC_ACQ_REL ); } +inline int64 ThreadInterlockedDecrement64( int64 volatile * pDest ) { Assert( (size_t)pDest % 8 == 0 ); return __atomic_sub_fetch( pDest, 1, __ATOMIC_ACQ_REL ); } +inline int64 ThreadInterlockedExchange64( int64 volatile * pDest, int64 value ) { Assert( (size_t)pDest % 8 == 0 ); return __atomic_exchange_n( pDest, value, __ATOMIC_ACQ_REL ); } +inline int64 ThreadInterlockedExchangeAdd64( int64 volatile * pDest, int64 value ) { Assert( (size_t)pDest % 8 == 0 ); return __atomic_fetch_add( pDest, value, __ATOMIC_ACQ_REL ); } +inline int64 ThreadInterlockedCompareExchange64( int64 volatile * pDest, int64 value, int64 comperand ) { Assert( (size_t)pDest % 8 == 0 ); int64* alignedComperand = (int64*)aligned_alloc(8, sizeof(int64)); *alignedComperand = comperand; auto initial = __atomic_load_n( pDest, __ATOMIC_ACQUIRE ); __atomic_compare_exchange_n( pDest, alignedComperand, value, false, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED ); free(alignedComperand); return initial; } +inline bool ThreadInterlockedAssignIf64( int64 volatile *pDest, int64 value, int64 comperand ) { Assert( (size_t)pDest % 8 == 0 ); return __atomic_compare_exchange_n( pDest, &comperand, value, false, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED ); } +#else TT_INTERFACE int64 ThreadInterlockedIncrement64( int64 volatile * ); TT_INTERFACE int64 ThreadInterlockedDecrement64( int64 volatile * ); TT_INTERFACE int64 ThreadInterlockedCompareExchange64( int64 volatile *, int64 value, int64 comperand ); TT_INTERFACE int64 ThreadInterlockedExchange64( int64 volatile *, int64 value ); TT_INTERFACE int64 ThreadInterlockedExchangeAdd64( int64 volatile *, int64 value ); TT_INTERFACE bool ThreadInterlockedAssignIf64(volatile int64 *pDest, int64 value, int64 comperand ); +#endif +#endif -inline unsigned ThreadInterlockedExchangeSubtract( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline unsigned ThreadInterlockedIncrement( unsigned volatile *p ) { return ThreadInterlockedIncrement( (long volatile *)p ); } -inline unsigned ThreadInterlockedDecrement( unsigned volatile *p ) { return ThreadInterlockedDecrement( (long volatile *)p ); } -inline unsigned ThreadInterlockedExchange( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchange( (long volatile *)p, value ); } -inline unsigned ThreadInterlockedExchangeAdd( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline unsigned ThreadInterlockedCompareExchange( unsigned volatile *p, unsigned value, unsigned comperand ) { return ThreadInterlockedCompareExchange( (long volatile *)p, value, comperand ); } -inline bool ThreadInterlockedAssignIf( unsigned volatile *p, unsigned value, unsigned comperand ) { return ThreadInterlockedAssignIf( (long volatile *)p, value, comperand ); } - -inline int ThreadInterlockedExchangeSubtract( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline int ThreadInterlockedIncrement( int volatile *p ) { return ThreadInterlockedIncrement( (long volatile *)p ); } -inline int ThreadInterlockedDecrement( int volatile *p ) { return ThreadInterlockedDecrement( (long volatile *)p ); } -inline int ThreadInterlockedExchange( int volatile *p, int value ) { return ThreadInterlockedExchange( (long volatile *)p, value ); } -inline int ThreadInterlockedExchangeAdd( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline int ThreadInterlockedCompareExchange( int volatile *p, int value, int comperand ) { return ThreadInterlockedCompareExchange( (long volatile *)p, value, comperand ); } -inline bool ThreadInterlockedAssignIf( int volatile *p, int value, int comperand ) { return ThreadInterlockedAssignIf( (long volatile *)p, value, comperand ); } +inline uint32_t ThreadInterlockedExchangeSubtract( uint32_t volatile *p, uint32_t value ) { return ThreadInterlockedExchangeAdd( (int32_t volatile *)p, value ); } +inline uint32_t ThreadInterlockedIncrement( uint32_t volatile *p ) { return ThreadInterlockedIncrement( (int32_t volatile *)p ); } +inline uint32_t ThreadInterlockedDecrement( uint32_t volatile *p ) { return ThreadInterlockedDecrement( (int32_t volatile *)p ); } +inline uint32_t ThreadInterlockedExchange( uint32_t volatile *p, uint32_t value ) { return ThreadInterlockedExchange( (int32_t volatile *)p, value ); } +inline uint32_t ThreadInterlockedExchangeAdd( uint32_t volatile *p, uint32_t value ) { return ThreadInterlockedExchangeAdd( (int32_t volatile *)p, value ); } +inline uint32_t ThreadInterlockedCompareExchange( uint32_t volatile *p, uint32_t value, uint32_t comperand ) { return ThreadInterlockedCompareExchange( (int32_t volatile *)p, value, comperand ); } +inline bool ThreadInterlockedAssignIf( uint32_t volatile *p, uint32_t value, uint32_t comperand ) { return ThreadInterlockedAssignIf( (int32_t volatile *)p, value, comperand ); } //----------------------------------------------------------------------------- // Access to VTune thread profiling @@ -379,7 +414,7 @@ template class CInterlockedIntT { public: - CInterlockedIntT() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T) == sizeof(long) ); } + CInterlockedIntT() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T) == sizeof(int32_t) ); } CInterlockedIntT( T value ) : m_value( value ) {} operator T() const { return m_value; } @@ -388,17 +423,17 @@ public: bool operator==( T rhs ) const { return ( m_value == rhs ); } bool operator!=( T rhs ) const { return ( m_value != rhs ); } - T operator++() { return (T)ThreadInterlockedIncrement( (long *)&m_value ); } + T operator++() { return (T)ThreadInterlockedIncrement( (int32_t *)&m_value ); } T operator++(int) { return operator++() - 1; } - T operator--() { return (T)ThreadInterlockedDecrement( (long *)&m_value ); } + T operator--() { return (T)ThreadInterlockedDecrement( (int32_t *)&m_value ); } T operator--(int) { return operator--() + 1; } - bool AssignIf( T conditionValue, T newValue ) { return ThreadInterlockedAssignIf( (long *)&m_value, (long)newValue, (long)conditionValue ); } + bool AssignIf( T conditionValue, T newValue ) { return ThreadInterlockedAssignIf( (int32_t *)&m_value, (int32_t)newValue, (int32_t)conditionValue ); } - T operator=( T newValue ) { ThreadInterlockedExchange((long *)&m_value, newValue); return m_value; } + T operator=( T newValue ) { ThreadInterlockedExchange((int32_t *)&m_value, newValue); return m_value; } - void operator+=( T add ) { ThreadInterlockedExchangeAdd( (long *)&m_value, (long)add ); } + void operator+=( T add ) { ThreadInterlockedExchangeAdd( (int32_t *)&m_value, (int32_t)add ); } void operator-=( T subtract ) { operator+=( -subtract ); } void operator*=( T multiplier ) { T original, result; @@ -433,7 +468,7 @@ template class CInterlockedPtr { public: - CInterlockedPtr() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T *) == sizeof(long) ); /* Will need to rework operator+= for 64 bit */ } + CInterlockedPtr() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T *) == sizeof(int32_t) ); /* Will need to rework operator+= for 64 bit */ } CInterlockedPtr( T *value ) : m_value( value ) {} operator T *() const { return m_value; } @@ -442,17 +477,17 @@ public: bool operator==( T *rhs ) const { return ( m_value == rhs ); } bool operator!=( T *rhs ) const { return ( m_value != rhs ); } - T *operator++() { return ((T *)ThreadInterlockedExchangeAdd( (long *)&m_value, sizeof(T) )) + 1; } - T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd( (long *)&m_value, sizeof(T) ); } + T *operator++() { return ((T *)ThreadInterlockedExchangeAdd( (int32_t *)&m_value, sizeof(T) )) + 1; } + T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd( (int32_t *)&m_value, sizeof(T) ); } - T *operator--() { return ((T *)ThreadInterlockedExchangeAdd( (long *)&m_value, -sizeof(T) )) - 1; } - T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd( (long *)&m_value, -sizeof(T) ); } + T *operator--() { return ((T *)ThreadInterlockedExchangeAdd( (int32_t *)&m_value, -sizeof(T) )) - 1; } + T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd( (int32_t *)&m_value, -sizeof(T) ); } bool AssignIf( T *conditionValue, T *newValue ) { return ThreadInterlockedAssignPointerToConstIf( (void const **) &m_value, (void const *) newValue, (void const *) conditionValue ); } T *operator=( T *newValue ) { ThreadInterlockedExchangePointerToConst( (void const **) &m_value, (void const *) newValue ); return newValue; } - void operator+=( int add ) { ThreadInterlockedExchangeAdd( (long *)&m_value, add * sizeof(T) ); } + void operator+=( int add ) { ThreadInterlockedExchangeAdd( (int32_t *)&m_value, add * sizeof(T) ); } void operator-=( int subtract ) { operator+=( -subtract ); } T *operator+( int rhs ) const { return m_value + rhs; } @@ -555,22 +590,21 @@ public: } private: - FORCEINLINE bool TryLockInline( const uint32 threadId ) volatile + FORCEINLINE bool TryLockInline( const ThreadId_t threadId ) volatile { - if ( threadId != m_ownerID && !ThreadInterlockedAssignIf( (volatile long *)&m_ownerID, (long)threadId, 0 ) ) + if ( threadId != m_ownerID && !ThreadInterlockedAssignIf( (volatile int32_t *)&m_ownerID, (int32_t)threadId, 0 ) ) return false; ++m_depth; return true; } - bool TryLock( const uint32 threadId ) volatile + bool TryLock( const ThreadId_t threadId ) volatile { return TryLockInline( threadId ); } - TT_CLASS void Lock( const uint32 threadId, unsigned nSpinSleepTime ) volatile; - + TT_CLASS void Lock( const ThreadId_t threadId, unsigned nSpinSleepTime ) volatile; public: bool TryLock() volatile { @@ -589,7 +623,7 @@ public: #endif void Lock( unsigned nSpinSleepTime = 0 ) volatile { - const uint32 threadId = ThreadGetCurrentId(); + const auto threadId = ThreadGetCurrentId(); if ( !TryLockInline( threadId ) ) { @@ -622,8 +656,13 @@ public: #endif --m_depth; - if ( !m_depth ) + if ( !m_depth ) { +#ifdef _WIN64 + _InterlockedExchange64( (int64 volatile*)&m_ownerID, 0 ); +#else ThreadInterlockedExchange( &m_ownerID, 0 ); +#endif + } } bool TryLock() const volatile { return (const_cast(this))->TryLock(); } @@ -633,11 +672,11 @@ public: // To match regular CThreadMutex: bool AssertOwnedByCurrentThread() { return true; } void SetTrace( bool ) {} + ThreadId_t GetOwnerId() const { return m_ownerID; } - uint32 GetOwnerId() const { return m_ownerID; } int GetDepth() const { return m_depth; } private: - volatile uint32 m_ownerID; + volatile ThreadId_t m_ownerID; int m_depth; }; @@ -745,7 +784,7 @@ private: MUTEX_TYPE &m_lock; // Disallow copying - CAutoLockT( const CAutoLockT & ); + CAutoLockT( const CAutoLockT & ); CAutoLockT &operator=( const CAutoLockT & ); }; @@ -845,13 +884,13 @@ private: class TT_CLASS CThreadSemaphore : public CThreadSyncObject { public: - CThreadSemaphore(long initialValue, long maxValue); + CThreadSemaphore(int32_t initialValue, int32_t maxValue); //----------------------------------------------------- // Increases the count of the semaphore object by a specified // amount. Wait() decreases the count by one on return. //----------------------------------------------------- - bool Release(long releaseCount = 1, long * pPreviousCount = NULL ); + bool Release(int32_t releaseCount = 1, int32_t * pPreviousCount = NULL ); private: CThreadSemaphore(const CThreadSemaphore &); @@ -983,7 +1022,13 @@ private: class TFRWL_ALIGN TT_CLASS CThreadSpinRWLock { public: - CThreadSpinRWLock() { COMPILE_TIME_ASSERT( sizeof( LockInfo_t ) == sizeof( int64 ) ); Assert( (int)this % 8 == 0 ); memset( this, 0, sizeof( *this ) ); } + CThreadSpinRWLock() + { + COMPILE_TIME_ASSERT( sizeof( LockInfo_t ) == sizeof( int64 ) ); + Assert( (int)this % 8 == 0 ); + m_lockInfo.m_writerId = 0; + m_lockInfo.m_nReaders = 0; + } bool TryLockForWrite(); bool TryLockForRead(); @@ -1003,13 +1048,13 @@ public: private: struct LockInfo_t { - uint32 m_writerId; + ThreadId_t m_writerId; int m_nReaders; }; bool AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand ); - bool TryLockForWrite( const uint32 threadId ); - void SpinLockForWrite( const uint32 threadId ); + bool TryLockForWrite( const ThreadId_t threadId ); + void SpinLockForWrite( const ThreadId_t threadId ); volatile LockInfo_t m_lockInfo; CInterlockedInt m_nWriters; @@ -1051,7 +1096,7 @@ public: #ifdef _WIN32 // Access the thread handle directly HANDLE GetThreadHandle(); - uint GetThreadId(); + ThreadId_t GetThreadId(); #endif //----------------------------------------------------- @@ -1119,7 +1164,11 @@ protected: #endif // "Virtual static" facility +#ifdef PLATFORM_WINDOWS typedef unsigned (__stdcall *ThreadProc_t)( void * ); +#else + typedef unsigned (*ThreadProc_t)( void * ); +#endif virtual ThreadProc_t GetThreadProc(); CThreadMutex m_Lock; @@ -1141,7 +1190,11 @@ private: bool * pfInitSuccess; }; +#ifdef PLATFORM_WINDOWS static unsigned __stdcall ThreadProc( void * pv ); +#else + static void* ThreadProc( void * pv ); +#endif // make copy constructor and assignment operator inaccessible CThread( const CThread & ); @@ -1343,7 +1396,7 @@ extern "C" inline void CThreadMutex::Lock() { #ifdef THREAD_MUTEX_TRACING_ENABLED - uint thisThreadID = ThreadGetCurrentId(); + ThreadId_t thisThreadID = ThreadGetCurrentId(); if ( m_bTrace && m_currentOwnerID && ( m_currentOwnerID != thisThreadID ) ) Msg( "Thread %u about to wait for lock %x owned by %u\n", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID ); #endif @@ -1501,7 +1554,7 @@ inline bool CThreadSpinRWLock::AssignIf( const LockInfo_t &newValue, const LockI return ThreadInterlockedAssignIf64( (int64 *)&m_lockInfo, *((int64 *)&newValue), *((int64 *)&comperand) ); } -inline bool CThreadSpinRWLock::TryLockForWrite( const uint32 threadId ) +inline bool CThreadSpinRWLock::TryLockForWrite( const ThreadId_t threadId ) { // In order to grab a write lock, there can be no readers and no owners of the write lock if ( m_lockInfo.m_nReaders > 0 || ( m_lockInfo.m_writerId && m_lockInfo.m_writerId != threadId ) ) @@ -1509,8 +1562,8 @@ inline bool CThreadSpinRWLock::TryLockForWrite( const uint32 threadId ) return false; } - static const LockInfo_t oldValue = { 0, 0 }; - LockInfo_t newValue = { threadId, 0 }; + static const LockInfo_t oldValue = {0, 0}; + LockInfo_t newValue = {threadId, 0}; const bool bSuccess = AssignIf( newValue, oldValue ); #if defined(_X360) if ( bSuccess ) @@ -1559,7 +1612,7 @@ inline bool CThreadSpinRWLock::TryLockForRead() inline void CThreadSpinRWLock::LockForWrite() { - const uint32 threadId = ThreadGetCurrentId(); + const ThreadId_t threadId = ThreadGetCurrentId(); m_nWriters++; diff --git a/public/tier0/tslist.h b/public/tier0/tslist.h index c0df0b25..ad032a58 100644 --- a/public/tier0/tslist.h +++ b/public/tier0/tslist.h @@ -172,7 +172,7 @@ public: TSLNodeBase_t *Detach() { #ifdef USE_NATIVE_SLIST - TSLNodeBase_t *pBase = (TSLNodeBase_t *)InterlockedFlushSList( &m_Head ); + TSLNodeBase_t *pBase = (TSLNodeBase_t *)InterlockedFlushSList( (PSLIST_HEADER)&m_Head ); #ifdef _X360 __lwsync(); // read-acquire barrier #endif @@ -201,7 +201,7 @@ public: int Count() const { #ifdef USE_NATIVE_SLIST - return QueryDepthSList( &m_Head ); + return QueryDepthSList( (PSLIST_HEADER)&m_Head ); #else return m_Head.value.Depth; #endif diff --git a/public/tier0/validator.h b/public/tier0/validator.h index d2cc2dba..e95fee54 100644 --- a/public/tier0/validator.h +++ b/public/tier0/validator.h @@ -52,6 +52,8 @@ public: void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures + BOOL IsClaimed(void const *) const; + private: CValObject *m_pValObjectFirst; // Linked list of all ValObjects diff --git a/public/tier0/vcrmode.h b/public/tier0/vcrmode.h index dfed7d86..dd462e47 100644 --- a/public/tier0/vcrmode.h +++ b/public/tier0/vcrmode.h @@ -139,18 +139,18 @@ typedef struct VCR_s tchar* (*Hook_GetCommandLine)(); // Registry hooks. - long (*Hook_RegOpenKeyEx)( void *hKey, const tchar *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void *pHKey ); - long (*Hook_RegSetValueEx)(void *hKey, tchar const *lpValueName, unsigned long Reserved, unsigned long dwType, uint8 const *lpData, unsigned long cbData); - long (*Hook_RegQueryValueEx)(void *hKey, tchar const *lpValueName, unsigned long *lpReserved, unsigned long *lpType, uint8 *lpData, unsigned long *lpcbData); - long (*Hook_RegCreateKeyEx)(void *hKey, tchar const *lpSubKey, unsigned long Reserved, tchar *lpClass, unsigned long dwOptions, unsigned long samDesired, void *lpSecurityAttributes, void *phkResult, unsigned long *lpdwDisposition); + int32_t (*Hook_RegOpenKeyEx)( void *hKey, const tchar *lpSubKey, uint32_t ulOptions, uint32_t samDesired, void *pHKey ); + int32_t (*Hook_RegSetValueEx)(void *hKey, tchar const *lpValueName, uint32_t Reserved, uint32_t dwType, uint8 const *lpData, uint32_t cbData); + int32_t (*Hook_RegQueryValueEx)(void *hKey, tchar const *lpValueName, uint32_t *lpReserved, uint32_t *lpType, uint8 *lpData, uint32_t *lpcbData); + int32_t (*Hook_RegCreateKeyEx)(void *hKey, tchar const *lpSubKey, uint32_t Reserved, tchar *lpClass, uint32_t dwOptions, uint32_t samDesired, void *lpSecurityAttributes, void *phkResult, uint32_t *lpdwDisposition); void (*Hook_RegCloseKey)(void *hKey); // hInput is a HANDLE. - int (*Hook_GetNumberOfConsoleInputEvents)( void *hInput, unsigned long *pNumEvents ); + int (*Hook_GetNumberOfConsoleInputEvents)( void *hInput, uint32_t *pNumEvents ); // hInput is a HANDLE. // pRecs is an INPUT_RECORD pointer. - int (*Hook_ReadConsoleInput)( void *hInput, void *pRecs, int nMaxRecs, unsigned long *pNumRead ); + int (*Hook_ReadConsoleInput)( void *hInput, void *pRecs, int nMaxRecs, uint32_t *pNumRead ); // This calls time() then gives you localtime()'s result. @@ -186,19 +186,19 @@ typedef struct VCR_s // This mirrors the Windows API CreateThread function and returns a HANDLE the same way. void* (*Hook_CreateThread)( void *lpThreadAttributes, - unsigned long dwStackSize, + uint32_t dwStackSize, void *lpStartAddress, void *lpParameter, - unsigned long dwCreationFlags, - unsigned long *lpThreadID ); + uint32_t dwCreationFlags, + uint32_t *lpThreadID ); - unsigned long (*Hook_WaitForSingleObject)( + uint32_t (*Hook_WaitForSingleObject)( void *handle, - unsigned long dwMilliseconds ); + uint32_t dwMilliseconds ); void (*Hook_EnterCriticalSection)( void *pCS ); - void (*Hook_Time)( long *pTime ); + void (*Hook_Time)( int32_t *pTime ); // String value. Playback just verifies that the incoming string is the same as it was when recording. void (*GenericString)( const char *pEventName, const char *pString ); @@ -206,7 +206,7 @@ typedef struct VCR_s // Works like GenericValue, except upon playback it will verify that pData's contents are the same as it was during recording. void (*GenericValueVerify)( const tchar *pEventName, const void *pData, int maxLen ); - unsigned long (*Hook_WaitForMultipleObjects)( uint32 nHandles, const void **pHandles, int bWaitAll, uint32 timeout ); + uint32_t (*Hook_WaitForMultipleObjects)( uint32 nHandles, const void **pHandles, int bWaitAll, uint32 timeout ); } VCR_t; diff --git a/public/tier0/vprof.h b/public/tier0/vprof.h index 9fed016b..7a547459 100644 --- a/public/tier0/vprof.h +++ b/public/tier0/vprof.h @@ -261,7 +261,7 @@ public: int GetL2CacheMisses(); // Not used in the common case... - void SetCurFrameTime( unsigned long milliseconds ); + void SetCurFrameTime( uint32_t milliseconds ); void SetClientData( int iClientData ) { m_iClientData = iClientData; } int GetClientData() const { return m_iClientData; } @@ -269,8 +269,10 @@ public: #ifdef DBGFLAG_VALIDATE void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures #endif // DBGFLAG_VALIDATE - - +protected: +#ifdef _WIN32 + void DumpSingleNode(CVProfNode *, CVProfNode *, int, bool); +#endif // Used by vprof record/playback. private: @@ -386,6 +388,11 @@ enum CounterGroup_t COUNTER_GROUP_TEXTURE_PER_FRAME // Per-frame texture usage counters. }; +class DBG_CLASS CVProfManager +{ + +}; + class DBG_CLASS CVProfile { public: @@ -451,6 +458,8 @@ public: #endif + void RegisterNode(CVProfNode *pNode); + void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted ); void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ); void ExitScope(); diff --git a/public/tier1/UtlStringMap.h b/public/tier1/UtlStringMap.h index cfa9d8cc..f2ad0002 100644 --- a/public/tier1/UtlStringMap.h +++ b/public/tier1/UtlStringMap.h @@ -47,7 +47,7 @@ public: bool Defined( const char *pString ) const { - return m_SymbolTable.Find( pString ) != UTL_INVAL_SYMBOL; + return m_SymbolTable.Find( pString ).IsValid(); } UtlSymId_t Find( const char *pString ) const diff --git a/public/tier1/bitbuf.h b/public/tier1/bitbuf.h index af3de6ae..4ddf09e3 100644 --- a/public/tier1/bitbuf.h +++ b/public/tier1/bitbuf.h @@ -156,7 +156,7 @@ public: void WriteByte(int val); void WriteShort(int val); void WriteWord(int val); - void WriteLong(long val); + void WriteLong(int32_t val); void WriteLongLong(int64 val); void WriteFloat(float val); bool WriteBytes( const void *pBuf, int nBytes ); @@ -297,7 +297,7 @@ inline void old_bf_write::WriteUBitLong( unsigned int curData, int numbits, bool // Make sure it doesn't overflow. if ( bCheckRange && numbits < 32 ) { - if ( curData >= (unsigned long)(1 << numbits) ) + if ( curData >= (uint32_t)(1 << numbits) ) { CallErrorHandler( BITBUFERROR_VALUE_OUT_OF_RANGE, GetDebugName() ); } @@ -305,7 +305,7 @@ inline void old_bf_write::WriteUBitLong( unsigned int curData, int numbits, bool Assert( numbits >= 0 && numbits <= 32 ); #endif - extern unsigned long g_BitWriteMasks[32][33]; + extern uint32_t g_BitWriteMasks[32][33]; // Bounds checking.. if ((m_iCurBit+numbits) > m_nDataBits) @@ -321,17 +321,17 @@ inline void old_bf_write::WriteUBitLong( unsigned int curData, int numbits, bool // Mask in a dword. unsigned int iDWord = iCurBit >> 5; - Assert( (iDWord*4 + sizeof(long)) <= (unsigned int)m_nDataBytes ); + Assert( (iDWord*4 + sizeof(int32_t)) <= (unsigned int)m_nDataBytes ); - unsigned long iCurBitMasked = iCurBit & 31; + uint32_t iCurBitMasked = iCurBit & 31; - unsigned long dword = LoadLittleDWord( (unsigned long*)m_pData, iDWord ); + uint32_t dword = LoadLittleDWord( (uint32_t*)m_pData, iDWord ); dword &= g_BitWriteMasks[iCurBitMasked][nBitsLeft]; dword |= curData << iCurBitMasked; // write to stream (lsb to msb ) properly - StoreLittleDWord( (unsigned long*)m_pData, iDWord, dword ); + StoreLittleDWord( (uint32_t*)m_pData, iDWord, dword ); // Did it span a dword? int nBitsWritten = 32 - iCurBitMasked; @@ -341,13 +341,13 @@ inline void old_bf_write::WriteUBitLong( unsigned int curData, int numbits, bool curData >>= nBitsWritten; // read from stream (lsb to msb) properly - dword = LoadLittleDWord( (unsigned long*)m_pData, iDWord+1 ); + dword = LoadLittleDWord( (uint32_t*)m_pData, iDWord+1 ); dword &= g_BitWriteMasks[0][nBitsLeft]; dword |= curData; // write to stream (lsb to msb) properly - StoreLittleDWord( (unsigned long*)m_pData, iDWord+1, dword ); + StoreLittleDWord( (uint32_t*)m_pData, iDWord+1, dword ); } m_iCurBit += numbits; @@ -459,7 +459,7 @@ public: int ReadByte(); int ReadShort(); int ReadWord(); - long ReadLong(); + int32_t ReadLong(); int64 ReadLongLong(); float ReadFloat(); bool ReadBytes(void *pOut, int nBytes); @@ -604,9 +604,9 @@ inline int old_bf_read::ReadOneBit() inline float old_bf_read::ReadBitFloat() { - long val; + int32_t val; - Assert(sizeof(float) == sizeof(long)); + Assert(sizeof(float) == sizeof(int32_t)); Assert(sizeof(float) == 4); if(CheckForOverflow(32)) @@ -627,7 +627,7 @@ inline float old_bf_read::ReadBitFloat() inline unsigned int old_bf_read::ReadUBitLong( int numbits ) { - extern unsigned long g_ExtraMasks[32]; + extern uint32_t g_ExtraMasks[32]; if ( (m_iCurBit+numbits) > m_nDataBits ) { @@ -640,7 +640,7 @@ inline unsigned int old_bf_read::ReadUBitLong( int numbits ) // Read the current dword. int idword1 = m_iCurBit >> 5; - unsigned int dword1 = LoadLittleDWord( (unsigned long*)m_pData, idword1 ); + unsigned int dword1 = LoadLittleDWord( (uint32_t*)m_pData, idword1 ); dword1 >>= (m_iCurBit & 31); // Get the bits we're interested in. @@ -656,7 +656,7 @@ inline unsigned int old_bf_read::ReadUBitLong( int numbits ) else { int nExtraBits = m_iCurBit & 31; - unsigned int dword2 = LoadLittleDWord( (unsigned long*)m_pData, idword1+1 ); + unsigned int dword2 = LoadLittleDWord( (uint32_t*)m_pData, idword1+1 ); dword2 &= g_ExtraMasks[nExtraBits]; @@ -809,7 +809,7 @@ public: } - FORCEINLINE void WriteLong(long val) + FORCEINLINE void WriteLong(int32_t val) { WriteSBitLong( val, 32 ); } @@ -910,7 +910,7 @@ FORCEINLINE void CBitWrite::WriteUBitLong( unsigned int nData, int nNumBits, boo // Make sure it doesn't overflow. if ( bCheckRange && nNumBits < 32 ) { - Assert( nData <= (unsigned long)(1 << nNumBits ) ); + Assert( nData <= (uint32_t)(1 << nNumBits ) ); } Assert( nNumBits >= 0 && nNumBits <= 32 ); #endif @@ -1195,12 +1195,12 @@ FORCEINLINE int CBitRead::ReadSBitLong( int numbits ) FORCEINLINE int CBitRead::ReadLong( void ) { - return ( int ) ReadUBitLong( sizeof(long) << 3 ); + return ( int ) ReadUBitLong( sizeof(int32_t) << 3 ); } FORCEINLINE float CBitRead::ReadFloat( void ) { - uint32 nUval = ReadUBitLong( sizeof(long) << 3 ); + uint32 nUval = ReadUBitLong( sizeof(int32_t) << 3 ); return * ( ( float * ) &nUval ); } diff --git a/public/tier1/checksum_crc.h b/public/tier1/checksum_crc.h index 3f6e9ec1..f77f1858 100644 --- a/public/tier1/checksum_crc.h +++ b/public/tier1/checksum_crc.h @@ -10,7 +10,9 @@ #pragma once #endif -typedef unsigned long CRC32_t; +#include + +typedef uint32_t CRC32_t; void CRC32_Init( CRC32_t *pulCRC ); void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *p, int len ); diff --git a/public/tier1/convar.h b/public/tier1/convar.h index a763c465..14a6b546 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -66,7 +66,7 @@ void ConVar_PublishToVXConsole(); //----------------------------------------------------------------------------- // Called when a ConCommand needs to execute //----------------------------------------------------------------------------- -typedef void ( *FnCommandCallbackV1_t )( void ); +typedef void ( *FnCommandCallbackVoid_t )( void ); typedef void ( *FnCommandCallback_t )( const CCommand &command ); #define COMMAND_COMPLETION_MAXITEMS 64 @@ -142,7 +142,7 @@ public: virtual CVarDLLIdentifier_t GetDLLIdentifier() const; protected: - virtual void Create( const char *pName, const char *pHelpString = 0, + virtual void CreateBase( const char *pName, const char *pHelpString = 0, int flags = 0 ); // Used internally by OneTimeInit to initialize/shutdown @@ -270,7 +270,7 @@ friend class CCvar; public: typedef ConCommandBase BaseClass; - ConCommand( const char *pName, FnCommandCallbackV1_t callback, + ConCommand( const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); @@ -300,7 +300,7 @@ private: // Call this function when executing the command union { - FnCommandCallbackV1_t m_fnCommandCallbackV1; + FnCommandCallbackVoid_t m_fnCommandCallbackV1; FnCommandCallback_t m_fnCommandCallback; ICommandCallback *m_pCommandCallback; }; @@ -373,12 +373,13 @@ public: bool GetMin( float& minVal ) const; bool GetMax( float& maxVal ) const; const char *GetDefault( void ) const; + void SetDefault( const char *pszDefault ); private: // Called by CCvar when the value of a var is changing. virtual void InternalSetValue(const char *value); // For CVARs marked FCVAR_NEVER_AS_STRING - virtual void InternalSetFloatValue( float fNewValue ); + virtual void InternalSetFloatValue( float fNewValue, bool bForce = false ); virtual void InternalSetIntValue( int nValue ); virtual bool ClampValue( float& value ); @@ -390,7 +391,7 @@ private: // Used internally by OneTimeInit to initialize. virtual void Init(); - + int GetFlags() { return m_pParent->m_nFlags; } private: // This either points to "this" or it points to the original declaration of a ConVar. @@ -415,6 +416,13 @@ private: float m_fMinVal; bool m_bHasMax; float m_fMaxVal; + + bool m_bHasCompMin; + float m_fCompMinVal; + bool m_bHasCompMax; + float m_fCompMaxVal; + bool m_bCompetitiveRestrictions; + // Call this function when ConVar changes FnChangeCallback_t m_fnChangeCallback; diff --git a/public/tier1/datamanager.h b/public/tier1/datamanager.h index 02181541..06990d32 100644 --- a/public/tier1/datamanager.h +++ b/public/tier1/datamanager.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -14,9 +14,9 @@ #include "utlmultilist.h" #include "utlvector.h" -FORWARD_DECLARE_HANDLE( memhandle_t ); +DECLARE_HANDLE_32BIT( memhandle_t ); -#define INVALID_MEMHANDLE ((memhandle_t)0xffffffff) +#define INVALID_MEMHANDLE (memhandle_t::MakeHandle(~0)) class CDataManagerBase { @@ -251,7 +251,7 @@ private: inline unsigned short CDataManagerBase::FromHandle( memhandle_t handle ) { - unsigned int fullWord = (unsigned int)handle; + unsigned int fullWord = handle.GetHandleValue(); unsigned short serial = fullWord>>16; unsigned short index = fullWord & 0xFFFF; index--; diff --git a/public/tier1/iconvar.h b/public/tier1/iconvar.h index 53a7e126..7a276bd0 100644 --- a/public/tier1/iconvar.h +++ b/public/tier1/iconvar.h @@ -62,11 +62,15 @@ class CCommand; #define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time #define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file #define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles +#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload +#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload #define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server - +#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread #define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox +#define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars + #define FCVAR_SERVER_CAN_EXECUTE (1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd. #define FCVAR_SERVER_CANNOT_QUERY (1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue). #define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command. @@ -78,11 +82,11 @@ class CCommand; // #define FCVAR_AVAILABLE (1<<20) // #define FCVAR_AVAILABLE (1<<21) // #define FCVAR_AVAILABLE (1<<23) -// #define FCVAR_AVAILABLE (1<<25) // #define FCVAR_AVAILABLE (1<<26) // #define FCVAR_AVAILABLE (1<<27) // #define FCVAR_AVAILABLE (1<<31) +#define FCVAR_MATERIAL_THREAD_MASK ( FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD ) //----------------------------------------------------------------------------- // Called when a ConVar changes value diff --git a/public/tier1/interface.h b/public/tier1/interface.h index 00beb450..a1147769 100644 --- a/public/tier1/interface.h +++ b/public/tier1/interface.h @@ -36,21 +36,16 @@ #pragma once #endif -#if defined _LINUX || defined __APPLE__ +#ifdef _LINUX #include // dlopen,dlclose, et al #include -#ifndef HMODULE -#define HMODULE void * -#endif - -#ifndef GetProcAddress #define GetProcAddress dlsym -#endif -#ifndef _snprintf -#define _snprintf snprintf +#ifdef _snprintf +#undef _snprintf #endif +#define _snprintf snprintf #endif // TODO: move interface.cpp into tier0 library. @@ -125,18 +120,21 @@ public: // Use this to expose a singleton interface with a global variable you've created. #if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) -#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ - static void* __Create##className##interfaceName##_interface() {return static_cast( &globalVarName );} \ +#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \ + static void* __Create##className##interfaceName##_interface() {return static_cast( &globalVarName );} \ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); #else -#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ +#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \ namespace _SUBSYSTEM \ { \ - static void* __Create##className##interfaceName##_interface() {return static_cast( &globalVarName );} \ + static void* __Create##className##interfaceName##_interface() {return static_cast( &globalVarName );} \ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \ } #endif +#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ + EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, , interfaceName, versionName, globalVarName) + // Use this to expose a singleton interface. This creates the global variable for you automatically. #if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) #define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ @@ -179,12 +177,18 @@ extern CreateInterfaceFn Sys_GetFactory( CSysModule *pModule ); extern CreateInterfaceFn Sys_GetFactory( const char *pModuleName ); extern CreateInterfaceFn Sys_GetFactoryThis( void ); +enum Sys_Flags +{ + SYS_NOFLAGS = 0x00, + SYS_NOLOAD = 0x01 // no loading, no ref-counting, only returns handle if lib is loaded. +}; + //----------------------------------------------------------------------------- // Load & Unload should be called in exactly one place for each module // The factory for that module should be passed on to dependent components for // proper versioning. //----------------------------------------------------------------------------- -extern CSysModule *Sys_LoadModule( const char *pModuleName ); +extern CSysModule *Sys_LoadModule( const char *pModuleName, Sys_Flags flags = SYS_NOFLAGS ); extern void Sys_UnloadModule( CSysModule *pModule ); // This is a helper function to load a module, get its factory, and get a specific interface. diff --git a/public/tier1/mempool.h b/public/tier1/mempool.h index 3b927812..8dbf3eae 100644 --- a/public/tier1/mempool.h +++ b/public/tier1/mempool.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -440,7 +440,7 @@ inline void CAlignedMemPool inline int __cdecl CAlignedMemPool::CompareChunk( void * const *ppLeft, void * const *ppRight ) { - return ((unsigned)*ppLeft) - ((unsigned)*ppRight); + return ((uintp)*ppLeft) - ((uintp)*ppRight); } template diff --git a/public/tier1/netadr.h b/public/tier1/netadr.h index e03e7be9..5f96c9b1 100644 --- a/public/tier1/netadr.h +++ b/public/tier1/netadr.h @@ -55,8 +55,8 @@ public: bool IsValid() const; // ip & port != 0 void SetFromSocket( int hSocket ); // These function names are decorated because the Xbox360 defines macros for ntohl and htonl - unsigned long addr_ntohl() const; - unsigned long addr_htonl() const; + uint32_t addr_ntohl() const; + uint32_t addr_htonl() const; bool operator==(const netadr_s &netadr) const {return ( CompareAdr( netadr ) );} bool operator<(const netadr_s &netadr) const; diff --git a/public/tier1/refcount.h b/public/tier1/refcount.h index 16318b31..a55263c9 100644 --- a/public/tier1/refcount.h +++ b/public/tier1/refcount.h @@ -159,8 +159,8 @@ public: class CRefMT { public: - static int Increment( int *p) { return ThreadInterlockedIncrement( (long *)p ); } - static int Decrement( int *p) { return ThreadInterlockedDecrement( (long *)p ); } + static int Increment( int *p) { return ThreadInterlockedIncrement( (int32_t *)p ); } + static int Decrement( int *p) { return ThreadInterlockedDecrement( (int32_t *)p ); } }; class CRefST diff --git a/public/tier1/smartptr.h b/public/tier1/smartptr.h index fa17a792..a0065e5a 100644 --- a/public/tier1/smartptr.h +++ b/public/tier1/smartptr.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -107,14 +107,14 @@ template < typename T > class CArrayAutoPtr : public CPlainAutoPtr < T > // Warning: no polymorphic destructor (delete on base class will be a mistake) { public: - explicit CArrayAutoPtr( T *p = NULL ) { Attach( p ); } - ~CArrayAutoPtr( void ) { Delete(); } + explicit CArrayAutoPtr( T *p = NULL ) { this->Attach( p ); } + ~CArrayAutoPtr( void ) { this->Delete(); } public: - void Delete( void ) { delete [] Detach(); } + void Delete( void ) { delete [] CPlainAutoPtr < T >::Detach(); } public: - T & operator [] ( int k ) const { return Get()[ k ]; } + T & operator [] ( int k ) const { return CPlainAutoPtr < T >::Get()[ k ]; } }; diff --git a/public/tier1/strtools.h b/public/tier1/strtools.h index b699c85e..c6b3ec07 100644 --- a/public/tier1/strtools.h +++ b/public/tier1/strtools.h @@ -17,6 +17,7 @@ #include #include #include +#include #endif #include @@ -137,13 +138,24 @@ void V_normalizeFloatString( char* pFloat ); // pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen. // // This means the last parameter can usually be a sizeof() of a string. -void V_strncpy( char *pDest, const char *pSrc, int maxLen ); +void V_strncpy( OUT_Z_CAP(maxLenInChars) char *pDest, const char *pSrc, int maxLenInChars ); + +// Ultimate safe strcpy function, for arrays only -- buffer size is inferred by the compiler +template void V_strcpy_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], const char *pSrc ) +{ + V_strncpy( pDest, pSrc, (int)maxLenInChars ); +} + int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ); void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ); int V_snwprintf( wchar_t *pDest, int destLen, const wchar_t *pFormat, ... ); #define COPY_ALL_CHARACTERS -1 -char *V_strncat(char *, const char *, size_t destBufferSize, int max_chars_to_copy=COPY_ALL_CHARACTERS ); +char *V_strncat( INOUT_Z_CAP(cchDest) char *pDest, const char *pSrc, size_t cchDest, int max_chars_to_copy=COPY_ALL_CHARACTERS ); +template char *V_strcat_safe( INOUT_Z_ARRAY char (&pDest)[cchDest], const char *pSrc, int nMaxCharsToCopy=COPY_ALL_CHARACTERS ) +{ + return V_strncat( pDest, pSrc, (int)cchDest, nMaxCharsToCopy ); +} char *V_strnlwr(char *, size_t); @@ -169,16 +181,20 @@ typedef char * va_list; #endif // _VA_LIST_DEFINED -#elif defined(_LINUX) || defined(__APPLE__) +#elif POSIX #include #endif #ifdef _WIN32 #define CORRECT_PATH_SEPARATOR '\\' +#define CORRECT_PATH_SEPARATOR_S "\\" #define INCORRECT_PATH_SEPARATOR '/' -#elif defined(_LINUX) || defined(__APPLE__) +#define INCORRECT_PATH_SEPARATOR_S "/" +#elif POSIX #define CORRECT_PATH_SEPARATOR '/' +#define CORRECT_PATH_SEPARATOR_S "/" #define INCORRECT_PATH_SEPARATOR '\\' +#define INCORRECT_PATH_SEPARATOR_S "\\" #endif int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params ); @@ -193,6 +209,16 @@ char *V_pretifynum( int64 value ); int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ); int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes ); + +// strips leading and trailing whitespace; returns true if any characters were removed. UTF-8 and UTF-16 versions. +bool Q_StripPrecedingAndTrailingWhitespace( char *pch ); +bool Q_StripPrecedingAndTrailingWhitespaceW( wchar_t *pwch ); + +// strips leading and trailing whitespace, also taking "aggressive" characters +// like punctuation spaces, non-breaking spaces, composing characters, and so on +bool Q_AggressiveStripPrecedingAndTrailingWhitespace( char *pch ); +bool Q_AggressiveStripPrecedingAndTrailingWhitespaceW( wchar_t *pwch ); +bool Q_RemoveAllEvilCharacters( char *pch ); // Functions for converting hexidecimal character strings back into binary data etc. // // e.g., diff --git a/public/tier1/tier1.h b/public/tier1/tier1.h index 176e5879..8c70fc78 100644 --- a/public/tier1/tier1.h +++ b/public/tier1/tier1.h @@ -32,7 +32,7 @@ class IProcessUtils; // These are marked DLL_EXPORT for Linux. DLL_EXPORT ICvar *cvar; -DLL_EXPORT ICvar *g_pCVar; +extern ICvar *g_pCVar; extern IProcessUtils *g_pProcessUtils; diff --git a/public/tier1/utlbuffer.h b/public/tier1/utlbuffer.h index f4e7eef9..3246e2ea 100644 --- a/public/tier1/utlbuffer.h +++ b/public/tier1/utlbuffer.h @@ -1,4 +1,4 @@ -//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// +//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======// // // Purpose: // @@ -181,6 +181,7 @@ public: unsigned int GetUnsignedInt( ); float GetFloat( ); double GetDouble( ); + void* GetPtr( ); void GetString( char* pString, int nMaxChars = 0 ); void Get( void* pMem, int size ); void GetLine( char* pLine, int nMaxChars = 0 ); @@ -254,6 +255,7 @@ public: void PutUnsignedInt( unsigned int u ); void PutFloat( float f ); void PutDouble( double d ); + void PutPtr( void * ); void PutString( const char* pString ); void Put( const void* pMem, int size ); @@ -627,7 +629,7 @@ inline void CUtlBuffer::GetTypeBin< float >( float &dest ) { if ( CheckGet( sizeof( float ) ) ) { - unsigned int pData = (unsigned int)PeekGet(); + uintptr_t pData = (uintptr_t)PeekGet(); if ( IsX360() && ( pData & 0x03 ) ) { // handle unaligned read @@ -737,6 +739,18 @@ inline double CUtlBuffer::GetDouble( ) return d; } +inline void *CUtlBuffer::GetPtr( ) +{ + void *p; + // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal +#ifndef X64BITS + p = ( void* )GetUnsignedInt(); +#else + p = ( void* )GetInt64(); +#endif + return p; +} + //----------------------------------------------------------------------------- // Where am I writing? @@ -949,6 +963,18 @@ inline void CUtlBuffer::PutDouble( double d ) PutType( d, "%f" ); } +inline void CUtlBuffer::PutPtr( void *p ) +{ + // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal + if (!IsText()) + { + PutTypeBin( p ); + } + else + { + Printf( "0x%p", p ); + } +} //----------------------------------------------------------------------------- // Am I a text buffer? diff --git a/public/tier1/utlfixedmemory.h b/public/tier1/utlfixedmemory.h index bb84844d..870f65c8 100644 --- a/public/tier1/utlfixedmemory.h +++ b/public/tier1/utlfixedmemory.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -88,9 +88,9 @@ public: if ( !IsValidIterator( it ) ) return InvalidIndex(); - return ( int )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex ); + return ( intp )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex ); } - bool IsIdxAfter( int i, const Iterator_t &it ) const + bool IsIdxAfter( intp i, const Iterator_t &it ) const { Assert( IsValidIterator( it ) ); if ( !IsValidIterator( it ) ) @@ -110,8 +110,8 @@ public: Iterator_t InvalidIterator() const { return Iterator_t( NULL, -1 ); } // element access - T& operator[]( int i ); - const T& operator[]( int i ) const; + T& operator[]( intp i ); + const T& operator[]( intp i ) const; T& Element( int i ); const T& Element( int i ) const; @@ -136,7 +136,7 @@ protected: // Fast swap - WARNING: Swap invalidates all ptr-based indices!!! void Swap( CUtlFixedMemory< T > &mem ); - bool IsInBlock( int i, BlockHeader_t *pBlockHeader ) const + bool IsInBlock( intp i, BlockHeader_t *pBlockHeader ) const { T *p = ( T* )i; const T *p0 = HeaderToBlock( pBlockHeader ); @@ -209,14 +209,14 @@ void CUtlFixedMemory::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ // element access //----------------------------------------------------------------------------- template< class T > -inline T& CUtlFixedMemory::operator[]( int i ) +inline T& CUtlFixedMemory::operator[]( intp i ) { Assert( IsIdxValid(i) ); return *( T* )i; } template< class T > -inline const T& CUtlFixedMemory::operator[]( int i ) const +inline const T& CUtlFixedMemory::operator[]( intp i ) const { Assert( IsIdxValid(i) ); return *( T* )i; diff --git a/public/tier1/utlhash.h b/public/tier1/utlhash.h index b7cba7d4..c15e6c84 100644 --- a/public/tier1/utlhash.h +++ b/public/tier1/utlhash.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -895,7 +895,7 @@ template inline UtlHashFixedHandle for ( UtlPtrLinkedListIndex_t iElement = bucket.Head(); iElement != bucket.InvalidIndex(); iElement = bucket.Next( iElement ) ) { if ( bucket[iElement].m_uiKey == uiKey ) - return (UtlHashFixedHandle_t)iElement; + return (UtlHashFixedHandle_t)(intp)iElement; } return InvalidHandle(); diff --git a/public/tier1/utllinkedlist.h b/public/tier1/utllinkedlist.h index 56ac7273..0d51a462 100644 --- a/public/tier1/utllinkedlist.h +++ b/public/tier1/utllinkedlist.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Linked list container class // @@ -178,11 +178,11 @@ protected: // this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice template < class T > -class CUtlFixedLinkedList : public CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > > +class CUtlFixedLinkedList : public CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > > { public: CUtlFixedLinkedList( int growSize = 0, int initSize = 0 ) - : CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > >( growSize, initSize ) {} + : CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >( growSize, initSize ) {} bool IsValidIndex( int i ) const { diff --git a/public/tier1/utlmemory.h b/public/tier1/utlmemory.h index afb027dd..8acdb7a4 100644 --- a/public/tier1/utlmemory.h +++ b/public/tier1/utlmemory.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -17,6 +17,7 @@ #include "tier0/dbg.h" #include #include "tier0/platform.h" +#include "mathlib/mathlib.h" #include "tier0/memalloc.h" #include "tier0/memdbgon.h" @@ -79,7 +80,10 @@ public: // Can we use this index? bool IsIdxValid( I i ) const; - static I InvalidIndex() { return ( I )-1; } + + // Specify the invalid ('null') index that we'll only return on failure + static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT + static I InvalidIndex() { return INVALID_INDEX; } // Gets the base address (can change when adding elements!) T* Base(); @@ -89,6 +93,8 @@ public: void SetExternalBuffer( T* pMemory, int numElements ); void SetExternalBuffer( const T* pMemory, int numElements ); void AssumeMemory( T *pMemory, int nSize ); + T* Detach(); + void *DetachMemory(); // Fast swap void Swap( CUtlMemory< T, I > &mem ); @@ -132,7 +138,7 @@ protected: const int MAX_GROW = 128; if ( m_nGrowSize * sizeof(T) > MAX_GROW ) { - m_nGrowSize = MAX( 1, MAX_GROW / sizeof(T) ); + m_nGrowSize = V_max( 1, MAX_GROW / sizeof(T) ); } } #endif @@ -168,9 +174,9 @@ public: void Grow( int nCount = 1 ) { - if ( CUtlMemory::IsExternallyAllocated() ) + if ( this->IsExternallyAllocated() ) { - CUtlMemory::ConvertToGrowableMemory( m_nMallocGrowSize ); + this->ConvertToGrowableMemory( m_nMallocGrowSize ); } BaseClass::Grow( nCount ); } @@ -180,10 +186,10 @@ public: if ( CUtlMemory::m_nAllocationCount >= num ) return; - if ( CUtlMemory::IsExternallyAllocated() ) + if ( this->IsExternallyAllocated() ) { // Can't grow a buffer whose memory was externally allocated - CUtlMemory::ConvertToGrowableMemory( m_nMallocGrowSize ); + this->ConvertToGrowableMemory( m_nMallocGrowSize ); } BaseClass::EnsureCapacity( num ); @@ -207,8 +213,11 @@ public: CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); } // Can we use this index? - bool IsIdxValid( int i ) const { return (i >= 0) && (i < (int)SIZE); } - static int InvalidIndex() { return -1; } + bool IsIdxValid( int i ) const { return (i >= 0) && (i < SIZE); } + + // Specify the invalid ('null') index that we'll only return on failure + static const int INVALID_INDEX = -1; // For use with COMPILE_TIME_ASSERT + static int InvalidIndex() { return INVALID_INDEX; } // Gets the base address T* Base() { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); } @@ -231,7 +240,7 @@ public: void Grow( int num = 1 ) { Assert( 0 ); } // Makes sure we've got at least this much memory - void EnsureCapacity( int num ) { Assert( num <= (int)SIZE ); } + void EnsureCapacity( int num ) { Assert( num <= SIZE ); } // Memory deallocation void Purge() {} @@ -264,6 +273,134 @@ private: char m_Memory[ SIZE*sizeof(T) + nAlignment ]; }; +#ifdef _LINUX +#define REMEMBER_ALLOC_SIZE_FOR_VALGRIND 1 +#endif + +//----------------------------------------------------------------------------- +// The CUtlMemoryConservative class: +// A dynamic memory class that tries to minimize overhead (itself small, no custom grow factor) +//----------------------------------------------------------------------------- +template< typename T > +class CUtlMemoryConservative +{ + +public: + // constructor, destructor + CUtlMemoryConservative( int nGrowSize = 0, int nInitSize = 0 ) : m_pMemory( NULL ) + { +#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND + m_nCurAllocSize = 0; +#endif + + } + CUtlMemoryConservative( T* pMemory, int numElements ) { Assert( 0 ); } + ~CUtlMemoryConservative() { if ( m_pMemory ) free( m_pMemory ); } + + // Can we use this index? + bool IsIdxValid( int i ) const { return ( IsDebug() ) ? ( i >= 0 && i < NumAllocated() ) : ( i >= 0 ); } + static int InvalidIndex() { return -1; } + + // Gets the base address + T* Base() { return m_pMemory; } + const T* Base() const { return m_pMemory; } + + // element access + T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; } + const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } + T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; } + const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } + + // Attaches the buffer to external memory.... + void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); } + + // Size + FORCEINLINE void RememberAllocSize( size_t sz ) + { +#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND + m_nCurAllocSize = sz; +#endif + } + + size_t AllocSize( void ) const + { +#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND + return m_nCurAllocSize; +#else + return ( m_pMemory ) ? g_pMemAlloc->GetSize( m_pMemory ) : 0; +#endif + } + + int NumAllocated() const + { + return AllocSize() / sizeof( T ); + } + int Count() const + { + return NumAllocated(); + } + + FORCEINLINE void ReAlloc( size_t sz ) + { + m_pMemory = (T*)realloc( m_pMemory, sz ); + RememberAllocSize( sz ); + } + // Grows the memory, so that at least allocated + num elements are allocated + void Grow( int num = 1 ) + { + int nCurN = NumAllocated(); + ReAlloc( ( nCurN + num ) * sizeof( T ) ); + } + + // Makes sure we've got at least this much memory + void EnsureCapacity( int num ) + { + size_t nSize = sizeof( T ) * MAX( num, Count() ); + ReAlloc( nSize ); + } + + // Memory deallocation + void Purge() + { + free( m_pMemory ); + RememberAllocSize( 0 ); + m_pMemory = NULL; + } + + // Purge all but the given number of elements + void Purge( int numElements ) { ReAlloc( numElements * sizeof(T) ); } + + // is the memory externally allocated? + bool IsExternallyAllocated() const { return false; } + + // Set the size by which the memory grows + void SetGrowSize( int size ) {} + + class Iterator_t + { + public: + Iterator_t( int i, int _limit ) : index( i ), limit( _limit ) {} + int index; + int limit; + bool operator==( const Iterator_t it ) const { return index == it.index; } + bool operator!=( const Iterator_t it ) const { return index != it.index; } + }; + Iterator_t First() const { int limit = NumAllocated(); return Iterator_t( limit ? 0 : InvalidIndex(), limit ); } + Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( ( it.index + 1 < it.limit ) ? it.index + 1 : InvalidIndex(), it.limit ); } + int GetIndex( const Iterator_t &it ) const { return it.index; } + bool IsIdxAfter( int i, const Iterator_t &it ) const { return i > it.index; } + bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ) && ( it.index < it.limit ); } + Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex(), 0 ); } + +private: + T *m_pMemory; +#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND + size_t m_nCurAllocSize; +#endif + +}; + + //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- @@ -400,6 +537,24 @@ void CUtlMemory::AssumeMemory( T* pMemory, int numElements ) m_nAllocationCount = numElements; } +template< class T, class I > +void *CUtlMemory::DetachMemory() +{ + if ( IsExternallyAllocated() ) + return NULL; + + void *pMemory = m_pMemory; + m_pMemory = 0; + m_nAllocationCount = 0; + return pMemory; +} + +template< class T, class I > +inline T* CUtlMemory::Detach() +{ + return (T*)DetachMemory(); +} + //----------------------------------------------------------------------------- // element access @@ -504,8 +659,10 @@ inline int CUtlMemory::Count() const template< class T, class I > inline bool CUtlMemory::IsIdxValid( I i ) const { - int idx = (int)i; - return idx >= 0 && idx < m_nAllocationCount; + // GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0). + // We get the warning even if we cast inside the expression. It only goes away if we assign to another variable. + int32_t x = i; + return ( x >= 0 ) && ( x < m_nAllocationCount ); } //----------------------------------------------------------------------------- @@ -560,14 +717,14 @@ void CUtlMemory::Grow( int num ) UTLMEMORY_TRACK_FREE(); - m_nAllocationCount = UtlMemory_CalcNewAllocationCount( m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T) ); + int nNewAllocationCount = UtlMemory_CalcNewAllocationCount( m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T) ); // if m_nAllocationRequested wraps index type I, recalculate - if ( ( int )( I )m_nAllocationCount < nAllocationRequested ) + if ( ( int )( I )nNewAllocationCount < nAllocationRequested ) { - if ( ( int )( I )m_nAllocationCount == 0 && ( int )( I )( m_nAllocationCount - 1 ) >= nAllocationRequested ) + if ( ( int )( I )nNewAllocationCount == 0 && ( int )( I )( nNewAllocationCount - 1 ) >= nAllocationRequested ) { - --m_nAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1 + --nNewAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1 } else { @@ -577,13 +734,15 @@ void CUtlMemory::Grow( int num ) Assert( 0 ); return; } - while ( ( int )( I )m_nAllocationCount < nAllocationRequested ) + while ( ( int )( I )nNewAllocationCount < nAllocationRequested ) { - m_nAllocationCount = ( m_nAllocationCount + nAllocationRequested ) / 2; + nNewAllocationCount = ( nNewAllocationCount + nAllocationRequested ) / 2; } } } + m_nAllocationCount = nNewAllocationCount; + UTLMEMORY_TRACK_ALLOC(); if (m_pMemory) @@ -759,7 +918,7 @@ CUtlMemoryAligned::CUtlMemoryAligned( int nGrowSize, int nInitAll CUtlMemory::m_pMemory = 0; CUtlMemory::m_nAllocationCount = nInitAllocationCount; CUtlMemory::m_nGrowSize = nGrowSize; - CUtlMemory::ValidateGrowSize(); + this->ValidateGrowSize(); // Alignment must be a power of two COMPILE_TIME_ASSERT( (nAlignment & (nAlignment-1)) == 0 ); @@ -768,8 +927,8 @@ CUtlMemoryAligned::CUtlMemoryAligned( int nGrowSize, int nInitAll { UTLMEMORY_TRACK_ALLOC(); MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); - } + CUtlMemory::m_pMemory = (T*)_aligned_malloc( nInitAllocationCount * sizeof(T), nAlignment ); + } } template< class T, int nAlignment > @@ -837,7 +996,7 @@ void CUtlMemoryAligned::Grow( int num ) { Assert( num > 0 ); - if ( CUtlMemory::IsExternallyAllocated() ) + if ( this->IsExternallyAllocated() ) { // Can't grow a buffer whose memory was externally allocated Assert(0); @@ -857,13 +1016,13 @@ void CUtlMemoryAligned::Grow( int num ) if ( CUtlMemory::m_pMemory ) { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_realloc( CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); + CUtlMemory::m_pMemory = (T*)MemAlloc_ReallocAligned( CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); Assert( CUtlMemory::m_pMemory ); } else { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); + CUtlMemory::m_pMemory = (T*)MemAlloc_AllocAligned( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); Assert( CUtlMemory::m_pMemory ); } } @@ -878,7 +1037,7 @@ inline void CUtlMemoryAligned::EnsureCapacity( int num ) if ( CUtlMemory::m_nAllocationCount >= num ) return; - if ( CUtlMemory::IsExternallyAllocated() ) + if ( this->IsExternallyAllocated() ) { // Can't grow a buffer whose memory was externally allocated Assert(0); @@ -894,12 +1053,12 @@ inline void CUtlMemoryAligned::EnsureCapacity( int num ) if ( CUtlMemory::m_pMemory ) { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_realloc( CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); + CUtlMemory::m_pMemory = (T*)MemAlloc_ReallocAligned( CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); } else { MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); + CUtlMemory::m_pMemory = (T*)MemAlloc_AllocAligned( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); } } @@ -910,12 +1069,12 @@ inline void CUtlMemoryAligned::EnsureCapacity( int num ) template< class T, int nAlignment > void CUtlMemoryAligned::Purge() { - if ( !CUtlMemory::IsExternallyAllocated() ) + if ( !this->IsExternallyAllocated() ) { if ( CUtlMemory::m_pMemory ) { UTLMEMORY_TRACK_FREE(); - _aligned_free( CUtlMemory::m_pMemory ); + MemAlloc_FreeAligned( CUtlMemory::m_pMemory ); CUtlMemory::m_pMemory = 0; } CUtlMemory::m_nAllocationCount = 0; diff --git a/public/tier1/utlmultilist.h b/public/tier1/utlmultilist.h index ea7cdcea..0a3bf561 100644 --- a/public/tier1/utlmultilist.h +++ b/public/tier1/utlmultilist.h @@ -385,21 +385,6 @@ struct validindex_t } }; -template -struct validindex_t -{ - static inline bool IsValidIndex(const CUtlMultiList *list, unsigned long i) - { - return (i < list->m_MaxElementIndex) && ((list->m_Memory[i].m_Previous != i) || - (list->m_Memory[i].m_Next == i)); - } - - static inline bool IsInList(const CUtlMultiList *list, unsigned long i) - { - return (i < list->m_MaxElementIndex) && (list->Previous(i) != i); - } -}; - //----------------------------------------------------------------------------- // Are nodes in the list or valid? //----------------------------------------------------------------------------- diff --git a/public/tier1/utlvector.h b/public/tier1/utlvector.h index 3dd9186e..f397038a 100644 --- a/public/tier1/utlvector.h +++ b/public/tier1/utlvector.h @@ -25,7 +25,9 @@ #include "tier1/strtools.h" #define FOR_EACH_VEC( vecName, iteratorName ) \ - for ( int iteratorName = 0; iteratorName < vecName.Count(); iteratorName++ ) + for ( int iteratorName = 0; iteratorName < (vecName).Count(); iteratorName++ ) +#define FOR_EACH_VEC_BACK( vecName, iteratorName ) \ + for ( int iteratorName = (vecName).Count()-1; iteratorName >= 0; iteratorName-- ) //----------------------------------------------------------------------------- // The CUtlVector class: @@ -65,9 +67,7 @@ public: const T* Base() const { return m_Memory.Base(); } // Returns the number of elements in the vector - // SIZE IS DEPRECATED! int Count() const; - int Size() const; // don't use me! // Is element index valid? bool IsValidIndex( int i ) const; @@ -87,13 +87,16 @@ public: // Adds multiple elements, uses default constructor int AddMultipleToHead( int num ); - int AddMultipleToTail( int num, const T *pToCopy=NULL ); - int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and + int AddMultipleToTail( int num ); + int AddMultipleToTail( int num, const T *pToCopy ); + int InsertMultipleBefore( int elem, int num ); + int InsertMultipleBefore( int elem, int num, const T *pToCopy ); int InsertMultipleAfter( int elem, int num ); // Calls RemoveAll() then AddMultipleToTail. void SetSize( int size ); void SetCount( int count ); + void SetCountNonDestructively( int count ); //sets count by adding or removing elements to tail TODO: This should probably be the default behavior for SetCount // Calls SetSize and copies each element. void CopyArray( const T *pArray, int size ); @@ -106,6 +109,7 @@ public: // Finds an element (element needs operator== defined) int Find( const T& src ) const; + void FillWithValue( const T& src ); bool HasElement( const T& src ) const; @@ -119,7 +123,10 @@ public: void FastRemove( int elem ); // doesn't preserve order void Remove( int elem ); // preserves order, shifts elements bool FindAndRemove( const T& src ); // removes first occurrence of src, preserves order, shifts elements + bool FindAndFastRemove( const T& src ); // removes first occurrence of src, doesn't preserve order void RemoveMultiple( int elem, int num ); // preserves order, shifts elements + void RemoveMultipleFromHead(int num); // removes num elements from tail + void RemoveMultipleFromTail(int num); // removes num elements from tail void RemoveAll(); // doesn't deallocate memory // Memory deallocation @@ -156,6 +163,7 @@ protected: CAllocator m_Memory; int m_Size; +#ifndef _X360 // For easier access to the elements through the debugger // it's in release builds so this can be used in libraries correctly T *m_pElements; @@ -164,6 +172,9 @@ protected: { m_pElements = Base(); } +#else + inline void ResetDbgInfo() {} +#endif }; @@ -177,8 +188,9 @@ public: }; //----------------------------------------------------------------------------- -// The CUtlVectorFixed class: -// A array class with a fixed allocation scheme +// The CUtlVectorMT class: +// A array class with some sort of mutex protection. Not sure which operations are protected from +// which others. //----------------------------------------------------------------------------- template< class BASE_UTLVECTOR, class MUTEX_TYPE = CThreadFastMutex > @@ -211,8 +223,8 @@ public: //----------------------------------------------------------------------------- -// The CUtlVectorFixed class: -// A array class with a fixed allocation scheme +// The CUtlVectorFixedGrowable class: +// A array class with a fixed allocation scheme backed by a dynamic one //----------------------------------------------------------------------------- template< class T, size_t MAX_SIZE > class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable > @@ -225,6 +237,274 @@ public: }; +//----------------------------------------------------------------------------- +// The CUtlVectorConservative class: +// A array class with a conservative allocation scheme +//----------------------------------------------------------------------------- +template< class T > +class CUtlVectorConservative : public CUtlVector< T, CUtlMemoryConservative > +{ + typedef CUtlVector< T, CUtlMemoryConservative > BaseClass; +public: + + // constructor, destructor + CUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} + CUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} +}; + + +//----------------------------------------------------------------------------- +// The CUtlVectorUltra Conservative class: +// A array class with a very conservative allocation scheme, with customizable allocator +// Especialy useful if you have a lot of vectors that are sparse, or if you're +// carefully packing holders of vectors +//----------------------------------------------------------------------------- +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4200) // warning C4200: nonstandard extension used : zero-sized array in struct/union +#pragma warning(disable : 4815 ) // warning C4815: 'staticData' : zero-sized array in stack object will have no elements +#endif + +class CUtlVectorUltraConservativeAllocator +{ +public: + static void *Alloc( size_t nSize ) + { + return malloc( nSize ); + } + + static void *Realloc( void *pMem, size_t nSize ) + { + return realloc( pMem, nSize ); + } + + static void Free( void *pMem ) + { + free( pMem ); + } + + static size_t GetSize( void *pMem ) + { + return mallocsize( pMem ); + } + +}; + +template +class CUtlVectorUltraConservative : private A +{ +public: + CUtlVectorUltraConservative() + { + m_pData = StaticData(); + } + + ~CUtlVectorUltraConservative() + { + RemoveAll(); + } + + int Count() const + { + return m_pData->m_Size; + } + + static int InvalidIndex() + { + return -1; + } + + inline bool IsValidIndex( int i ) const + { + return (i >= 0) && (i < Count()); + } + + T& operator[]( int i ) + { + Assert( IsValidIndex( i ) ); + return m_pData->m_Elements[i]; + } + + const T& operator[]( int i ) const + { + Assert( IsValidIndex( i ) ); + return m_pData->m_Elements[i]; + } + + T& Element( int i ) + { + Assert( IsValidIndex( i ) ); + return m_pData->m_Elements[i]; + } + + const T& Element( int i ) const + { + Assert( IsValidIndex( i ) ); + return m_pData->m_Elements[i]; + } + + void EnsureCapacity( int num ) + { + int nCurCount = Count(); + if ( num <= nCurCount ) + { + return; + } + if ( m_pData == StaticData() ) + { + m_pData = (Data_t *)A::Alloc( sizeof(int) + ( num * sizeof(T) ) ); + m_pData->m_Size = 0; + } + else + { + int nNeeded = sizeof(int) + ( num * sizeof(T) ); + int nHave = A::GetSize( m_pData ); + if ( nNeeded > nHave ) + { + m_pData = (Data_t *)A::Realloc( m_pData, nNeeded ); + } + } + } + + int AddToTail( const T& src ) + { + int iNew = Count(); + EnsureCapacity( Count() + 1 ); + m_pData->m_Elements[iNew] = src; + m_pData->m_Size++; + return iNew; + } + + void RemoveAll() + { + if ( Count() ) + { + for (int i = m_pData->m_Size; --i >= 0; ) + { + Destruct(&m_pData->m_Elements[i]); + } + } + if ( m_pData != StaticData() ) + { + A::Free( m_pData ); + m_pData = StaticData(); + + } + } + + void PurgeAndDeleteElements() + { + if ( m_pData != StaticData() ) + { + for( int i=0; i < m_pData->m_Size; i++ ) + { + delete Element(i); + } + RemoveAll(); + } + } + + void FastRemove( int elem ) + { + Assert( IsValidIndex(elem) ); + + Destruct( &Element(elem) ); + if (Count() > 0) + { + if ( elem != m_pData->m_Size -1 ) + memcpy( &Element(elem), &Element(m_pData->m_Size-1), sizeof(T) ); + --m_pData->m_Size; + } + if ( !m_pData->m_Size ) + { + A::Free( m_pData ); + m_pData = StaticData(); + } + } + + void Remove( int elem ) + { + Destruct( &Element(elem) ); + ShiftElementsLeft(elem); + --m_pData->m_Size; + if ( !m_pData->m_Size ) + { + A::Free( m_pData ); + m_pData = StaticData(); + } + } + + int Find( const T& src ) const + { + int nCount = Count(); + for ( int i = 0; i < nCount; ++i ) + { + if (Element(i) == src) + return i; + } + return -1; + } + + bool FindAndRemove( const T& src ) + { + int elem = Find( src ); + if ( elem != -1 ) + { + Remove( elem ); + return true; + } + return false; + } + + + bool FindAndFastRemove( const T& src ) + { + int elem = Find( src ); + if ( elem != -1 ) + { + FastRemove( elem ); + return true; + } + return false; + } + + struct Data_t + { + int m_Size; + T m_Elements[]; + }; + + Data_t *m_pData; +private: + void ShiftElementsLeft( int elem, int num = 1 ) + { + int Size = Count(); + Assert( IsValidIndex(elem) || ( Size == 0 ) || ( num == 0 )); + int numToMove = Size - elem - num; + if ((numToMove > 0) && (num > 0)) + { + Q_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) ); + +#ifdef _DEBUG + Q_memset( &Element(Size-num), 0xDD, num * sizeof(T) ); +#endif + } + } + + + + static Data_t *StaticData() + { + static Data_t staticData; + Assert( staticData.m_Size == 0 ); + return &staticData; + } +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + //----------------------------------------------------------------------------- // The CCopyableUtlVector class: // A array class that allows copy construction (so you can nest a CUtlVector inside of another one of our containers) @@ -242,6 +522,8 @@ public: CCopyableUtlVector( CCopyableUtlVector const& vec ) { CopyArray( vec.Base(), vec.Count() ); } }; +// TODO (Ilya): It seems like all the functions in CUtlVector are simple enough that they should be inlined. + //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- @@ -284,24 +566,28 @@ inline CUtlVector& CUtlVector::operator=( const CUtlVector &ot template< typename T, class A > inline T& CUtlVector::operator[]( int i ) { + Assert( i < m_Size ); return m_Memory[ i ]; } template< typename T, class A > inline const T& CUtlVector::operator[]( int i ) const { + Assert( i < m_Size ); return m_Memory[ i ]; } template< typename T, class A > inline T& CUtlVector::Element( int i ) { + Assert( i < m_Size ); return m_Memory[ i ]; } template< typename T, class A > inline const T& CUtlVector::Element( int i ) const { + Assert( i < m_Size ); return m_Memory[ i ]; } @@ -337,12 +623,6 @@ inline const T& CUtlVector::Tail() const //----------------------------------------------------------------------------- // Count //----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::Size() const -{ - return m_Size; -} - template< typename T, class A > inline int CUtlVector::Count() const { @@ -441,7 +721,9 @@ template< typename T, class A > void CUtlVector::EnsureCount( int num ) { if (Count() < num) + { AddMultipleToTail( num - Count() ); + } } @@ -559,11 +841,17 @@ inline int CUtlVector::AddMultipleToHead( int num ) return InsertMultipleBefore( 0, num ); } +template< typename T, class A > +inline int CUtlVector::AddMultipleToTail( int num ) +{ + return InsertMultipleBefore( m_Size, num ); +} + template< typename T, class A > inline int CUtlVector::AddMultipleToTail( int num, const T *pToCopy ) { // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || !pToCopy || (pToCopy + num < Base()) || (pToCopy >= (Base() + Count()) ) ); + Assert( (Base() == NULL) || !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count()) ) ); return InsertMultipleBefore( m_Size, num, pToCopy ); } @@ -588,6 +876,14 @@ inline void CUtlVector::SetSize( int size ) SetCount( size ); } +template< typename T, class A > +void CUtlVector::SetCountNonDestructively( int count ) +{ + int delta = count - m_Size; + if(delta > 0) AddMultipleToTail( delta ); + else if(delta < 0) RemoveMultipleFromTail( -delta ); +} + template< typename T, class A > void CUtlVector::CopyArray( const T *pArray, int size ) { @@ -606,7 +902,9 @@ void CUtlVector::Swap( CUtlVector< T, A > &vec ) { m_Memory.Swap( vec.m_Memory ); V_swap( m_Size, vec.m_Size ); +#ifndef _X360 V_swap( m_pElements, vec.m_pElements ); +#endif } template< typename T, class A > @@ -617,15 +915,37 @@ int CUtlVector::AddVectorToTail( CUtlVector const &src ) int base = Count(); // Make space. - AddMultipleToTail( src.Count() ); + int nSrcCount = src.Count(); + EnsureCapacity( base + nSrcCount ); // Copy the elements. - for ( int i=0; i < src.Count(); i++ ) + m_Size += nSrcCount; + for ( int i=0; i < nSrcCount; i++ ) { - (*this)[base + i] = src[i]; + CopyConstruct( &Element(base+i), src[i] ); + } + return base; +} + +template< typename T, class A > +inline int CUtlVector::InsertMultipleBefore( int elem, int num ) +{ + if( num == 0 ) + return elem; + + // Can insert at the end + Assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(num); + ShiftElementsRight( elem, num ); + + // Invoke default constructors + for (int i = 0; i < num; ++i ) + { + Construct( &Element( elem+i ) ); } - return base; + return elem; } template< typename T, class A > @@ -638,18 +958,21 @@ inline int CUtlVector::InsertMultipleBefore( int elem, int num, const T *p Assert( (elem == Count()) || IsValidIndex(elem) ); GrowVector(num); - ShiftElementsRight(elem, num); + ShiftElementsRight( elem, num ); // Invoke default constructors - for (int i = 0; i < num; ++i) - Construct( &Element(elem+i) ); - - // Copy stuff in? - if ( pToInsert ) + if ( !pToInsert ) + { + for (int i = 0; i < num; ++i ) + { + Construct( &Element( elem+i ) ); + } + } + else { for ( int i=0; i < num; i++ ) { - Element( elem+i ) = pToInsert[i]; + CopyConstruct( &Element( elem+i ), pToInsert[i] ); } } @@ -671,6 +994,15 @@ int CUtlVector::Find( const T& src ) const return -1; } +template< typename T, class A > +void CUtlVector::FillWithValue( const T& src ) +{ + for ( int i = 0; i < Count(); i++ ) + { + Element(i) = src; + } +} + template< typename T, class A > bool CUtlVector::HasElement( const T& src ) const { @@ -689,7 +1021,8 @@ void CUtlVector::FastRemove( int elem ) Destruct( &Element(elem) ); if (m_Size > 0) { - memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) ); + if ( elem != m_Size -1 ) + memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) ); --m_Size; } } @@ -714,6 +1047,18 @@ bool CUtlVector::FindAndRemove( const T& src ) return false; } +template< typename T, class A > +bool CUtlVector::FindAndFastRemove( const T& src ) +{ + int elem = Find( src ); + if ( elem != -1 ) + { + FastRemove( elem ); + return true; + } + return false; +} + template< typename T, class A > void CUtlVector::RemoveMultiple( int elem, int num ) { @@ -727,6 +1072,29 @@ void CUtlVector::RemoveMultiple( int elem, int num ) m_Size -= num; } +template< typename T, class A > +void CUtlVector::RemoveMultipleFromHead( int num ) +{ + Assert( num <= Count() ); + + for (int i = num; --i >= 0; ) + Destruct(&Element(i)); + + ShiftElementsLeft(0, num); + m_Size -= num; +} + +template< typename T, class A > +void CUtlVector::RemoveMultipleFromTail( int num ) +{ + Assert( num <= Count() ); + + for (int i = m_Size-num; i < m_Size; i++) + Destruct(&Element(i)); + + m_Size -= num; +} + template< typename T, class A > void CUtlVector::RemoveAll() { @@ -790,5 +1158,55 @@ void CUtlVector::Validate( CValidator &validator, char *pchName ) } #endif // DBGFLAG_VALIDATE +// A vector class for storing pointers, so that the elements pointed to by the pointers are deleted +// on exit. +template class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> > +{ +public: + ~CUtlVectorAutoPurge( void ) + { + this->PurgeAndDeleteElements(); + } + +}; + +// easy string list class with dynamically allocated strings. For use with V_SplitString, etc. +// Frees the dynamic strings in destructor. +class CUtlStringList : public CUtlVectorAutoPurge< char *> +{ +public: + void CopyAndAddToTail( char const *pString ) // clone the string and add to the end + { + char *pNewStr = new char[1 + strlen( pString )]; + V_strcpy( pNewStr, pString ); + AddToTail( pNewStr ); + } + + static int __cdecl SortFunc( char * const * sz1, char * const * sz2 ) + { + return strcmp( *sz1, *sz2 ); + } + +}; + + + +// placing it here a few days before Cert to minimize disruption to the rest of codebase +class CSplitString: public CUtlVector > +{ +public: + CSplitString(const char *pString, const char *pSeparator); + CSplitString(const char *pString, const char **pSeparators, int nSeparators); + ~CSplitString(); + // + // NOTE: If you want to make Construct() public and implement Purge() here, you'll have to free m_szBuffer there + // +private: + void Construct(const char *pString, const char **pSeparators, int nSeparators); + void PurgeAndDeleteElements(); +private: + char *m_szBuffer; // a copy of original string, with '\0' instead of separators +}; + #endif // CCVECTOR_H diff --git a/public/toolframework/itoolentity.h b/public/toolframework/itoolentity.h index 5dde011f..d55889b6 100644 --- a/public/toolframework/itoolentity.h +++ b/public/toolframework/itoolentity.h @@ -220,9 +220,6 @@ public: virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) = 0; virtual ITempEntsSystem *GetTempEntsSystem( void ) = 0; - - // Only in VSERVERTOOLS003 and later - virtual CBaseTempEntity *GetTempEntList( void ) = 0; virtual CGlobalEntityList *GetEntityList( void ) = 0; @@ -248,8 +245,9 @@ public: typedef IServerTools IServerTools001; #define VSERVERTOOLS_INTERFACE_VERSION_1 "VSERVERTOOLS001" -#define VSERVERTOOLS_INTERFACE_VERSION "VSERVERTOOLS002" -#define VSERVERTOOLS_INTERFACE_VERSION_INT 2 +#define VSERVERTOOLS_INTERFACE_VERSION_2 "VSERVERTOOLS002" +#define VSERVERTOOLS_INTERFACE_VERSION "VSERVERTOOLS003" +#define VSERVERTOOLS_INTERFACE_VERSION_INT 3 //----------------------------------------------------------------------------- // Purpose: Client side tool interace (right now just handles IClientRenderables). diff --git a/public/vscript/ivscript.h b/public/vscript/ivscript.h new file mode 100644 index 00000000..7f5c1db7 --- /dev/null +++ b/public/vscript/ivscript.h @@ -0,0 +1,1415 @@ +//========== Copyright © 2008, Valve Corporation, All rights reserved. ======== +// +// Purpose: VScript +// +// Overview +// -------- +// VScript is an abstract binding layer that allows code to expose itself to +// multiple scripting languages in a uniform format. Code can expose +// functions, classes, and data to the scripting languages, and can also +// call functions that reside in scripts. +// +// Initializing +// ------------ +// +// To create a script virtual machine (VM), grab the global instance of +// IScriptManager, call CreateVM, then call Init on the returned VM. Right +// now you can have multiple VMs, but only VMs for a specific language. +// +// Exposing functions and classes +// ------------------------------ +// +// To expose a C++ function to the scripting system, you just need to fill out a +// description block. Using templates, the system will automatically deduce +// all of the binding requirements (parameters and return values). Functions +// are limited as to what the types of the parameters can be. See ScriptVariant_t. +// +// extern IScriptVM *pScriptVM; +// bool Foo( int ); +// void Bar(); +// float FooBar( int, const char * ); +// float OverlyTechnicalName( bool ); +// +// void RegisterFuncs() +// { +// ScriptRegisterFunction( pScriptVM, Foo ); +// ScriptRegisterFunction( pScriptVM, Bar ); +// ScriptRegisterFunction( pScriptVM, FooBar ); +// ScriptRegisterFunctionNamed( pScriptVM, OverlyTechnicalName, "SimpleName" ); +// } +// +// class CMyClass +// { +// public: +// bool Foo( int ); +// void Bar(); +// float FooBar( int, const char * ); +// float OverlyTechnicalName( bool ); +// }; +// +// BEGIN_SCRIPTDESC_ROOT( CMyClass ) +// DEFINE_SCRIPTFUNC( Foo ) +// DEFINE_SCRIPTFUNC( Bar ) +// DEFINE_SCRIPTFUNC( FooBar ) +// DEFINE_SCRIPTFUNC_NAMED( OverlyTechnicalName, "SimpleMemberName" ) +// END_SCRIPTDESC(); +// +// class CMyDerivedClass : public CMyClass +// { +// public: +// float DerivedFunc() const; +// }; +// +// BEGIN_SCRIPTDESC( CMyDerivedClass, CMyClass ) +// DEFINE_SCRIPTFUNC( DerivedFunc ) +// END_SCRIPTDESC(); +// +// CMyDerivedClass derivedInstance; +// +// void AnotherFunction() +// { +// // Manual class exposure +// pScriptVM->RegisterClass( GetScriptDescForClass( CMyClass ) ); +// +// // Auto registration by instance +// pScriptVM->RegisterInstance( &derivedInstance, "theInstance" ); +// } +// +// Classes with "DEFINE_SCRIPT_CONSTRUCTOR()" in their description can be instanced within scripts +// +// Scopes +// ------ +// Scripts can either be run at the global scope, or in a user defined scope. In the latter case, +// all "globals" within the script are actually in the scope. This can be used to bind private +// data spaces with C++ objects. +// +// Calling a function on a script +// ------------------------------ +// Generally, use the "Call" functions. This example is the equivalent of DoIt("Har", 6.0, 99). +// +// hFunction = pScriptVM->LookupFunction( "DoIt", hScope ); +// pScriptVM->Call( hFunction, hScope, true, NULL, "Har", 6.0, 99 ); +// +//============================================================================= + +#ifndef IVSCRIPT_H +#define IVSCRIPT_H + +#include "platform.h" +#include "datamap.h" +#include "appframework/IAppSystem.h" +#include "tier1/functors.h" +#include "tier0/memdbgon.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +#ifdef VSCRIPT_DLL_EXPORT +#define VSCRIPT_INTERFACE DLL_EXPORT +#define VSCRIPT_OVERLOAD DLL_GLOBAL_EXPORT +#define VSCRIPT_CLASS DLL_CLASS_EXPORT +#else +#define VSCRIPT_INTERFACE DLL_IMPORT +#define VSCRIPT_OVERLOAD DLL_GLOBAL_IMPORT +#define VSCRIPT_CLASS DLL_CLASS_IMPORT +#endif + +class CUtlBuffer; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define VSCRIPT_INTERFACE_VERSION "VScriptManager010" + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +class IScriptVM; + +enum ScriptLanguage_t +{ + SL_NONE, + SL_GAMEMONKEY, + SL_SQUIRREL, + SL_LUA, + SL_PYTHON, + + SL_DEFAULT = SL_SQUIRREL +}; + +class IScriptManager : public IAppSystem +{ +public: + virtual IScriptVM *CreateVM( ScriptLanguage_t language = SL_DEFAULT ) = 0; + virtual void DestroyVM( IScriptVM * ) = 0; +}; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +DECLARE_POINTER_HANDLE( HSCRIPT ); +#define INVALID_HSCRIPT ((HSCRIPT)-1) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +enum ExtendedFieldType +{ + FIELD_TYPEUNKNOWN = FIELD_TYPECOUNT, + FIELD_CSTRING, + FIELD_HSCRIPT, + FIELD_VARIANT, +}; + +typedef int ScriptDataType_t; +struct ScriptVariant_t; + +template struct ScriptDeducer { /*enum { FIELD_TYPE = FIELD_TYPEUNKNOWN };*/ }; +#define DECLARE_DEDUCE_FIELDTYPE( fieldType, type ) template<> struct ScriptDeducer { enum { FIELD_TYPE = fieldType }; }; + +DECLARE_DEDUCE_FIELDTYPE( FIELD_VOID, void ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_FLOAT, float ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, const char * ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, char * ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, Vector ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, const Vector &); +DECLARE_DEDUCE_FIELDTYPE( FIELD_INTEGER, int ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_BOOLEAN, bool ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_CHARACTER, char ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_HSCRIPT, HSCRIPT ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VARIANT, ScriptVariant_t ); + +#define ScriptDeduceType( T ) ScriptDeducer::FIELD_TYPE + +template +inline const char * ScriptFieldTypeName() +{ + T::using_unknown_script_type(); +} + +#define DECLARE_NAMED_FIELDTYPE( fieldType, strName ) template <> inline const char * ScriptFieldTypeName() { return strName; } +DECLARE_NAMED_FIELDTYPE( void, "void" ); +DECLARE_NAMED_FIELDTYPE( float, "float" ); +DECLARE_NAMED_FIELDTYPE( const char *, "cstring" ); +DECLARE_NAMED_FIELDTYPE( char *, "cstring" ); +DECLARE_NAMED_FIELDTYPE( Vector, "vector" ); +DECLARE_NAMED_FIELDTYPE( const Vector&, "vector" ); +DECLARE_NAMED_FIELDTYPE( int, "integer" ); +DECLARE_NAMED_FIELDTYPE( bool, "boolean" ); +DECLARE_NAMED_FIELDTYPE( char, "character" ); +DECLARE_NAMED_FIELDTYPE( HSCRIPT, "hscript" ); +DECLARE_NAMED_FIELDTYPE( ScriptVariant_t, "variant" ); + +inline const char * ScriptFieldTypeName( int16 eType) +{ + switch( eType ) + { + case FIELD_VOID: return "void"; + case FIELD_FLOAT: return "float"; + case FIELD_CSTRING: return "cstring"; + case FIELD_VECTOR: return "vector"; + case FIELD_INTEGER: return "integer"; + case FIELD_BOOLEAN: return "boolean"; + case FIELD_CHARACTER: return "character"; + case FIELD_HSCRIPT: return "hscript"; + case FIELD_VARIANT: return "variant"; + default: return "unknown_script_type"; + } +} + +//--------------------------------------------------------- + +struct ScriptFuncDescriptor_t +{ + ScriptFuncDescriptor_t() + { + m_pszFunction = NULL; + m_ReturnType = FIELD_TYPEUNKNOWN; + m_pszDescription = NULL; + } + + const char *m_pszScriptName; + const char *m_pszFunction; + const char *m_pszDescription; + ScriptDataType_t m_ReturnType; + CUtlVector m_Parameters; +}; + + +//--------------------------------------------------------- + +// Prefix a script description with this in order to not show the function or class in help +#define SCRIPT_HIDE "@" + +// Prefix a script description of a class to indicate it is a singleton and the single instance should be in the help +#define SCRIPT_SINGLETON "!" + +// Prefix a script description with this to indicate it should be represented using an alternate name +#define SCRIPT_ALIAS( alias, description ) "#" alias ":" description + +//--------------------------------------------------------- + +enum ScriptFuncBindingFlags_t +{ + SF_MEMBER_FUNC = 0x01, +}; + +typedef bool (*ScriptBindingFunc_t)( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ); + +struct ScriptFunctionBinding_t +{ + ScriptFuncDescriptor_t m_desc; + ScriptBindingFunc_t m_pfnBinding; + void * m_pFunction; + unsigned m_flags; + + int m_unknown[3]; +}; + +//--------------------------------------------------------- +class IScriptInstanceHelper +{ +public: + virtual void *GetProxied( void *p ) { return p; } + virtual bool ToString( void *p, char *pBuf, int bufSize ) { return false; } + virtual void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId ) { return NULL; } +}; + +//--------------------------------------------------------- + +struct ScriptClassDesc_t +{ + ScriptClassDesc_t() : m_pszScriptName( 0 ), m_pszClassname( 0 ), m_pszDescription( 0 ), m_pBaseDesc( 0 ), m_pfnConstruct( 0 ), m_pfnDestruct( 0 ), pHelper(NULL) {} + + const char * m_pszScriptName; + const char * m_pszClassname; + const char * m_pszDescription; + ScriptClassDesc_t * m_pBaseDesc; + CUtlVector m_FunctionBindings; + + void *(*m_pfnConstruct)(); + void (*m_pfnDestruct)( void *); + IScriptInstanceHelper * pHelper; // optional helper +}; + +//--------------------------------------------------------- +// A simple variant type. Intentionally not full featured (no implicit conversion, no memory management) +//--------------------------------------------------------- + +enum SVFlags_t +{ + SV_FREE = 0x01, +}; + +#pragma warning(push) +#pragma warning(disable:4800) +struct ScriptVariant_t +{ + ScriptVariant_t() : m_flags( 0 ), m_type( FIELD_VOID ) { m_pVector = 0; } + ScriptVariant_t( int val ) : m_flags( 0 ), m_type( FIELD_INTEGER ) { m_int = val;} + ScriptVariant_t( float val ) : m_flags( 0 ), m_type( FIELD_FLOAT ) { m_float = val; } + ScriptVariant_t( double val ) : m_flags( 0 ), m_type( FIELD_FLOAT ) { m_float = (float)val; } + ScriptVariant_t( char val ) : m_flags( 0 ), m_type( FIELD_CHARACTER ) { m_char = val; } + ScriptVariant_t( bool val ) : m_flags( 0 ), m_type( FIELD_BOOLEAN ) { m_bool = val; } + ScriptVariant_t( HSCRIPT val ) : m_flags( 0 ), m_type( FIELD_HSCRIPT ) { m_hScript = val; } + + ScriptVariant_t( const Vector &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = &val; } else { m_pVector = new Vector( val ); m_flags |= SV_FREE; } } + ScriptVariant_t( const Vector *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = val; } else { m_pVector = new Vector( *val ); m_flags |= SV_FREE; } } + ScriptVariant_t( const char *val , bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_CSTRING ) { if ( !bCopy ) { m_pszString = val; } else { m_pszString = strdup( val ); m_flags |= SV_FREE; } } + + bool IsNull() const { return (m_type == FIELD_VOID ); } + + operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; } + operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; } + operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; } + operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); static Vector vecNull(0, 0, 0); return (m_pVector) ? *m_pVector : vecNull; } + operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; } + operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; } + operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; } + + void operator=( int i ) { m_type = FIELD_INTEGER; m_int = i; } + void operator=( float f ) { m_type = FIELD_FLOAT; m_float = f; } + void operator=( double f ) { m_type = FIELD_FLOAT; m_float = (float)f; } + void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_pVector = &vec; } + void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_pVector = vec; } + void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_pszString = psz; } + void operator=( char c ) { m_type = FIELD_CHARACTER; m_char = c; } + void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_bool = b; } + void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_hScript = h; } + + void Free() { if ( ( m_flags & SV_FREE ) && ( m_type == FIELD_HSCRIPT || m_type == FIELD_VECTOR || m_type == FIELD_CSTRING ) ) delete m_pszString; } // Generally only needed for return results + + template + T Get() + { + T value; + AssignTo( &value ); + return value; + } + + template + bool AssignTo( T *pDest ) + { + ScriptDataType_t destType = ScriptDeduceType( T ); + if ( destType == FIELD_TYPEUNKNOWN ) + { + DevWarning( "Unable to convert script variant to unknown type\n" ); + } + if ( destType == m_type ) + { + *pDest = *this; + return true; + } + + if ( m_type != FIELD_VECTOR && m_type != FIELD_CSTRING && destType != FIELD_VECTOR && destType != FIELD_CSTRING ) + { + switch ( m_type ) + { + case FIELD_VOID: *pDest = 0; break; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_CHARACTER: *pDest = m_char; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + case FIELD_HSCRIPT: *pDest = m_hScript; return true; + } + } + else + { + DevWarning( "No free conversion of %s script variant to %s right now\n", + ScriptFieldTypeName( m_type ), ScriptFieldTypeName() ); + if ( destType != FIELD_VECTOR ) + { + *pDest = 0; + } + } + return false; + } + + bool AssignTo( float *pDest ) + { + switch( m_type ) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + default: + DevWarning( "No conversion from %s to float now\n", ScriptFieldTypeName( m_type ) ); + return false; + } + } + + bool AssignTo( int *pDest ) + { + switch( m_type ) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + default: + DevWarning( "No conversion from %s to int now\n", ScriptFieldTypeName( m_type ) ); + return false; + } + } + + bool AssignTo( bool *pDest ) + { + switch( m_type ) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + default: + DevWarning( "No conversion from %s to bool now\n", ScriptFieldTypeName( m_type ) ); + return false; + } + } + + bool AssignTo( char **pDest ) + { + DevWarning( "No free conversion of string or vector script variant right now\n" ); + // If want to support this, probably need to malloc string and require free on other side [3/24/2008 tom] + *pDest = ""; + return false; + } + + bool AssignTo( ScriptVariant_t *pDest ) + { + pDest->m_type = m_type; + if ( m_type == FIELD_VECTOR ) + { + pDest->m_pVector = new Vector; + ((Vector *)(pDest->m_pVector))->Init( m_pVector->x, m_pVector->y, m_pVector->z ); + pDest->m_flags |= SV_FREE; + } + else if ( m_type == FIELD_CSTRING ) + { + pDest->m_pszString = strdup( m_pszString ); + pDest->m_flags |= SV_FREE; + } + else + { + pDest->m_int = m_int; + } + return false; + } + + union + { + int m_int; + float m_float; + const char * m_pszString; + const Vector * m_pVector; + char m_char; + bool m_bool; + HSCRIPT m_hScript; + }; + + int16 m_type; + int16 m_flags; + +private: +}; + +#define SCRIPT_VARIANT_NULL ScriptVariant_t() + +#pragma warning(pop) + + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#include "vscript_templates.h" + +// Lower level macro primitives +#define ScriptInitFunctionBinding( pScriptFunction, func ) ScriptInitFunctionBindingNamed( pScriptFunction, func, #func ) +#define ScriptInitFunctionBindingNamed( pScriptFunction, func, scriptName ) do { ScriptInitFuncDescriptorNamed( (&(pScriptFunction)->m_desc), func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( &func ); (pScriptFunction)->m_pFunction = (void *)&func; } while (0) + +#define ScriptInitMemberFunctionBinding( pScriptFunction, class, func ) ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, #func ) +#define ScriptInitMemberFunctionBindingNamed( pScriptFunction, class, func, scriptName ) ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName ) +#define ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName ) do { ScriptInitMemberFuncDescriptor_( (&(pScriptFunction)->m_desc), class, func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( ((class *)0), &class::func ); (pScriptFunction)->m_pFunction = ScriptConvertFuncPtrToVoid( &class::func ); (pScriptFunction)->m_flags = SF_MEMBER_FUNC; } while (0) + +#define ScriptInitClassDesc( pClassDesc, class, pBaseClassDesc ) ScriptInitClassDescNamed( pClassDesc, class, pBaseClassDesc, #class ) +#define ScriptInitClassDescNamed( pClassDesc, class, pBaseClassDesc, scriptName ) ScriptInitClassDescNamed_( pClassDesc, class, pBaseClassDesc, scriptName ) +#define ScriptInitClassDescNoBase( pClassDesc, class ) ScriptInitClassDescNoBaseNamed( pClassDesc, class, #class ) +#define ScriptInitClassDescNoBaseNamed( pClassDesc, class, scriptName ) ScriptInitClassDescNamed_( pClassDesc, class, NULL, scriptName ) +#define ScriptInitClassDescNamed_( pClassDesc, class, pBaseClassDesc, scriptName ) do { (pClassDesc)->m_pszScriptName = scriptName; (pClassDesc)->m_pszClassname = #class; (pClassDesc)->m_pBaseDesc = pBaseClassDesc; } while ( 0 ) + +#define ScriptAddFunctionToClassDesc( pClassDesc, class, func, description ) ScriptAddFunctionToClassDescNamed( pClassDesc, class, func, #func, description ) +#define ScriptAddFunctionToClassDescNamed( pClassDesc, class, func, scriptName, description ) do { ScriptFunctionBinding_t *pBinding = &((pClassDesc)->m_FunctionBindings[(pClassDesc)->m_FunctionBindings.AddToTail()]); pBinding->m_desc.m_pszDescription = description; ScriptInitMemberFunctionBindingNamed( pBinding, class, func, scriptName ); } while (0) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define ScriptRegisterFunction( pVM, func, description ) ScriptRegisterFunctionNamed( pVM, func, #func, description ) +#define ScriptRegisterFunctionNamed( pVM, func, scriptName, description ) do { static ScriptFunctionBinding_t binding; binding.m_desc.m_pszDescription = description; binding.m_desc.m_Parameters.RemoveAll(); ScriptInitFunctionBindingNamed( &binding, func, scriptName ); pVM->RegisterFunction( &binding ); } while (0) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define ALLOW_SCRIPT_ACCESS() template friend ScriptClassDesc_t *GetScriptDesc(T *); + +#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_NAMED( className, baseClass, #className, description ) +#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_NAMED( className, #className, description ) + +#if defined( COMPILER_MSVC ) + #define DEFINE_SCRIPTDESC_FUNCTION( className, baseClass ) \ + ScriptClassDesc_t * GetScriptDesc( className * ) +#else + #define DEFINE_SCRIPTDESC_FUNCTION( className, baseClass ) \ + template <> ScriptClassDesc_t * GetScriptDesc( baseClass *); \ + template <> ScriptClassDesc_t * GetScriptDesc( className *) +#endif + +#define BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) \ + ScriptClassDesc_t g_##className##_ScriptDesc; \ + DEFINE_SCRIPTDESC_FUNCTION( className, baseClass ) \ + { \ + static bool bInitialized; \ + if ( bInitialized ) \ + { \ + return &g_##className##_ScriptDesc; \ + } \ + \ + bInitialized = true; \ + \ + typedef className _className; \ + ScriptClassDesc_t *pDesc = &g_##className##_ScriptDesc; \ + pDesc->m_pszDescription = description; \ + ScriptInitClassDescNamed( pDesc, className, GetScriptDescForClass( baseClass ), scriptName ); \ + ScriptClassDesc_t *pInstanceHelperBase = pDesc->m_pBaseDesc; \ + while ( pInstanceHelperBase ) \ + { \ + if ( pInstanceHelperBase->pHelper ) \ + { \ + pDesc->pHelper = pInstanceHelperBase->pHelper; \ + break; \ + } \ + pInstanceHelperBase = pInstanceHelperBase->m_pBaseDesc; \ + } + + +#define BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) \ + BEGIN_SCRIPTDESC_NAMED( className, ScriptNoBase_t, scriptName, description ) + +#define END_SCRIPTDESC() \ + return pDesc; \ + } + +#define DEFINE_SCRIPTFUNC( func, description ) DEFINE_SCRIPTFUNC_NAMED( func, #func, description ) +#define DEFINE_SCRIPTFUNC_NAMED( func, scriptName, description ) ScriptAddFunctionToClassDescNamed( pDesc, _className, func, scriptName, description ); +#define DEFINE_SCRIPT_CONSTRUCTOR() ScriptAddConstructorToClassDesc( pDesc, _className ); +#define DEFINE_SCRIPT_INSTANCE_HELPER( p ) pDesc->pHelper = (p); + +template ScriptClassDesc_t *GetScriptDesc(T *); + +struct ScriptNoBase_t; +template <> inline ScriptClassDesc_t *GetScriptDesc( ScriptNoBase_t *) { return NULL; } + +#define GetScriptDescForClass( className ) GetScriptDesc( ( className *)NULL ) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +template +class CScriptConstructor +{ +public: + static void *Construct() { return new T; } + static void Destruct( void *p ) { delete (T *)p; } +}; + +#define ScriptAddConstructorToClassDesc( pClassDesc, class ) do { (pClassDesc)->m_pfnConstruct = &CScriptConstructor::Construct; (pClassDesc)->m_pfnDestruct = &CScriptConstructor::Destruct; } while (0) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +enum ScriptErrorLevel_t +{ + SCRIPT_LEVEL_WARNING = 0, + SCRIPT_LEVEL_ERROR, +}; + +typedef void ( *ScriptOutputFunc_t )( const char *pszText ); +typedef bool ( *ScriptErrorFunc_t )( ScriptErrorLevel_t eLevel, const char *pszText ); + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#ifdef RegisterClass +#undef RegisterClass +#endif + +enum ScriptStatus_t +{ + SCRIPT_ERROR = -1, + SCRIPT_DONE, + SCRIPT_RUNNING, +}; + +class IScriptVM +{ +public: + virtual bool Init() = 0; + virtual void Shutdown() = 0; + + virtual bool ConnectDebugger() = 0; + virtual void DisconnectDebugger() = 0; + + virtual ScriptLanguage_t GetLanguage() = 0; + virtual const char *GetLanguageName() = 0; + + virtual void AddSearchPath( const char *pszSearchPath ) = 0; + + //-------------------------------------------------------- + + virtual bool Frame( float simTime ) = 0; + + //-------------------------------------------------------- + // Simple script usage + //-------------------------------------------------------- + virtual ScriptStatus_t Run( const char *pszScript, bool bWait = true ) = 0; + inline ScriptStatus_t Run( const unsigned char *pszScript, bool bWait = true ) { return Run( (char *)pszScript, bWait ); } + + //-------------------------------------------------------- + // Compilation + //-------------------------------------------------------- + virtual HSCRIPT CompileScript( const char *pszScript, const char *pszId = NULL ) = 0; + inline HSCRIPT CompileScript( const unsigned char *pszScript, const char *pszId = NULL ) { return CompileScript( (char *)pszScript, pszId ); } + virtual void ReleaseScript( HSCRIPT ) = 0; + + //-------------------------------------------------------- + // Execution of compiled + //-------------------------------------------------------- + virtual ScriptStatus_t Run( HSCRIPT hScript, HSCRIPT hScope = NULL, bool bWait = true ) = 0; + virtual ScriptStatus_t Run( HSCRIPT hScript, bool bWait ) = 0; + + //-------------------------------------------------------- + // Scope + //-------------------------------------------------------- + virtual HSCRIPT CreateScope( const char *pszScope, HSCRIPT hParent = NULL ) = 0; + virtual HSCRIPT ReferenceScope( HSCRIPT hScript ) = 0; + virtual void ReleaseScope( HSCRIPT hScript ) = 0; + + //-------------------------------------------------------- + // Script functions + //-------------------------------------------------------- + virtual HSCRIPT LookupFunction( const char *pszFunction, HSCRIPT hScope = NULL ) = 0; + virtual void ReleaseFunction( HSCRIPT hScript ) = 0; + + //-------------------------------------------------------- + // Script functions (raw, use Call()) + //-------------------------------------------------------- + virtual ScriptStatus_t ExecuteFunction( HSCRIPT hFunction, ScriptVariant_t *pArgs, int nArgs, ScriptVariant_t *pReturn, HSCRIPT hScope, bool bWait ) = 0; + + //-------------------------------------------------------- + // External functions + //-------------------------------------------------------- + virtual void RegisterFunction( ScriptFunctionBinding_t *pScriptFunction ) = 0; + + //-------------------------------------------------------- + // External classes + //-------------------------------------------------------- + virtual bool RegisterClass( ScriptClassDesc_t *pClassDesc ) = 0; + + //-------------------------------------------------------- + // External instances. Note class will be auto-registered. + //-------------------------------------------------------- + + virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pDesc, void *pInstance ) = 0; + virtual void SetInstanceUniqeId( HSCRIPT hInstance, const char *pszId ) = 0; + template HSCRIPT RegisterInstance( T *pInstance ) { return RegisterInstance( GetScriptDesc( pInstance ), pInstance ); } + template HSCRIPT RegisterInstance( T *pInstance, const char *pszInstance, HSCRIPT hScope = NULL) { HSCRIPT hInstance = RegisterInstance( GetScriptDesc( pInstance ), pInstance ); SetValue( hScope, pszInstance, hInstance ); return hInstance; } + virtual void RemoveInstance( HSCRIPT ) = 0; + void RemoveInstance( HSCRIPT hInstance, const char *pszInstance, HSCRIPT hScope = NULL ) { ClearValue( hScope, pszInstance ); RemoveInstance( hInstance ); } + void RemoveInstance( const char *pszInstance, HSCRIPT hScope = NULL ) { ScriptVariant_t val; if ( GetValue( hScope, pszInstance, &val ) ) { if ( val.m_type == FIELD_HSCRIPT ) { RemoveInstance( val, pszInstance, hScope ); } ReleaseValue( val ); } } + + virtual void *GetInstanceValue( HSCRIPT hInstance, ScriptClassDesc_t *pExpectedType = NULL ) = 0; + + //---------------------------------------------------------------------------- + + virtual bool GenerateUniqueKey( const char *pszRoot, char *pBuf, int nBufSize ) = 0; + + //---------------------------------------------------------------------------- + + virtual bool ValueExists( HSCRIPT hScope, const char *pszKey ) = 0; + bool ValueExists( const char *pszKey ) { return ValueExists( NULL, pszKey ); } + + virtual bool SetValue( HSCRIPT hScope, const char *pszKey, const char *pszValue ) = 0; + virtual bool SetValue( HSCRIPT hScope, const char *pszKey, const ScriptVariant_t &value ) = 0; + bool SetValue( const char *pszKey, const ScriptVariant_t &value ) { return SetValue(NULL, pszKey, value ); } + + virtual void CreateTable( ScriptVariant_t &Table ) = 0; + virtual int GetNumTableEntries( HSCRIPT hScope ) = 0; + virtual int GetKeyValue( HSCRIPT hScope, int nIterator, ScriptVariant_t *pKey, ScriptVariant_t *pValue ) = 0; + + virtual bool GetValue( HSCRIPT hScope, const char *pszKey, ScriptVariant_t *pValue ) = 0; + bool GetValue( const char *pszKey, ScriptVariant_t *pValue ) { return GetValue(NULL, pszKey, pValue ); } + virtual void ReleaseValue( ScriptVariant_t &value ) = 0; + + virtual bool ClearValue( HSCRIPT hScope, const char *pszKey ) = 0; + bool ClearValue( const char *pszKey) { return ClearValue( NULL, pszKey ); } + + //---------------------------------------------------------------------------- + + virtual void WriteState( CUtlBuffer *pBuffer ) = 0; + virtual void ReadState( CUtlBuffer *pBuffer ) = 0; + virtual void RemoveOrphanInstances() = 0; + + virtual void DumpState() = 0; + + virtual void SetOutputCallback( ScriptOutputFunc_t pFunc ) = 0; + virtual void SetErrorCallback( ScriptErrorFunc_t pFunc ) = 0; + + //---------------------------------------------------------------------------- + + virtual bool RaiseException( const char *pszExceptionText ) = 0; + + //---------------------------------------------------------------------------- + // Call API + // + // Note for string and vector return types, the caller must delete the pointed to memory + //---------------------------------------------------------------------------- + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope = NULL, bool bWait = true, ScriptVariant_t *pReturn = NULL ) + { + return ExecuteFunction( hFunction, NULL, 0, pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1 ) + { + ScriptVariant_t args[1]; args[0] = arg1; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2 ) + { + ScriptVariant_t args[2]; args[0] = arg1; args[1] = arg2; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3 ) + { + ScriptVariant_t args[3]; args[0] = arg1; args[1] = arg2; args[2] = arg3; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4 ) + { + ScriptVariant_t args[4]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5 ) + { + ScriptVariant_t args[5]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6 ) + { + ScriptVariant_t args[6]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7 ) + { + ScriptVariant_t args[7]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8 ) + { + ScriptVariant_t args[8]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9 ) + { + ScriptVariant_t args[9]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10 ) + { + ScriptVariant_t args[10]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11 ) + { + ScriptVariant_t args[11]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12 ) + { + ScriptVariant_t args[12]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13 ) + { + ScriptVariant_t args[13]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13, ARG_TYPE_14 arg14 ) + { + ScriptVariant_t args[14]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; args[13] = arg14; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + +}; + + +//----------------------------------------------------------------------------- +// Script scope helper class +//----------------------------------------------------------------------------- + +class CDefScriptScopeBase +{ +public: + static IScriptVM *GetVM() + { + extern IScriptVM *g_pScriptVM; + return g_pScriptVM; + } +}; + +template +class CScriptScopeT : public CDefScriptScopeBase +{ +public: + CScriptScopeT() : + m_hScope( INVALID_HSCRIPT ), + m_flags( 0 ) + { + } + + ~CScriptScopeT() + { + Term(); + } + + bool IsInitialized() + { + return m_hScope != INVALID_HSCRIPT; + } + + bool Init( const char *pszName ) + { + m_hScope = GetVM()->CreateScope( pszName ); + return ( m_hScope != NULL ); + } + + bool Init( HSCRIPT hScope, bool bExternal = true ) + { + if ( bExternal ) + { + m_flags |= EXTERNAL; + } + m_hScope = hScope; + return ( m_hScope != NULL ); + } + + bool InitGlobal() + { + Assert( 0 ); // todo [3/24/2008 tom] + m_hScope = GetVM()->CreateScope( "" ); + return ( m_hScope != NULL ); + } + + void Term() + { + if ( m_hScope != INVALID_HSCRIPT ) + { + IScriptVM *pVM = GetVM(); + if ( pVM ) + { + for ( int i = 0; i < m_FuncHandles.Count(); i++ ) + { + pVM->ReleaseFunction( *m_FuncHandles[i] ); + } + } + m_FuncHandles.Purge(); + if ( m_hScope && pVM && !(m_flags & EXTERNAL) ) + { + pVM->ReleaseScope( m_hScope ); + } + m_hScope = INVALID_HSCRIPT; + } + m_flags = 0; + } + + void InvalidateCachedValues() + { + IScriptVM *pVM = GetVM(); + for ( int i = 0; i < m_FuncHandles.Count(); i++ ) + { + if ( *m_FuncHandles[i] ) + pVM->ReleaseFunction( *m_FuncHandles[i] ); + *m_FuncHandles[i] = INVALID_HSCRIPT; + } + m_FuncHandles.RemoveAll(); + } + + operator HSCRIPT() + { + return ( m_hScope != INVALID_HSCRIPT ) ? m_hScope : NULL; + } + + bool ValueExists( const char *pszKey ) { return GetVM()->ValueExists( m_hScope, pszKey ); } + bool SetValue( const char *pszKey, const ScriptVariant_t &value ) { return GetVM()->SetValue(m_hScope, pszKey, value ); } + bool GetValue( const char *pszKey, ScriptVariant_t *pValue ) { return GetVM()->GetValue(m_hScope, pszKey, pValue ); } + void ReleaseValue( ScriptVariant_t &value ) { GetVM()->ReleaseValue( value ); } + bool ClearValue( const char *pszKey) { return GetVM()->ClearValue( m_hScope, pszKey ); } + + ScriptStatus_t Run( HSCRIPT hScript ) + { + InvalidateCachedValues(); + return GetVM()->Run( hScript, m_hScope ); + } + + ScriptStatus_t Run( const char *pszScriptText, const char *pszScriptName = NULL ) + { + InvalidateCachedValues(); + HSCRIPT hScript = GetVM()->CompileScript( pszScriptText, pszScriptName ); + if ( hScript ) + { + ScriptStatus_t result = GetVM()->Run( hScript, m_hScope ); + GetVM()->ReleaseScript( hScript ); + return result; + } + return SCRIPT_ERROR; + } + + ScriptStatus_t Run( const unsigned char *pszScriptText, const char *pszScriptName = NULL ) + { + return Run( (const char *)pszScriptText, pszScriptName); + } + + HSCRIPT LookupFunction( const char *pszFunction ) + { + return GetVM()->LookupFunction( pszFunction, m_hScope ); + } + + void ReleaseFunction( HSCRIPT hScript ) + { + GetVM()->ReleaseFunction( hScript ); + } + + bool FunctionExists( const char *pszFunction ) + { + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + GetVM()->ReleaseFunction( hFunction ); + return ( hFunction != NULL ) ; + } + + //----------------------------------------------------- + + enum Flags_t + { + EXTERNAL = 0x01, + }; + + //----------------------------------------------------- + + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn = NULL ) + { + return GetVM()->ExecuteFunction( hFunction, NULL, 0, pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1 ) + { + ScriptVariant_t args[1]; args[0] = arg1; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2 ) + { + ScriptVariant_t args[2]; args[0] = arg1; args[1] = arg2; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3 ) + { + ScriptVariant_t args[3]; args[0] = arg1; args[1] = arg2; args[2] = arg3; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4 ) + { + ScriptVariant_t args[4]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5 ) + { + ScriptVariant_t args[5]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6 ) + { + ScriptVariant_t args[6]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7 ) + { + ScriptVariant_t args[7]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8 ) + { + ScriptVariant_t args[8]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9 ) + { + ScriptVariant_t args[9]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10 ) + { + ScriptVariant_t args[10]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11 ) + { + ScriptVariant_t args[11]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12 ) + { + ScriptVariant_t args[12]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13 ) + { + ScriptVariant_t args[13]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13, ARG_TYPE_14 arg14 ) + { + ScriptVariant_t args[14]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; args[13] = arg14; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn = NULL ) + { + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, NULL, 0, pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1 ) + { + ScriptVariant_t args[1]; args[0] = arg1; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2 ) + { + ScriptVariant_t args[2]; args[0] = arg1; args[1] = arg2; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3 ) + { + ScriptVariant_t args[3]; args[0] = arg1; args[1] = arg2; args[2] = arg3; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4 ) + { + ScriptVariant_t args[4]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5 ) + { + ScriptVariant_t args[5]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6 ) + { + ScriptVariant_t args[6]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7 ) + { + ScriptVariant_t args[7]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8 ) + { + ScriptVariant_t args[8]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9 ) + { + ScriptVariant_t args[9]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10 ) + { + ScriptVariant_t args[10]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11 ) + { + ScriptVariant_t args[11]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12 ) + { + ScriptVariant_t args[12]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13 ) + { + ScriptVariant_t args[13]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13, ARG_TYPE_14 arg14 ) + { + ScriptVariant_t args[14]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; args[13] = arg14; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + +protected: + HSCRIPT m_hScope; + int m_flags; + CUtlVectorConservative m_FuncHandles; +}; + +typedef CScriptScopeT<> CScriptScope; + +#define VScriptAddEnumToScope_( scope, enumVal, scriptName ) (scope).SetValue( scriptName, (int)enumVal ) +#define VScriptAddEnumToScope( scope, enumVal ) VScriptAddEnumToScope_( scope, enumVal, #enumVal ) + +#define VScriptAddEnumToRoot( enumVal ) g_pScriptVM->SetValue( #enumVal, (int)enumVal ) + +//----------------------------------------------------------------------------- +// Script function proxy support +//----------------------------------------------------------------------------- + +class CScriptFuncHolder +{ +public: + CScriptFuncHolder() : hFunction( INVALID_HSCRIPT ) {} + bool IsValid() { return ( hFunction != INVALID_HSCRIPT ); } + bool IsNull() { return ( !hFunction ); } + HSCRIPT hFunction; +}; + +#define DEFINE_SCRIPT_PROXY_GUTS( FuncName, N ) \ + CScriptFuncHolder m_hScriptFunc_##FuncName; \ + template < typename RET_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N> \ + bool FuncName( RET_TYPE *pRetVal FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + if ( !m_hScriptFunc_##FuncName.IsValid() ) \ + { \ + m_hScriptFunc_##FuncName.hFunction = LookupFunction( #FuncName ); \ + m_FuncHandles.AddToTail( &m_hScriptFunc_##FuncName.hFunction ); \ + } \ + \ + if ( !m_hScriptFunc_##FuncName.IsNull() ) \ + { \ + ScriptVariant_t returnVal; \ + ScriptStatus_t result = Call( m_hScriptFunc_##FuncName.hFunction, &returnVal, FUNC_CALL_ARGS_##N ); \ + if ( result != SCRIPT_ERROR ) \ + { \ + returnVal.AssignTo( pRetVal ); \ + returnVal.Free(); \ + return true; \ + } \ + } \ + return false; \ + } + +#define DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, N ) \ + CScriptFuncHolder m_hScriptFunc_##FuncName; \ + template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N> \ + bool FuncName( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \ + { \ + if ( !m_hScriptFunc_##FuncName.IsValid() ) \ + { \ + m_hScriptFunc_##FuncName.hFunction = LookupFunction( #FuncName ); \ + m_FuncHandles.AddToTail( &m_hScriptFunc_##FuncName.hFunction ); \ + } \ + \ + if ( !m_hScriptFunc_##FuncName.IsNull() ) \ + { \ + ScriptStatus_t result = Call( m_hScriptFunc_##FuncName.hFunction, NULL, FUNC_CALL_ARGS_##N ); \ + if ( result != SCRIPT_ERROR ) \ + { \ + return true; \ + } \ + } \ + return false; \ + } + +#define DEFINE_SCRIPT_PROXY_0V( FuncName ) \ + CScriptFuncHolder m_hScriptFunc_##FuncName; \ + bool FuncName() \ + { \ + if ( !m_hScriptFunc_##FuncName.IsValid() ) \ + { \ + m_hScriptFunc_##FuncName.hFunction = LookupFunction( #FuncName ); \ + m_FuncHandles.AddToTail( &m_hScriptFunc_##FuncName.hFunction ); \ + } \ + \ + if ( !m_hScriptFunc_##FuncName.IsNull() ) \ + { \ + ScriptStatus_t result = Call( m_hScriptFunc_##FuncName.hFunction, NULL ); \ + if ( result != SCRIPT_ERROR ) \ + { \ + return true; \ + } \ + } \ + return false; \ + } + +#define DEFINE_SCRIPT_PROXY_0( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 0 ) +#define DEFINE_SCRIPT_PROXY_1( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 1 ) +#define DEFINE_SCRIPT_PROXY_2( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 2 ) +#define DEFINE_SCRIPT_PROXY_3( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 3 ) +#define DEFINE_SCRIPT_PROXY_4( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 4 ) +#define DEFINE_SCRIPT_PROXY_5( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 5 ) +#define DEFINE_SCRIPT_PROXY_6( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 6 ) +#define DEFINE_SCRIPT_PROXY_7( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 7 ) +#define DEFINE_SCRIPT_PROXY_8( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 8 ) +#define DEFINE_SCRIPT_PROXY_9( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 9 ) +#define DEFINE_SCRIPT_PROXY_10( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 10 ) +#define DEFINE_SCRIPT_PROXY_11( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 11 ) +#define DEFINE_SCRIPT_PROXY_12( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 12 ) +#define DEFINE_SCRIPT_PROXY_13( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 13 ) +#define DEFINE_SCRIPT_PROXY_14( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 14 ) + +#define DEFINE_SCRIPT_PROXY_1V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 1 ) +#define DEFINE_SCRIPT_PROXY_2V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 2 ) +#define DEFINE_SCRIPT_PROXY_3V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 3 ) +#define DEFINE_SCRIPT_PROXY_4V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 4 ) +#define DEFINE_SCRIPT_PROXY_5V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 5 ) +#define DEFINE_SCRIPT_PROXY_6V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 6 ) +#define DEFINE_SCRIPT_PROXY_7V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 7 ) +#define DEFINE_SCRIPT_PROXY_8V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 8 ) +#define DEFINE_SCRIPT_PROXY_9V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 9 ) +#define DEFINE_SCRIPT_PROXY_10V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 10 ) +#define DEFINE_SCRIPT_PROXY_11V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 11 ) +#define DEFINE_SCRIPT_PROXY_12V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 12 ) +#define DEFINE_SCRIPT_PROXY_13V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 13 ) +#define DEFINE_SCRIPT_PROXY_14V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 14 ) + +//----------------------------------------------------------------------------- + +#include "tier0/memdbgoff.h" + +#endif // IVSCRIPT_H diff --git a/public/vscript/vscript_templates.h b/public/vscript/vscript_templates.h new file mode 100644 index 00000000..358210c1 --- /dev/null +++ b/public/vscript/vscript_templates.h @@ -0,0 +1,414 @@ +//========== Copyright © 2008, Valve Corporation, All rights reserved. ======== +// +// Purpose: +// +//============================================================================= + +#ifndef VSCRIPT_TEMPLATES_H +#define VSCRIPT_TEMPLATES_H + +#include "tier0/basetypes.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +#define FUNC_APPEND_PARAMS_0 +#define FUNC_APPEND_PARAMS_1 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 1 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); +#define FUNC_APPEND_PARAMS_2 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 2 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); +#define FUNC_APPEND_PARAMS_3 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 3 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); +#define FUNC_APPEND_PARAMS_4 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 4 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); +#define FUNC_APPEND_PARAMS_5 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 5 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); +#define FUNC_APPEND_PARAMS_6 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 6 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); +#define FUNC_APPEND_PARAMS_7 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 7 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); +#define FUNC_APPEND_PARAMS_8 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 8 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); +#define FUNC_APPEND_PARAMS_9 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 9 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); +#define FUNC_APPEND_PARAMS_10 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 10 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); +#define FUNC_APPEND_PARAMS_11 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 11 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); +#define FUNC_APPEND_PARAMS_12 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 12 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); +#define FUNC_APPEND_PARAMS_13 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 13 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) ); +#define FUNC_APPEND_PARAMS_14 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 14 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_14 ) ); + +#define DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER(N) \ + template \ + inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \ + FUNC_APPEND_PARAMS_##N \ + } + +FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER ); + +#define DEFINE_MEMBER_FUNC_TYPE_DEDUCER(N) \ + template \ + inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \ + FUNC_APPEND_PARAMS_##N \ + } + +FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER ); + +//------------------------------------- + +#define DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER(N) \ + template \ + inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \ + { \ + pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \ + FUNC_APPEND_PARAMS_##N \ + } + +FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER ); + +#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); } + +#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); } +#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func ) +#define ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, scriptName ) ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) +#define ScriptInitMemberFuncDescriptor( pDesc, class, func ) ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, #func ) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +template +inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) +{ + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) ) + { + union FuncPtrConvert + { + void *p; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvert convert; + convert.pFunc = pFunc; + return convert.p; + } +#if defined( COMPILER_MSVC ) + else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.pFunc = pFunc; + if ( convert.mfp.m_delta == 0 ) + { + return convert.mfp.p; + } + AssertMsg( 0, "Function pointer must be from primary vtable" ); + } + else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + int m_vtordisp; + int m_vtable_index; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.pFunc = pFunc; + if ( convert.mfp.m_delta == 0 ) + { + return convert.mfp.p; + } + AssertMsg( 0, "Function pointer must be from primary vtable" ); + } +#elif defined( GNUC ) + else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) + { + AssertMsg( 0, "Note: This path has not been verified yet. See comments below in #else case." ); + + struct GnuMFP + { + union + { + void *funcadr; // If vtable_index_2 is even, then this is the function pointer. + int vtable_index_2; // If vtable_index_2 is odd, then this = vindex*2+1. + }; + int delta; + }; + + GnuMFP *p = (GnuMFP*)&pFunc; + if ( p->vtable_index_2 & 1 ) + { + char **delta = (char**)p->delta; + char *pCur = *delta + (p->vtable_index_2+1)/2; + return (void*)( pCur + 4 ); + } + else + { + return p->funcadr; + } + } +#else +#error "Need to implement code to crack non-offset member function pointer case" + // For gcc, see: http://www.codeproject.com/KB/cpp/FastDelegate.aspx + // + // Current versions of the GNU compiler use a strange and tricky + // optimization. It observes that, for virtual inheritance, you have to look + // up the vtable in order to get the voffset required to calculate the this + // pointer. While you're doing that, you might as well store the function + // pointer in the vtable. By doing this, they combine the m_func_address and + // m_vtable_index fields into one, and they distinguish between them by + // ensuring that function pointers always point to even addresses but vtable + // indices are always odd: + // + // // GNU g++ uses a tricky space optimisation, also adopted by IBM's VisualAge and XLC. + // struct GnuMFP { + // union { + // CODEPTR funcadr; // always even + // int vtable_index_2; // = vindex*2+1, always odd + // }; + // int delta; + // }; + // adjustedthis = this + delta + // if (funcadr & 1) CALL (* ( *delta + (vindex+1)/2) + 4) + // else CALL funcadr + // + // The G++ method is well documented, so it has been adopted by many other + // vendors, including IBM's VisualAge and XLC compilers, recent versions of + // Open64, Pathscale EKO, and Metrowerks' 64-bit compilers. A simpler scheme + // used by earlier versions of GCC is also very common. SGI's now + // discontinued MIPSPro and Pro64 compilers, and Apple's ancient MrCpp + // compiler used this method. (Note that the Pro64 compiler has become the + // open source Open64 compiler). + +#endif + else + AssertMsg( 0, "Member function pointer not supported. Why on earth are you using virtual inheritance!?" ); + return NULL; +} + +template +inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) +{ + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) ) + { + union FuncPtrConvert + { + void *p; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvert convert; + convert.p = p; + return convert.pFunc; + } + +#if defined( COMPILER_MSVC ) + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.mfp.p = p; + convert.mfp.m_delta = 0; + return convert.pFunc; + } + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + int m_vtordisp; + int m_vtable_index; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.mfp.p = p; + convert.mfp.m_delta = 0; + return convert.pFunc; + } +#elif defined( POSIX ) + AssertMsg( 0, "Note: This path has not been implemented yet." ); +#else +#error "Need to implement code to crack non-offset member function pointer case" +#endif + Assert( 0 ); + return NULL; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_0 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_1 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_1 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_2 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_2 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_3 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_3 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_4 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_4 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_5 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_5 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_6 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_6 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_7 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_7 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_8 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_8 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_9 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_9 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_10 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_10 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_11 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_11 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_12 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_12 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_13 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_13 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_14 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_14 + +#define SCRIPT_BINDING_ARGS_0 +#define SCRIPT_BINDING_ARGS_1 pArguments[0] +#define SCRIPT_BINDING_ARGS_2 pArguments[0], pArguments[1] +#define SCRIPT_BINDING_ARGS_3 pArguments[0], pArguments[1], pArguments[2] +#define SCRIPT_BINDING_ARGS_4 pArguments[0], pArguments[1], pArguments[2], pArguments[3] +#define SCRIPT_BINDING_ARGS_5 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4] +#define SCRIPT_BINDING_ARGS_6 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5] +#define SCRIPT_BINDING_ARGS_7 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6] +#define SCRIPT_BINDING_ARGS_8 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7] +#define SCRIPT_BINDING_ARGS_9 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8] +#define SCRIPT_BINDING_ARGS_10 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9] +#define SCRIPT_BINDING_ARGS_11 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10] +#define SCRIPT_BINDING_ARGS_12 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11] +#define SCRIPT_BINDING_ARGS_13 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12] +#define SCRIPT_BINDING_ARGS_14 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12], pArguments[13] + + +#define DEFINE_SCRIPT_BINDINGS(N) \ + template \ + class CNonMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( pReturn ); \ + Assert( !pContext ); \ + \ + if ( nArguments != N || !pReturn || pContext ) \ + { \ + return false; \ + } \ + *pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \ + if ( pReturn->m_type == FIELD_VECTOR ) \ + pReturn->m_pVector = new Vector(*pReturn->m_pVector); \ + return true; \ + } \ + }; \ + \ + template \ + class CNonMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( !pReturn ); \ + Assert( !pContext ); \ + \ + if ( nArguments != N || pReturn || pContext ) \ + { \ + return false; \ + } \ + ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \ + return true; \ + } \ + }; \ + \ + template \ + class CMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( pReturn ); \ + Assert( pContext ); \ + \ + if ( nArguments != N || !pReturn || !pContext ) \ + { \ + return false; \ + } \ + *pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid(pFunction))( SCRIPT_BINDING_ARGS_##N ); \ + if ( pReturn->m_type == FIELD_VECTOR ) \ + pReturn->m_pVector = new Vector(*pReturn->m_pVector); \ + return true; \ + } \ + }; \ + \ + template \ + class CMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( !pReturn ); \ + Assert( pContext ); \ + \ + if ( nArguments != N || pReturn || !pContext ) \ + { \ + return false; \ + } \ + (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid(pFunction))( SCRIPT_BINDING_ARGS_##N ); \ + return true; \ + } \ + }; \ + \ + template \ + inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ + return &CNonMemberScriptBinding##N::Call; \ + } \ + \ + template \ + inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ + return &CMemberScriptBinding##N::Call; \ + } \ + \ + template \ + inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \ + { \ + typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ + return &CMemberScriptBinding##N::Call; \ + } + +FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS ); + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#endif // VSCRIPT_TEMPLATES_H diff --git a/public/vstdlib/jobthread.h b/public/vstdlib/jobthread.h index 89868323..33a4ab51 100644 --- a/public/vstdlib/jobthread.h +++ b/public/vstdlib/jobthread.h @@ -979,7 +979,7 @@ public: m_szDescription = pszDescription; } - void Run( long lBegin, long nItems, int nMaxParallel = INT_MAX ) + void Run( int32_t lBegin, int32_t nItems, int nMaxParallel = INT_MAX ) { if ( nItems ) { @@ -1015,11 +1015,11 @@ private: { m_ItemProcessor.Begin(); - long lLimit = m_lLimit; + int32_t lLimit = m_lLimit; for (;;) { - long lIndex = m_lIndex ++; + int32_t lIndex = m_lIndex ++; if ( lIndex < lLimit ) { m_ItemProcessor.Process( lIndex ); @@ -1035,23 +1035,23 @@ private: --m_nActive; } CInterlockedInt m_lIndex; - long m_lLimit; + int32_t m_lLimit; CInterlockedInt m_nActive; const char * m_szDescription; }; -inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, void (*pfnProcess)( long const & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +inline void ParallelLoopProcess( const char *szDescription, int32_t lBegin, unsigned nItems, void (*pfnProcess)( int32_t const & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) { - CParallelLoopProcessor< CFuncJobItemProcessor< long const > > processor( szDescription ); + CParallelLoopProcessor< CFuncJobItemProcessor< int32_t const > > processor( szDescription ); processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); processor.Run( lBegin, nItems, nMaxParallel ); } template < typename OBJECT_TYPE, typename FUNCTION_CLASS > -inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( long const & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +inline void ParallelLoopProcess( const char *szDescription, int32_t lBegin, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( long const & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) { - CParallelLoopProcessor< CMemberFuncJobItemProcessor > processor( szDescription ); + CParallelLoopProcessor< CMemberFuncJobItemProcessor > processor( szDescription ); processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd ); processor.Run( lBegin, nItems, nMaxParallel ); } diff --git a/public/vstdlib/random.h b/public/vstdlib/random.h index cace9fa9..6ce4a40f 100644 --- a/public/vstdlib/random.h +++ b/public/vstdlib/random.h @@ -24,7 +24,7 @@ //----------------------------------------------------------------------------- // A generator of uniformly distributed random numbers //----------------------------------------------------------------------------- -class IUniformRandomStream +class VSTDLIB_CLASS IUniformRandomStream { public: // Sets the seed of the random number generator diff --git a/tier1/AMBuilder b/tier1/AMBuilder new file mode 100644 index 00000000..3ee9d191 --- /dev/null +++ b/tier1/AMBuilder @@ -0,0 +1,48 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys + +builder.SetBuildFolder('/') + +project = builder.StaticLibraryProject('tier1') + +project.sources = [ + 'bitbuf.cpp', + 'byteswap.cpp', + 'characterset.cpp', + 'checksum_crc.cpp', + 'checksum_md5.cpp', + 'commandbuffer.cpp', + 'convar.cpp', + 'datamanager.cpp', + 'diff.cpp', + 'generichash.cpp', + 'interface.cpp', + 'KeyValues.cpp', + 'mempool.cpp', + 'memstack.cpp', + 'NetAdr.cpp', + 'newbitbuf.cpp', + 'processor_detect.cpp', + 'rangecheckedvar.cpp', + 'stringpool.cpp', + 'strtools.cpp', + 'tier1.cpp', + 'undiff.cpp', + 'uniqueid.cpp', + 'utlbuffer.cpp', + 'utlbufferutil.cpp', + 'utlstring.cpp', + 'utlsymbol.cpp' +] + +for cxx in HL2SDK.targets: + binary = HL2SDK.ConfigureLibrary(project, cxx, builder) + compiler = binary.compiler + + compiler.cxxincludes += [ + os.path.join(builder.currentSourcePath, '..', 'public'), + os.path.join(builder.currentSourcePath, '..', 'public', 'tier0'), + os.path.join(builder.currentSourcePath, '..', 'public', 'tier1') + ] + +HL2SDK.libs += builder.Add(project) \ No newline at end of file diff --git a/tier1/KeyValues.cpp b/tier1/KeyValues.cpp index 897d53c0..ddd9d010 100644 --- a/tier1/KeyValues.cpp +++ b/tier1/KeyValues.cpp @@ -229,12 +229,12 @@ class CKeyValuesGrowableStringTable public: // Constructor CKeyValuesGrowableStringTable() : + m_hashLookup( 2048, 0, 0, m_Functor, m_Functor ), #ifdef PLATFORM_64BITS m_vecStrings( 0, 4 * 512 * 1024 ) #else m_vecStrings( 0, 512 * 1024 ) #endif - , m_hashLookup( 2048, 0, 0, m_Functor, m_Functor ) { m_vecStrings.AddToTail( '\0' ); } @@ -1465,14 +1465,14 @@ const wchar_t *KeyValues::GetWString( const char *keyName, const wchar_t *defaul bool KeyValues::GetBool( const char *keyName, bool defaultValue, bool* optGotDefault ) { if ( FindKey( keyName ) ) - { - if ( optGotDefault ) - (*optGotDefault) = false; + { + if ( optGotDefault ) + (*optGotDefault) = false; return 0 != GetInt( keyName, 0 ); - } + } - if ( optGotDefault ) - (*optGotDefault) = true; + if ( optGotDefault ) + (*optGotDefault) = true; return defaultValue; } @@ -2371,7 +2371,7 @@ void KeyValues::RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &b int ival = strtol( value, &pIEnd, 10 ); float fval = (float)strtod( value, &pFEnd ); - bool bOverflow = ( ival == LONG_MAX || ival == LONG_MIN ) && errno == ERANGE; + //bool bOverflow = ( ival == LONG_MAX || ival == LONG_MIN ) && errno == ERANGE; #ifdef POSIX // strtod supports hex representation in strings under posix but we DON'T // want that support in keyvalues, so undo it here if needed @@ -2409,7 +2409,7 @@ void KeyValues::RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &b dat->m_flValue = fval; dat->m_iDataType = TYPE_FLOAT; } - else if (pIEnd == pSEnd && !bOverflow) + else if (pIEnd == pSEnd) //&& !bOverflow) { dat->m_iValue = ival; dat->m_iDataType = TYPE_INT; @@ -2540,7 +2540,7 @@ bool KeyValues::WriteAsBinary( CUtlBuffer &buffer ) } case TYPE_PTR: { - buffer.PutUnsignedInt( (int)dat->m_pValue ); + buffer.PutPtr( dat->m_pValue ); } default: @@ -2644,7 +2644,7 @@ bool KeyValues::ReadAsBinary( CUtlBuffer &buffer, int nStackDepth ) } case TYPE_PTR: { - dat->m_pValue = (void*)buffer.GetUnsignedInt(); + dat->m_pValue = buffer.GetPtr(); } default: @@ -2882,14 +2882,16 @@ bool KeyValues::Dump( IKeyValuesDumpContext *pDump, int nIndentLevel /* = 0 */ ) return false; // Dump values - for ( KeyValues *val = this ? GetFirstValue() : NULL; val; val = val->GetNextValue() ) + KeyValues *val = this; + for ( val = val ? GetFirstValue() : val; val; val = val->GetNextValue() ) { if ( !pDump->KvWriteValue( val, nIndentLevel + 1 ) ) return false; } // Dump subkeys - for ( KeyValues *sub = this ? GetFirstTrueSubKey() : NULL; sub; sub = sub->GetNextTrueSubKey() ) + KeyValues *sub = this; + for ( sub = sub ? GetFirstTrueSubKey() : sub; sub; sub = sub->GetNextTrueSubKey() ) { if ( !sub->Dump( pDump, nIndentLevel + 1 ) ) return false; @@ -3054,4 +3056,4 @@ bool CKeyValuesDumpContextAsDevMsg::KvWriteText( char const *szText ) Msg( "%s", szText ); } return true; -} \ No newline at end of file +} diff --git a/tier1/NetAdr.cpp b/tier1/NetAdr.cpp index 78657a5d..e7ad6aa1 100644 --- a/tier1/NetAdr.cpp +++ b/tier1/NetAdr.cpp @@ -184,12 +184,12 @@ unsigned int netadr_t::GetIP() const return *(unsigned int *)&ip;; } -unsigned long netadr_t::addr_ntohl() const +uint32_t netadr_t::addr_ntohl() const { return ntohl( GetIP() ); } -unsigned long netadr_t::addr_htonl() const +uint32_t netadr_t::addr_htonl() const { return htonl( GetIP() ); } diff --git a/tier1/bitbuf.cpp b/tier1/bitbuf.cpp index f49f5ea0..fc930920 100644 --- a/tier1/bitbuf.cpp +++ b/tier1/bitbuf.cpp @@ -86,10 +86,10 @@ void SetBitBufErrorHandler( BitBufErrorHandler fn ) // Precalculated bit masks for WriteUBitLong. Using these tables instead of // doing the calculations gives a 33% speedup in WriteUBitLong. -unsigned long g_BitWriteMasks[32][33]; +uint32_t g_BitWriteMasks[32][33]; // (1 << i) - 1 -unsigned long g_ExtraMasks[32]; +uint32_t g_ExtraMasks[32]; class CBitWriteMasksInit { @@ -147,7 +147,7 @@ void old_bf_write::StartWriting( void *pData, int nBytes, int iStartBit, int nBi { // Make sure it's dword aligned and padded. Assert( (nBytes % 4) == 0 ); - Assert(((unsigned long)pData & 3) == 0); + Assert(((uint32_t)pData & 3) == 0); // The writing code will overrun the end of the buffer if it isn't dword aligned, so truncate to force alignment nBytes &= ~3; @@ -331,7 +331,7 @@ bool old_bf_write::WriteBits(const void *pInData, int nBits) } // Align output to dword boundary - while (((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8) + while (((uintptr_t)pOut & 3) != 0 && nBitsLeft >= 8) { WriteUBitLong( *pOut, 8, false ); @@ -354,18 +354,18 @@ bool old_bf_write::WriteBits(const void *pInData, int nBits) // X360TBD: Can't write dwords in WriteBits because they'll get swapped if ( IsPC() && nBitsLeft >= 32 ) { - unsigned long iBitsRight = (m_iCurBit & 31); - unsigned long iBitsLeft = 32 - iBitsRight; - unsigned long bitMaskLeft = g_BitWriteMasks[iBitsRight][32]; - unsigned long bitMaskRight = g_BitWriteMasks[0][iBitsRight]; + uint32_t iBitsRight = (m_iCurBit & 31); + uint32_t iBitsLeft = 32 - iBitsRight; + uint32_t bitMaskLeft = g_BitWriteMasks[iBitsRight][32]; + uint32_t bitMaskRight = g_BitWriteMasks[0][iBitsRight]; - unsigned long *pData = &((unsigned long*)m_pData)[m_iCurBit>>5]; + uint32_t *pData = &((uint32_t*)m_pData)[m_iCurBit>>5]; // Read dwords. while(nBitsLeft >= 32) { - unsigned long curData = *(unsigned long*)pOut; - pOut += sizeof(unsigned long); + uint32_t curData = *(uint32_t*)pOut; + pOut += sizeof(uint32_t); *pData &= bitMaskLeft; *pData |= curData << iBitsRight; @@ -529,12 +529,12 @@ void old_bf_write::WriteBitCoord (const float f) void old_bf_write::WriteBitFloat(float val) { - long intVal; + int32_t intVal; - Assert(sizeof(long) == sizeof(float)); + Assert(sizeof(int32_t) == sizeof(float)); Assert(sizeof(float) == 4); - intVal = *((long*)&val); + intVal = *((int32_t*)&val); WriteUBitLong( intVal, 32 ); } @@ -623,9 +623,9 @@ void old_bf_write::WriteWord(int val) WriteUBitLong(val, sizeof(unsigned short) << 3); } -void old_bf_write::WriteLong(long val) +void old_bf_write::WriteLong(int32_t val) { - WriteSBitLong(val, sizeof(long) << 3); + WriteSBitLong(val, sizeof(int32_t) << 3); } void old_bf_write::WriteLongLong(int64 val) @@ -635,8 +635,8 @@ void old_bf_write::WriteLongLong(int64 val) // Insert the two DWORDS according to network endian const short endianIndex = 0x0100; byte *idx = (byte*)&endianIndex; - WriteUBitLong(pLongs[*idx++], sizeof(long) << 3); - WriteUBitLong(pLongs[*idx], sizeof(long) << 3); + WriteUBitLong(pLongs[*idx++], sizeof(int32_t) << 3); + WriteUBitLong(pLongs[*idx], sizeof(int32_t) << 3); } void old_bf_write::WriteFloat(float val) @@ -701,7 +701,7 @@ old_bf_read::old_bf_read( const char *pDebugName, const void *pData, int nBytes, void old_bf_read::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) { // Make sure we're dword aligned. - Assert(((unsigned long)pData & 3) == 0); + Assert(((uint32_t)pData & 3) == 0); m_pData = (unsigned char*)pData; m_nDataBytes = nBytes; @@ -768,7 +768,7 @@ void old_bf_read::ReadBits(void *pOutData, int nBits) // align output to dword boundary - while( ((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8 ) + while( ((uintptr_t)pOut & 3) != 0 && nBitsLeft >= 8 ) { *pOut = (unsigned char)ReadUBitLong(8); ++pOut; @@ -781,8 +781,8 @@ void old_bf_read::ReadBits(void *pOutData, int nBits) // read dwords while ( nBitsLeft >= 32 ) { - *((unsigned long*)pOut) = ReadUBitLong(32); - pOut += sizeof(unsigned long); + *((uint32_t*)pOut) = ReadUBitLong(32); + pOut += sizeof(uint32_t); nBitsLeft -= 32; } } @@ -867,7 +867,9 @@ int old_bf_read::ReadSBitLong( int numbits ) } const byte g_BitMask[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; +#if FAST_BIT_SCAN const byte g_TrailingMask[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; +#endif inline int old_bf_read::CountRunOfZeros() { @@ -1156,9 +1158,9 @@ int old_bf_read::ReadWord() return ReadUBitLong(sizeof(unsigned short) << 3); } -long old_bf_read::ReadLong() +int32_t old_bf_read::ReadLong() { - return ReadSBitLong(sizeof(long) << 3); + return ReadSBitLong(sizeof(int32_t) << 3); } int64 old_bf_read::ReadLongLong() @@ -1169,8 +1171,8 @@ int64 old_bf_read::ReadLongLong() // Read the two DWORDs according to network endian const short endianIndex = 0x0100; byte *idx = (byte*)&endianIndex; - pLongs[*idx++] = ReadUBitLong(sizeof(long) << 3); - pLongs[*idx] = ReadUBitLong(sizeof(long) << 3); + pLongs[*idx++] = ReadUBitLong(sizeof(uint32_t) << 3); + pLongs[*idx] = ReadUBitLong(sizeof(uint32_t) << 3); return retval; } diff --git a/tier1/checksum_crc.cpp b/tier1/checksum_crc.cpp index 3e0f20d4..740de4cd 100644 --- a/tier1/checksum_crc.cpp +++ b/tier1/checksum_crc.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Generic CRC functions // @@ -147,7 +147,7 @@ JustAfew: // The low-order two bits of pb and nBuffer in total control the // upfront work. // - nFront = ((unsigned int)pb) & 3; + nFront = ((uintp)pb) & 3; nBuffer -= nFront; switch (nFront) { diff --git a/tier1/checksum_md5.cpp b/tier1/checksum_md5.cpp index 0c4aeefa..727abb05 100644 --- a/tier1/checksum_md5.cpp +++ b/tier1/checksum_md5.cpp @@ -36,7 +36,7 @@ //----------------------------------------------------------------------------- static void MD5Transform(unsigned int buf[4], unsigned int const in[16]) { - register unsigned int a, b, c, d; + unsigned int a, b, c, d; a = buf[0]; b = buf[1]; diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 5b693937..fe6f09d1 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -24,9 +24,10 @@ #endif #include "tier0/memdbgon.h" - +#ifndef NDEBUG // Comment this out when we release. -//#define ALLOW_DEVELOPMENT_CVARS +#define ALLOW_DEVELOPMENT_CVARS +#endif @@ -78,6 +79,7 @@ void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor ) pCur = pNext; } + g_pCVar->ProcessQueuedMaterialThreadConVarSets(); ConCommandBase::s_pConCommandBases = NULL; } @@ -114,7 +116,7 @@ ConCommandBase::ConCommandBase( void ) //----------------------------------------------------------------------------- ConCommandBase::ConCommandBase( const char *pName, const char *pHelpString /*=0*/, int flags /*= 0*/ ) { - Create( pName, pHelpString, flags ); + CreateBase( pName, pHelpString, flags ); } //----------------------------------------------------------------------------- @@ -151,16 +153,14 @@ CVarDLLIdentifier_t ConCommandBase::GetDLLIdentifier() const // *pHelpString - // flags - //----------------------------------------------------------------------------- -void ConCommandBase::Create( const char *pName, const char *pHelpString /*= 0*/, int flags /*= 0*/ ) +void ConCommandBase::CreateBase( const char *pName, const char *pHelpString /*= 0*/, int flags /*= 0*/ ) { - static const char *empty_string = ""; - m_bRegistered = false; // Name should be static data Assert( pName ); m_pszName = pName; - m_pszHelpString = pHelpString ? pHelpString : empty_string; + m_pszHelpString = pHelpString ? pHelpString : ""; m_nFlags = flags; @@ -267,7 +267,7 @@ char *ConCommandBase::CopyString( const char *from ) int len; char *to; - len = strlen( from ); + len = V_strlen( from ); if ( len <= 0 ) { to = new char[1]; @@ -505,7 +505,7 @@ int DefaultCompletionFunc( const char *partial, char commands[ COMMAND_COMPLETIO // m_bIsNewConCommand = true; //} -ConCommand::ConCommand( const char *pName, FnCommandCallbackV1_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +ConCommand::ConCommand( const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { // Set the callback m_fnCommandCallbackV1 = callback; @@ -515,7 +515,7 @@ ConCommand::ConCommand( const char *pName, FnCommandCallbackV1_t callback, const m_bHasCompletionCallback = completionFunc != 0 ? true : false; // Setup the rest - BaseClass::Create( pName, pHelpString, flags ); + BaseClass::CreateBase( pName, pHelpString, flags ); } ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) @@ -528,7 +528,7 @@ ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const c m_bUsingCommandCallbackInterface = false; // Setup the rest - BaseClass::Create( pName, pHelpString, flags ); + BaseClass::CreateBase( pName, pHelpString, flags ); } ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) @@ -541,7 +541,7 @@ ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const ch m_bUsingCommandCallbackInterface = true; // Setup the rest - BaseClass::Create( pName, pHelpString, flags ); + BaseClass::CreateBase( pName, pHelpString, flags ); } //----------------------------------------------------------------------------- @@ -592,7 +592,7 @@ void ConCommand::Dispatch( const CCommand &command ) } // Command without callback!!! - AssertMsg( 0, ( "Encountered ConCommand without a callback!\n" ) ); + AssertMsg( 0, "Encountered ConCommand '%s' without a callback!\n", GetName() ); } @@ -749,6 +749,15 @@ void ConVar::Init() //----------------------------------------------------------------------------- void ConVar::InternalSetValue( const char *value ) { + if ( IsFlagSet( FCVAR_MATERIAL_THREAD_MASK ) ) + { + if ( g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed() ) + { + g_pCVar->QueueMaterialThreadSetValue( this, value ); + return; + } + } + float fNewValue; char tempVal[ 32 ]; char *val; @@ -758,17 +767,20 @@ void ConVar::InternalSetValue( const char *value ) float flOldValue = m_fValue; val = (char *)value; - fNewValue = ( float )atof( value ); + if ( !value ) + fNewValue = 0.0f; + else + fNewValue = ( float )atof( value ); if ( ClampValue( fNewValue ) ) { Q_snprintf( tempVal,sizeof(tempVal), "%f", fNewValue ); val = tempVal; } - + // Redetermine value m_fValue = fNewValue; - m_nValue = ( int )( m_fValue ); + m_nValue = ( int )( fNewValue ); if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) { @@ -787,28 +799,39 @@ void ConVar::ChangeStringValue( const char *tempVal, float flOldValue ) char* pszOldValue = (char*)stackalloc( m_StringLength ); memcpy( pszOldValue, m_pszString, m_StringLength ); - int len = Q_strlen(tempVal) + 1; - - if ( len > m_StringLength) + if ( tempVal ) { - if (m_pszString) + int len = Q_strlen(tempVal) + 1; + + if ( len > m_StringLength) { - delete[] m_pszString; + if (m_pszString) + { + delete[] m_pszString; + } + + m_pszString = new char[len]; + m_StringLength = len; } - m_pszString = new char[len]; - m_StringLength = len; + memcpy( m_pszString, tempVal, len ); } - - memcpy( m_pszString, tempVal, len ); - - // Invoke any necessary callback function - if ( m_fnChangeCallback ) + else { - m_fnChangeCallback( this, pszOldValue, flOldValue ); + *m_pszString = 0; } - g_pCVar->CallGlobalChangeCallbacks( this, pszOldValue, flOldValue ); + // If nothing has changed, don't do the callbacks. + if (V_strcmp(pszOldValue, m_pszString) != 0) + { + // Invoke any necessary callback function + if ( m_fnChangeCallback ) + { + m_fnChangeCallback( this, pszOldValue, flOldValue ); + } + + g_pCVar->CallGlobalChangeCallbacks( this, pszOldValue, flOldValue ); + } stackfree( pszOldValue ); } @@ -839,11 +862,20 @@ bool ConVar::ClampValue( float& value ) // Purpose: // Input : *value - //----------------------------------------------------------------------------- -void ConVar::InternalSetFloatValue( float fNewValue ) +void ConVar::InternalSetFloatValue( float fNewValue, bool bForce /*= false */ ) { - if ( fNewValue == m_fValue ) + if ( fNewValue == m_fValue && !bForce ) return; + if ( IsFlagSet( FCVAR_MATERIAL_THREAD_MASK ) ) + { + if ( g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed() ) + { + g_pCVar->QueueMaterialThreadSetValue( this, fNewValue ); + return; + } + } + Assert( m_pParent == this ); // Only valid for root convars. // Check bounds @@ -875,6 +907,15 @@ void ConVar::InternalSetIntValue( int nValue ) if ( nValue == m_nValue ) return; + if ( IsFlagSet( FCVAR_MATERIAL_THREAD_MASK ) ) + { + if ( g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed() ) + { + g_pCVar->QueueMaterialThreadSetValue( this, nValue ); + return; + } + } + Assert( m_pParent == this ); // Only valid for root convars. float fValue = (float)nValue; @@ -907,15 +948,12 @@ void ConVar::Create( const char *pName, const char *pDefaultValue, int flags /*= const char *pHelpString /*= NULL*/, bool bMin /*= false*/, float fMin /*= 0.0*/, bool bMax /*= false*/, float fMax /*= false*/, FnChangeCallback_t callback /*= NULL*/ ) { - static const char *empty_string = ""; - m_pParent = this; // Name should be static data - m_pszDefaultValue = pDefaultValue ? pDefaultValue : empty_string; - Assert( m_pszDefaultValue ); + SetDefault( pDefaultValue ); - m_StringLength = strlen( m_pszDefaultValue ) + 1; + m_StringLength = V_strlen( m_pszDefaultValue ) + 1; m_pszString = new char[m_StringLength]; memcpy( m_pszString, m_pszDefaultValue, m_StringLength ); @@ -923,10 +961,19 @@ void ConVar::Create( const char *pName, const char *pDefaultValue, int flags /*= m_fMinVal = fMin; m_bHasMax = bMax; m_fMaxVal = fMax; + + // AM stubbed out just enough for ABI compat + m_bHasCompMin = false; + m_fCompMinVal = 0.0; + m_bHasCompMax = false; + m_fCompMaxVal = 0.0; + m_bCompetitiveRestrictions = false; + // m_fnChangeCallback = callback; m_fValue = ( float )atof( m_pszString ); + m_nValue = atoi( m_pszString ); // dont convert from float to int and lose bits // Bounds Check, should never happen, if it does, no big deal if ( m_bHasMin && ( m_fValue < m_fMinVal ) ) @@ -939,9 +986,7 @@ void ConVar::Create( const char *pName, const char *pDefaultValue, int flags /*= Assert( 0 ); } - m_nValue = ( int )m_fValue; - - BaseClass::Create( pName, pHelpString, flags ); + BaseClass::CreateBase( pName, pHelpString, flags ); } //----------------------------------------------------------------------------- @@ -1014,6 +1059,11 @@ const char *ConVar::GetDefault( void ) const return m_pParent->m_pszDefaultValue; } +void ConVar::SetDefault( const char *pszDefault ) +{ + m_pszDefaultValue = pszDefault ? pszDefault : ""; + Assert( m_pszDefaultValue ); +} //----------------------------------------------------------------------------- // This version is simply used to make reading convars simpler. diff --git a/tier1/datamanager.cpp b/tier1/datamanager.cpp index fd3ddf1a..33c74665 100644 --- a/tier1/datamanager.cpp +++ b/tier1/datamanager.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -9,8 +9,6 @@ #include "basetypes.h" #include "datamanager.h" -DECLARE_POINTER_HANDLE( memhandle_t ); - #define AUTO_LOCK_DM() AUTO_LOCK_( CDataManagerBase, *this ) CDataManagerBase::CDataManagerBase( unsigned int maxSize ) @@ -320,7 +318,7 @@ memhandle_t CDataManagerBase::ToHandle( unsigned short index ) unsigned int hiword = m_memoryLists.Element(index).serial; hiword <<= 16; index++; - return (memhandle_t)( hiword|index ); + return memhandle_t::MakeHandle( hiword|index ); } unsigned int CDataManagerBase::TargetSize() diff --git a/tier1/generichash.cpp b/tier1/generichash.cpp index af784fc4..48f62c51 100644 --- a/tier1/generichash.cpp +++ b/tier1/generichash.cpp @@ -137,12 +137,12 @@ unsigned FASTCALL HashStringCaselessConventional( const char *pszKey ) //----------------------------------------------------------------------------- unsigned FASTCALL HashInt( const int n ) { - register unsigned even, odd; + unsigned even, odd; even = g_nRandomValues[n & 0xff]; odd = g_nRandomValues[((n >> 8) & 0xff)]; even = g_nRandomValues[odd ^ (n >> 24)]; - odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; odd = g_nRandomValues[even ^ (n & 0xff)]; @@ -154,16 +154,16 @@ unsigned FASTCALL HashInt( const int n ) //----------------------------------------------------------------------------- unsigned FASTCALL Hash4( const void *pKey ) { - register const uint32 * p = (const uint32 *) pKey; - register unsigned even, - odd, - n; + const uint32 * p = (const uint32 *) pKey; + unsigned even, + odd, + n; n = *p; even = g_nRandomValues[n & 0xff]; odd = g_nRandomValues[((n >> 8) & 0xff)]; even = g_nRandomValues[odd ^ (n >> 24)]; - odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; odd = g_nRandomValues[even ^ (n & 0xff)]; @@ -176,16 +176,16 @@ unsigned FASTCALL Hash4( const void *pKey ) //----------------------------------------------------------------------------- unsigned FASTCALL Hash8( const void *pKey ) { - register const uint32 * p = (const uint32 *) pKey; - register unsigned even, - odd, - n; + const uint32 * p = (const uint32 *) pKey; + unsigned even, + odd, + n; n = *p; even = g_nRandomValues[n & 0xff]; odd = g_nRandomValues[((n >> 8) & 0xff)]; even = g_nRandomValues[odd ^ (n >> 24)]; - odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; odd = g_nRandomValues[even ^ (n & 0xff)]; @@ -204,16 +204,16 @@ unsigned FASTCALL Hash8( const void *pKey ) //----------------------------------------------------------------------------- unsigned FASTCALL Hash12( const void *pKey ) { - register const uint32 * p = (const uint32 *) pKey; - register unsigned even, - odd, - n; + const uint32 * p = (const uint32 *) pKey; + unsigned even, + odd, + n; n = *p; even = g_nRandomValues[n & 0xff]; odd = g_nRandomValues[((n >> 8) & 0xff)]; even = g_nRandomValues[odd ^ (n >> 24)]; - odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; odd = g_nRandomValues[even ^ (n & 0xff)]; @@ -238,16 +238,16 @@ unsigned FASTCALL Hash12( const void *pKey ) //----------------------------------------------------------------------------- unsigned FASTCALL Hash16( const void *pKey ) { - register const uint32 * p = (const uint32 *) pKey; - register unsigned even, - odd, - n; + const uint32 * p = (const uint32 *) pKey; + unsigned even, + odd, + n; n = *p; even = g_nRandomValues[n & 0xff]; odd = g_nRandomValues[((n >> 8) & 0xff)]; even = g_nRandomValues[odd ^ (n >> 24)]; - odd = g_nRandomValues[even ^ (n >> 16) & 0xff]; + odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)]; even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)]; odd = g_nRandomValues[even ^ (n & 0xff)]; diff --git a/tier1/interface.cpp b/tier1/interface.cpp index 976465b0..3a47e692 100644 --- a/tier1/interface.cpp +++ b/tier1/interface.cpp @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -27,13 +27,16 @@ #include "tier0/threadtools.h" #ifdef _WIN32 #include // getcwd -#elif defined _LINUX || defined __APPLE__ +#elif POSIX +#include +#include #define _getcwd getcwd #endif #if defined( _X360 ) #include "xbox/xbox_win32stubs.h" #endif + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -54,8 +57,15 @@ InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) : // CreateInterface. // This is the primary exported function by a dll, referenced by name via dynamic binding // that exposes an opqaue function pointer to the interface. +// +// We have the Internal variant so Sys_GetFactoryThis() returns the correct internal +// symbol under GCC/Linux/Mac as CreateInterface is DLL_EXPORT so its global so the loaders +// on those OS's pick exactly 1 of the CreateInterface symbols to be the one that is process wide and +// all Sys_GetFactoryThis() calls find that one, which doesn't work. Using the internal walkthrough here +// makes sure Sys_GetFactoryThis() has the dll specific symbol and GetProcAddress() returns the module specific +// function for CreateInterface again getting the dll specific symbol we need. // ------------------------------------------------------------------------------------ // -void* CreateInterface( const char *pName, int *pReturnCode ) +void* CreateInterfaceInternal( const char *pName, int *pReturnCode ) { InterfaceReg *pCur; @@ -78,8 +88,14 @@ void* CreateInterface( const char *pName, int *pReturnCode ) return NULL; } +void* CreateInterface( const char *pName, int *pReturnCode ) +{ + return CreateInterfaceInternal( pName, pReturnCode ); +} -#if defined _LINUX || defined __APPLE__ + + +#ifdef POSIX // Linux doesn't have this function so this emulates its functionality void *GetModuleHandle(const char *name) { @@ -119,14 +135,24 @@ void *GetModuleHandle(const char *name) //----------------------------------------------------------------------------- static void *Sys_GetProcAddress( const char *pModuleName, const char *pName ) { - HMODULE hModule = GetModuleHandle( pModuleName ); - return GetProcAddress( hModule, pName ); + HMODULE hModule = (HMODULE)GetModuleHandle( pModuleName ); +#ifdef WIN32 + return (void *)GetProcAddress( hModule, pName ); +#else + return (void *)dlsym( (void *)hModule, pName ); +#endif } +#if !defined(LINUX) static void *Sys_GetProcAddress( HMODULE hModule, const char *pName ) { - return GetProcAddress( hModule, pName ); +#ifdef WIN32 + return (void *)GetProcAddress( hModule, pName ); +#else + return (void *)dlsym( (void *)hModule, pName ); +#endif } +#endif bool Sys_IsDebuggerPresent() { @@ -142,53 +168,59 @@ struct ThreadedLoadLibaryContext_t #ifdef _WIN32 // wraps LoadLibraryEx() since 360 doesn't support that -static HMODULE InternalLoadLibrary( const char *pName ) +static HMODULE InternalLoadLibrary( const char *pName, Sys_Flags flags ) { #if defined(_X360) return LoadLibrary( pName ); #else - return LoadLibraryEx( pName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); + if ( flags & SYS_NOLOAD ) + return GetModuleHandle( pName ); + else + return LoadLibraryEx( pName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); #endif } unsigned ThreadedLoadLibraryFunc( void *pParam ) { ThreadedLoadLibaryContext_t *pContext = (ThreadedLoadLibaryContext_t*)pParam; - pContext->m_hLibrary = InternalLoadLibrary(pContext->m_pLibraryName); + pContext->m_hLibrary = InternalLoadLibrary( pContext->m_pLibraryName, SYS_NOFLAGS ); return 0; } -#endif -HMODULE Sys_LoadLibrary( const char *pLibraryName ) +#endif // _WIN32 + +HMODULE Sys_LoadLibrary( const char *pLibraryName, Sys_Flags flags ) { - char str[1024]; -#if defined( _WIN32 ) && !defined( _X360 ) - const char *pModuleExtension = ".dll"; - const char *pModuleAddition = pModuleExtension; -#elif defined( _X360 ) - const char *pModuleExtension = "_360.dll"; - const char *pModuleAddition = pModuleExtension; -#elif defined( _LINUX ) - const char *pModuleExtension = ".so"; - const char *pModuleAddition = "_i486.so"; // if an extension is on the filename assume the i486 binary set -#elif defined( __APPLE__ ) - const char *pModuleExtension = ".dylib"; - const char *pModuleAddition = ".dylib"; -#endif + char str[ 1024 ]; + // Note: DLL_EXT_STRING can be "_srv.so" or "_360.dll". So be careful + // when using the V_*Extension* routines... + const char *pDllStringExtension = V_GetFileExtension( DLL_EXT_STRING ); + const char *pModuleExtension = pDllStringExtension ? ( pDllStringExtension - 1 ) : DLL_EXT_STRING; + Q_strncpy( str, pLibraryName, sizeof(str) ); - if ( !Q_stristr( str, pModuleExtension ) ) + + if ( IsX360() ) { - if ( IsX360() ) + // old, probably busted, behavior for xbox + if ( !Q_stristr( str, pModuleExtension ) ) { - Q_StripExtension( str, str, sizeof(str) ); + V_SetExtension( str, pModuleExtension, sizeof(str) ); } - Q_strncat( str, pModuleAddition, sizeof(str) ); } + else + { + // always force the final extension to be .dll + V_SetExtension( str, pModuleExtension, sizeof(str) ); + } + Q_FixSlashes( str ); #ifdef _WIN32 ThreadedLoadLibraryFunc_t threadFunc = GetThreadedLoadLibraryFunc(); if ( !threadFunc ) - return InternalLoadLibrary( str ); + return InternalLoadLibrary( str, flags ); + + // We shouldn't be passing noload while threaded. + Assert( !( flags & SYS_NOLOAD ) ); ThreadedLoadLibaryContext_t context; context.m_pLibraryName = str; @@ -209,34 +241,39 @@ HMODULE Sys_LoadLibrary( const char *pLibraryName ) ReleaseThreadHandle( h ); return context.m_hLibrary; -#elif defined _LINUX || defined __APPLE__ - HMODULE ret = dlopen( str, RTLD_NOW ); - if ( ! ret ) +#elif POSIX + int dlopen_mode = RTLD_NOW; + + if ( flags & SYS_NOLOAD ) + dlopen_mode |= RTLD_NOLOAD; + + HMODULE ret = ( HMODULE )dlopen( str, dlopen_mode ); + if ( !ret && !( flags & SYS_NOLOAD ) ) { const char *pError = dlerror(); - if ( pError && ( strstr( pError, "No such file" ) == 0 ) ) + if ( pError && ( strstr( pError, "No such file" ) == 0 ) && ( strstr( pError, "image not found" ) == 0 ) ) { Msg( " failed to dlopen %s error=%s\n", str, pError ); - } } return ret; #endif } +static bool s_bRunningWithDebugModules = false; //----------------------------------------------------------------------------- // Purpose: Loads a DLL/component from disk and returns a handle to it // Input : *pModuleName - filename of the component // Output : opaque handle to the module (hides system dependency) //----------------------------------------------------------------------------- -CSysModule *Sys_LoadModule( const char *pModuleName ) +CSysModule *Sys_LoadModule( const char *pModuleName, Sys_Flags flags /* = SYS_NOFLAGS (0) */ ) { // If using the Steam filesystem, either the DLL must be a minimum footprint // file in the depot (MFP) or a filesystem GetLocalCopy() call must be made // prior to the call to this routine. char szCwd[1024]; - HMODULE hDLL = NULL; + HMODULE hDLL = 0; if ( !Q_IsAbsolutePath( pModuleName ) ) { @@ -247,7 +284,7 @@ CSysModule *Sys_LoadModule( const char *pModuleName ) int i = CommandLine()->FindParm( "-basedir" ); if ( i ) { - strcpy( szCwd, CommandLine()->GetParm( i+1 ) ); + V_strcpy_safe( szCwd, CommandLine()->GetParm( i + 1 ) ); } } if (szCwd[strlen(szCwd) - 1] == '/' || szCwd[strlen(szCwd) - 1] == '\\' ) @@ -256,7 +293,8 @@ CSysModule *Sys_LoadModule( const char *pModuleName ) } char szAbsoluteModuleName[1024]; - if ( strstr( pModuleName, "bin/") == pModuleName ) + size_t cCwd = strlen( szCwd ); + if ( strstr( pModuleName, "bin/") == pModuleName || ( szCwd[ cCwd - 1 ] == 'n' && szCwd[ cCwd - 2 ] == 'i' && szCwd[ cCwd - 3 ] == 'b' ) ) { // don't make bin/bin path Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/%s", szCwd, pModuleName ); @@ -265,13 +303,13 @@ CSysModule *Sys_LoadModule( const char *pModuleName ) { Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/bin/%s", szCwd, pModuleName ); } - hDLL = Sys_LoadLibrary( szAbsoluteModuleName ); + hDLL = Sys_LoadLibrary( szAbsoluteModuleName, flags ); } if ( !hDLL ) { // full path failed, let LoadLibrary() try to search the PATH now - hDLL = Sys_LoadLibrary( pModuleName ); + hDLL = Sys_LoadLibrary( pModuleName, flags ); #if defined( _DEBUG ) if ( !hDLL ) { @@ -293,28 +331,69 @@ CSysModule *Sys_LoadModule( const char *pModuleName ) LocalFree( (HLOCAL)lpMsgBuf ); #elif defined( _X360 ) - Msg( "Failed to load %s:\n", pModuleName ); + DWORD error = GetLastError(); + Msg( "Error(%d) - Failed to load %s:\n", error, pModuleName ); #else - Error( "Failed to load %s: %s\n", pModuleName, dlerror() ); + Msg( "Failed to load %s: %s\n", pModuleName, dlerror() ); #endif // _WIN32 } #endif // DEBUG } +#if !defined(LINUX) // If running in the debugger, assume debug binaries are okay, otherwise they must run with -allowdebug - if ( !IsX360() && hDLL && - !CommandLine()->FindParm( "-allowdebug" ) && - !Sys_IsDebuggerPresent() ) + if ( Sys_GetProcAddress( hDLL, "BuiltDebug" ) ) { - if ( Sys_GetProcAddress( hDLL, "BuiltDebug" ) ) + if ( !IsX360() && hDLL && + !CommandLine()->FindParm( "-allowdebug" ) && + !Sys_IsDebuggerPresent() ) { Error( "Module %s is a debug build\n", pModuleName ); } + + DevWarning( "Module %s is a debug build\n", pModuleName ); + + if ( !s_bRunningWithDebugModules ) + { + s_bRunningWithDebugModules = true; + +#if 0 //def IS_WINDOWS_PC + char chMemoryName[ MAX_PATH ]; + DebugKernelMemoryObjectName( chMemoryName ); + + (void) CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, chMemoryName ); + // Created a shared memory kernel object specific to process id + // Existence of this object indicates that we have debug modules loaded +#endif + } } +#endif return reinterpret_cast(hDLL); } +//----------------------------------------------------------------------------- +// Purpose: Determine if any debug modules were loaded +//----------------------------------------------------------------------------- +bool Sys_RunningWithDebugModules() +{ + if ( !s_bRunningWithDebugModules ) + { +#if 0 //def IS_WINDOWS_PC + char chMemoryName[ MAX_PATH ]; + DebugKernelMemoryObjectName( chMemoryName ); + + HANDLE hObject = OpenFileMapping( FILE_MAP_READ, FALSE, chMemoryName ); + if ( hObject && hObject != INVALID_HANDLE_VALUE ) + { + CloseHandle( hObject ); + s_bRunningWithDebugModules = true; + } +#endif + } + return s_bRunningWithDebugModules; +} + //----------------------------------------------------------------------------- // Purpose: Unloads a DLL/component from @@ -330,7 +409,7 @@ void Sys_UnloadModule( CSysModule *pModule ) #ifdef _WIN32 FreeLibrary( hDLL ); -#elif defined(_LINUX) || defined(__APPLE__) +#elif defined(POSIX) dlclose((void *)hDLL); #endif } @@ -349,7 +428,7 @@ CreateInterfaceFn Sys_GetFactory( CSysModule *pModule ) HMODULE hDLL = reinterpret_cast(pModule); #ifdef _WIN32 return reinterpret_cast(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME )); -#elif defined(_LINUX) || defined (__APPLE__) +#elif defined(POSIX) // Linux gives this error: //../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory //(CSysModule *)) (const char *, int *)': @@ -357,7 +436,7 @@ CreateInterfaceFn Sys_GetFactory( CSysModule *pModule ) //pointer-to-function and pointer-to-object // // so lets get around it :) - return (CreateInterfaceFn)(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME )); + return (CreateInterfaceFn)(GetProcAddress( (void *)hDLL, CREATEINTERFACE_PROCNAME )); #endif } @@ -367,7 +446,7 @@ CreateInterfaceFn Sys_GetFactory( CSysModule *pModule ) //----------------------------------------------------------------------------- CreateInterfaceFn Sys_GetFactoryThis( void ) { - return CreateInterface; + return &CreateInterfaceInternal; } //----------------------------------------------------------------------------- @@ -379,7 +458,7 @@ CreateInterfaceFn Sys_GetFactory( const char *pModuleName ) { #ifdef _WIN32 return static_cast( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) ); -#elif defined(_LINUX) || defined(__APPLE__) +#elif defined(POSIX) // see Sys_GetFactory( CSysModule *pModule ) for an explanation return (CreateInterfaceFn)( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) ); #endif @@ -463,3 +542,26 @@ void CDllDemandLoader::Unload() m_hModule = 0; } } + +#if defined( STAGING_ONLY ) && defined( _WIN32 ) + +typedef USHORT( WINAPI RtlCaptureStackBackTrace_FUNC )( + ULONG frames_to_skip, + ULONG frames_to_capture, + PVOID *backtrace, + PULONG backtrace_hash ); + +extern "C" int backtrace( void **buffer, int size ) +{ + HMODULE hNTDll = GetModuleHandleA( "ntdll.dll" ); + static RtlCaptureStackBackTrace_FUNC * const pfnRtlCaptureStackBackTrace = + ( RtlCaptureStackBackTrace_FUNC * )GetProcAddress( hNTDll, "RtlCaptureStackBackTrace" ); + + if ( !pfnRtlCaptureStackBackTrace ) + return 0; + + return (int)pfnRtlCaptureStackBackTrace( 2, size, buffer, 0 ); +} + +#endif // STAGING_ONLY && _WIN32 + diff --git a/tier1/newbitbuf.cpp b/tier1/newbitbuf.cpp index 420556ec..fb44920d 100644 --- a/tier1/newbitbuf.cpp +++ b/tier1/newbitbuf.cpp @@ -29,7 +29,7 @@ void CBitWrite::StartWriting( void *pData, int nBytes, int iStartBit, int nBits { // Make sure it's dword aligned and padded. Assert( (nBytes % 4) == 0 ); - Assert(((unsigned long)pData & 3) == 0); + Assert(((uint32_t)pData & 3) == 0); Assert( iStartBit == 0 ); m_pData = (uint32 *) pData; m_pDataOut = m_pData; @@ -107,8 +107,8 @@ void CBitWrite::WriteLongLong(int64 val) // Insert the two DWORDS according to network endian const short endianIndex = 0x0100; byte *idx = (byte*)&endianIndex; - WriteUBitLong(pLongs[*idx++], sizeof(long) << 3); - WriteUBitLong(pLongs[*idx], sizeof(long) << 3); + WriteUBitLong(pLongs[*idx++], sizeof(uint32_t) << 3); + WriteUBitLong(pLongs[*idx], sizeof(uint32_t) << 3); } bool CBitWrite::WriteBits(const void *pInData, int nBits) @@ -390,7 +390,7 @@ bool CBitRead::Seek( int nPosition ) void CBitRead::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) { // Make sure it's dword aligned and padded. - Assert(((unsigned long)pData & 3) == 0); + Assert(((uint32_t)pData & 3) == 0); m_pData = (uint32 *) pData; m_pDataIn = m_pData; m_nDataBytes = nBytes; @@ -471,8 +471,8 @@ int64 CBitRead::ReadLongLong( void ) // Read the two DWORDs according to network endian const short endianIndex = 0x0100; byte *idx = (byte*)&endianIndex; - pLongs[*idx++] = ReadUBitLong(sizeof(long) << 3); - pLongs[*idx] = ReadUBitLong(sizeof(long) << 3); + pLongs[*idx++] = ReadUBitLong(sizeof(uint32_t) << 3); + pLongs[*idx] = ReadUBitLong(sizeof(uint32_t) << 3); return retval; } @@ -483,7 +483,7 @@ void CBitRead::ReadBits(void *pOutData, int nBits) // align output to dword boundary - while( ((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8 ) + while( ((uintptr_t)pOut & 3) != 0 && nBitsLeft >= 8 ) { *pOut = (unsigned char)ReadUBitLong(8); ++pOut; @@ -496,8 +496,8 @@ void CBitRead::ReadBits(void *pOutData, int nBits) // read dwords while ( nBitsLeft >= 32 ) { - *((unsigned long*)pOut) = ReadUBitLong(32); - pOut += sizeof(unsigned long); + *((uint32_t*)pOut) = ReadUBitLong(32); + pOut += sizeof(uint32_t); nBitsLeft -= 32; } } diff --git a/tier1/processor_detect.cpp b/tier1/processor_detect.cpp index a6bfe91b..fc6347e7 100644 --- a/tier1/processor_detect.cpp +++ b/tier1/processor_detect.cpp @@ -6,7 +6,14 @@ // $NoKeywords: $ //=============================================================================// -#if defined _LINUX || defined __APPLE__ +#if defined ( _WIN64 ) + +bool CheckMMXTechnology(void) { return true; } +bool CheckSSETechnology(void) { return true; } +bool CheckSSE2Technology(void) { return true; } +bool Check3DNowTechnology(void) { return true; } + +#elif defined _LINUX || defined __APPLE__ #include "processor_detect_linux.cpp" diff --git a/tier1/processor_detect_linux.cpp b/tier1/processor_detect_linux.cpp index b09df0e0..a1359f34 100644 --- a/tier1/processor_detect_linux.cpp +++ b/tier1/processor_detect_linux.cpp @@ -1,41 +1,55 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: linux dependant ASM code for CPU capability detection // // $Workfile: $ // $NoKeywords: $ //=============================================================================// +#include #define cpuid(in,a,b,c,d) \ asm("pushl %%ebx\n\t" "cpuid\n\t" "movl %%ebx,%%esi\n\t" "pop %%ebx": "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (in)); bool CheckMMXTechnology(void) { - unsigned long eax,ebx,edx,unused; +#ifndef PLATFORM_64BITS + uint32_t eax,ebx,edx,unused; cpuid(1,eax,ebx,unused,edx); return edx & 0x800000; +#else + return true; +#endif } bool CheckSSETechnology(void) { - unsigned long eax,ebx,edx,unused; +#ifndef PLATFORM_64BITS + uint32_t eax,ebx,edx,unused; cpuid(1,eax,ebx,unused,edx); return edx & 0x2000000L; +#else + return true; +#endif } bool CheckSSE2Technology(void) { - unsigned long eax,ebx,edx,unused; +#ifndef PLATFORM_64BITS + uint32_t eax,ebx,edx,unused; cpuid(1,eax,ebx,unused,edx); return edx & 0x04000000; +#else + return true; +#endif } bool Check3DNowTechnology(void) { - unsigned long eax, unused; +#ifndef PLATFORM_64BITS + uint32_t eax, unused; cpuid(0x80000000,eax,unused,unused,unused); if ( eax > 0x80000000L ) @@ -44,4 +58,7 @@ bool Check3DNowTechnology(void) return ( eax & 1<<31 ); } return false; +#else + return true; +#endif } diff --git a/tier1/strtools.cpp b/tier1/strtools.cpp index e7943983..c397724a 100644 --- a/tier1/strtools.cpp +++ b/tier1/strtools.cpp @@ -992,9 +992,240 @@ char *V_pretifynum( int64 value ) return out; } +//----------------------------------------------------------------------------- +// Purpose: returns true if a wide character is a "mean" space; that is, +// if it is technically a space or punctuation, but causes disruptive +// behavior when used in names, web pages, chat windows, etc. +// +// characters in this set are removed from the beginning and/or end of strings +// by Q_AggressiveStripPrecedingAndTrailingWhitespaceW() +//----------------------------------------------------------------------------- +bool Q_IsMeanSpaceW( wchar_t wch ) +{ + bool bIsMean = false; + + switch ( wch ) + { + case L'\x0082': // BREAK PERMITTED HERE + case L'\x0083': // NO BREAK PERMITTED HERE + case L'\x00A0': // NO-BREAK SPACE + case L'\x034F': // COMBINING GRAPHEME JOINER + case L'\x2000': // EN QUAD + case L'\x2001': // EM QUAD + case L'\x2002': // EN SPACE + case L'\x2003': // EM SPACE + case L'\x2004': // THICK SPACE + case L'\x2005': // MID SPACE + case L'\x2006': // SIX SPACE + case L'\x2007': // figure space + case L'\x2008': // PUNCTUATION SPACE + case L'\x2009': // THIN SPACE + case L'\x200A': // HAIR SPACE + case L'\x200B': // ZERO-WIDTH SPACE + case L'\x200C': // ZERO-WIDTH NON-JOINER + case L'\x200D': // ZERO WIDTH JOINER + case L'\x200E': // LEFT-TO-RIGHT MARK + case L'\x2028': // LINE SEPARATOR + case L'\x2029': // PARAGRAPH SEPARATOR + case L'\x202F': // NARROW NO-BREAK SPACE + case L'\x2060': // word joiner + case L'\xFEFF': // ZERO-WIDTH NO BREAK SPACE + case L'\xFFFC': // OBJECT REPLACEMENT CHARACTER + bIsMean = true; + break; + } + + return bIsMean; +} + //----------------------------------------------------------------------------- -// Purpose: Converts a UTF8 string into a unicode string +// Purpose: strips trailing whitespace; returns pointer inside string just past +// any leading whitespace. +// +// bAggresive = true causes this function to also check for "mean" spaces, +// which we don't want in persona names or chat strings as they're disruptive +// to the user experience. +//----------------------------------------------------------------------------- +static wchar_t *StripWhitespaceWorker( int cchLength, wchar_t *pwch, bool *pbStrippedWhitespace, bool bAggressive ) +{ + // walk backwards from the end of the string, killing any whitespace + *pbStrippedWhitespace = false; + + wchar_t *pwchEnd = pwch + cchLength; + while ( --pwchEnd >= pwch ) + { + if ( !iswspace( *pwchEnd ) && ( !bAggressive || !Q_IsMeanSpaceW( *pwchEnd ) ) ) + break; + + *pwchEnd = 0; + *pbStrippedWhitespace = true; + } + + // walk forward in the string + while ( pwch < pwchEnd ) + { + if ( !iswspace( *pwch ) ) + break; + + *pbStrippedWhitespace = true; + pwch++; + } + + return pwch; +} + +//----------------------------------------------------------------------------- +// Purpose: Strips all evil characters (ie. zero-width no-break space) +// from a string. +//----------------------------------------------------------------------------- +bool Q_RemoveAllEvilCharacters( char *pch ) +{ + // convert to unicode + int cch = Q_strlen( pch ); + int cubDest = (cch + 1 ) * sizeof( wchar_t ); + wchar_t *pwch = (wchar_t *)stackalloc( cubDest ); + int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t ); + + bool bStrippedWhitespace = false; + + // Walk through and skip over evil characters + int nWalk = 0; + for( int i=0; i - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -