runtime·malg(int32 stacksize) { G *newg; byte *stk; newg = runtime·malloc(sizeof(G)); if(stacksize >= 0) { if(g == m->g0) { // running on scheduler stack already. stk = runtime·stackalloc(StackSystem + stacksize); } else { // have to call stackalloc on scheduler stack. g->param = (void*)(StackSystem + stacksize); runtime·mcall(mstackalloc); stk = g->param; g->param = nil; } newg->stack0 = stk; newg->stackguard = stk + StackGuard; newg->stackbase = stk + StackSystem + stacksize - sizeof(Stktop); runtime·memclr(newg->stackbase, sizeof(Stktop)); } return newg; }
void CPhysicsSystem::PhysicsSimulate() { CMiniProfilerGuard mpg(&g_mp_PhysicsSimulate); VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS ); float frametime = gpGlobals->frametime; if ( physenv ) { g_Collisions.BufferTouchEvents( true ); #ifdef _DEBUG physenv->DebugCheckContacts(); #endif frametime *= cl_phys_timescale.GetFloat(); int maxTicks = cl_phys_maxticks.GetInt(); if ( maxTicks ) { float maxFrameTime = physenv->GetDeltaFrameTime( maxTicks ) - 1e-4f; frametime = clamp( frametime, 0, maxFrameTime ); } physenv->Simulate( frametime ); int activeCount = physenv->GetActiveObjectCount(); g_mp_active_object_count.Add(activeCount); IPhysicsObject **pActiveList = NULL; if ( activeCount ) { PHYS_PROFILE(aUpdateActiveObjects) pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); physenv->GetActiveObjects( pActiveList ); for ( int i = 0; i < activeCount; i++ ) { C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData()); if ( pEntity ) { //const CCollisionProperty *collProp = pEntity->CollisionProp(); //debugoverlay->AddBoxOverlay( collProp->GetCollisionOrigin(), collProp->OBBMins(), collProp->OBBMaxs(), collProp->GetCollisionAngles(), 190, 190, 0, 0, 0.01 ); if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) { pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); } pEntity->VPhysicsUpdate( pActiveList[i] ); IPhysicsShadowController *pShadow = pActiveList[i]->GetShadowController(); if ( pShadow ) { // active shadow object, check for error Vector pos, targetPos; QAngle rot, targetAngles; pShadow->GetTargetPosition( &targetPos, &targetAngles ); pActiveList[i]->GetPosition( &pos, &rot ); Vector delta = targetPos - pos; float dist = VectorNormalize(delta); bool bBlocked = false; if ( dist > cl_phys_block_dist.GetFloat() ) { Vector vel; pActiveList[i]->GetImplicitVelocity( &vel, NULL ); float proj = DotProduct(vel, delta); if ( proj < dist * cl_phys_block_fraction.GetFloat() ) { bBlocked = true; //Msg("%s was blocked %.3f (%.3f proj)!\n", pEntity->GetClassname(), dist, proj ); } } Vector targetAxis; float deltaTargetAngle; RotationDeltaAxisAngle( rot, targetAngles, targetAxis, deltaTargetAngle ); if ( fabsf(deltaTargetAngle) > 0.5f ) { AngularImpulse angVel; pActiveList[i]->GetImplicitVelocity( NULL, &angVel ); float proj = DotProduct( angVel, targetAxis ) * Sign(deltaTargetAngle); if ( proj < (fabsf(deltaTargetAngle) * cl_phys_block_fraction.GetFloat()) ) { bBlocked = true; //Msg("%s was rot blocked %.3f proj %.3f!\n", pEntity->GetClassname(), deltaTargetAngle, proj ); } } if ( bBlocked ) { C_BaseEntity *pBlocker = FindPhysicsBlocker( pActiveList[i] ); if ( pBlocker ) { if ( IsBlockedShouldDisableCollisions( pEntity ) ) { PhysDisableEntityCollisions( pEntity, pBlocker ); pActiveList[i]->RecheckContactPoints(); // GetClassname returns a pointer to the same buffer always! //Msg("%s blocked !", pEntity->GetClassname() ); Msg("by %s\n", pBlocker->GetClassname() ); } } } } } } } #if 0 if ( cl_visualize_physics_shadows.GetBool() ) { int entityCount = NUM_ENT_ENTRIES; for ( int i = 0; i < entityCount; i++ ) { IClientEntity *pClientEnt = cl_entitylist->GetClientEntity(i); if ( !pClientEnt ) continue; C_BaseEntity *pEntity = pClientEnt->GetBaseEntity(); if ( !pEntity ) continue; Vector pos; QAngle angle; IPhysicsObject *pObj = pEntity->VPhysicsGetObject(); if ( !pObj || !pObj->GetShadowController() ) continue; pObj->GetShadowPosition( &pos, &angle ); debugoverlay->AddBoxOverlay( pos, pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs(), angle, 255, 255, 0, 32, 0 ); char tmp[256]; V_snprintf( tmp, sizeof(tmp),"%s, (%s)\n", pEntity->GetClassname(), VecToString(angle) ); debugoverlay->AddTextOverlay( pos, 0, tmp ); } } #endif g_Collisions.BufferTouchEvents( false ); g_Collisions.FrameUpdate(); } physicssound::PlayImpactSounds( m_impactSounds ); }
CBaseEntity * CASW_Rocket::FindPotentialTarget( void ) const { float bestdist = 0; CBaseEntity *bestent = NULL; Vector v_forward, v_right, v_up; AngleVectors( GetAbsAngles(), &v_forward, &v_right, &v_up ); // find the aimtarget nearest us int count = AimTarget_ListCount(); if ( count ) { CBaseEntity **pList = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * count ); AimTarget_ListCopy( pList, count ); CTraceFilterSkipTwoEntities filter(this, GetOwnerEntity(), COLLISION_GROUP_NONE); for ( int i = 0; i < count; i++ ) { CBaseEntity *pEntity = pList[i]; if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() ) { //Msg("not alive or not an edict, skipping\n"); continue; } if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() ) { //Msg("not alive or not an edict, skipping\n"); continue; } // don't autoaim onto marines if (pEntity->Classify() == CLASS_ASW_MARINE || pEntity->Classify() == CLASS_ASW_COLONIST) continue; if ( pEntity->Classify() == CLASS_ASW_PARASITE ) { CASW_Parasite *pParasite = static_cast< CASW_Parasite* >( pEntity ); if ( pParasite->m_bInfesting ) { continue; } } Vector center = pEntity->BodyTarget( GetAbsOrigin() ); Vector center_flat = center; center_flat.z = GetAbsOrigin().z; Vector dir = (center - GetAbsOrigin()); VectorNormalize( dir ); Vector dir_flat = (center_flat - GetAbsOrigin()); VectorNormalize( dir_flat ); // make sure it's in front of the rocket float dot = DotProduct (dir, v_forward ); //if (dot < 0) //{ //continue; //} float dist = (pEntity->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); if (dist > ASW_ROCKET_MAX_HOMING_RANGE) continue; // check another marine isn't between us and the target to reduce FF trace_t tr; UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr); if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE) continue; // does this critter already have enough rockets to kill it? { CASW_DamageAllocationMgr::IndexType_t assignmentIndex = m_RocketAssigner.Find( pEntity ); if ( m_RocketAssigner.IsValid(assignmentIndex) ) { if ( m_RocketAssigner[assignmentIndex].m_flAccumulatedDamage > pEntity->GetHealth() ) { continue; } } } // check another marine isn't between us and the target to reduce FF UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr); if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE) continue; // increase distance if dot isn't towards us dist += (1.0f - dot) * 150; // bias of x units when object is 90 degrees to the side if (bestdist == 0 || dist < bestdist) { bestdist = dist; bestent = pEntity; } } if ( bestent && asw_rocket_debug.GetBool() ) { Vector center = bestent->BodyTarget( GetAbsOrigin() ); Vector center_flat = center; center_flat.z = GetAbsOrigin().z; Vector dir = (center - GetAbsOrigin()); VectorNormalize( dir ); Msg( "Rocket[%d] starting homing in on %s(%d) dir = %f %f %f\n", entindex(), bestent->GetClassname(), bestent->entindex(), VectorExpand( dir ) ); } } return bestent; }
//----------------------------------------------------------------------------- // Emits occluder brushes //----------------------------------------------------------------------------- static void EmitOccluderBrushes() { char str[64]; g_OccluderData.RemoveAll(); g_OccluderPolyData.RemoveAll(); g_OccluderVertexIndices.RemoveAll(); tree_t *pOccluderTree = ClipOccluderBrushes(); if (!pOccluderTree) return; CUtlVector<face_t*> faceList( 1024, 1024 ); CUtlVector<side_t*> sideList( 1024, 1024 ); GenerateOccluderFaceList( pOccluderTree->headnode, faceList ); #ifdef _DEBUG int *pEmitted = (int*)stackalloc( faceList.Count() * sizeof(int) ); memset( pEmitted, 0, faceList.Count() * sizeof(int) ); #endif for ( entity_num=1; entity_num < num_entities; ++entity_num ) { if (!IsFuncOccluder(entity_num)) continue; // Output only those parts of the occluder tree which are a part of the brush int nOccluder = g_OccluderData.AddToTail(); doccluderdata_t &occluderData = g_OccluderData[ nOccluder ]; occluderData.firstpoly = g_OccluderPolyData.Count(); occluderData.mins.Init( FLT_MAX, FLT_MAX, FLT_MAX ); occluderData.maxs.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); occluderData.flags = 0; occluderData.area = -1; // NOTE: If you change the algorithm by which occluder numbers are allocated, // then you must also change FixupOnlyEntsOccluderEntities() below sprintf (str, "%i", nOccluder); SetKeyValue (&entities[entity_num], "occludernumber", str); int nIndex = g_OccluderInfo.AddToTail(); g_OccluderInfo[nIndex].m_nOccluderEntityIndex = entity_num; sideList.RemoveAll(); GenerateOccluderSideList( entity_num, sideList ); for ( int i = faceList.Count(); --i >= 0; ) { // Skip nodraw surfaces, but not triggers that have been marked as nodraw face_t *f = faceList[i]; if ( ( texinfo[f->texinfo].flags & SURF_NODRAW ) && (( texinfo[f->texinfo].flags & SURF_TRIGGER ) == 0 ) ) continue; // Only emit faces that appear in the side list of the occluder for ( int j = sideList.Count(); --j >= 0; ) { if ( sideList[j] != f->originalface ) continue; if ( f->numpoints < 3 ) continue; // not a final face Assert ( !f->merged && !f->split[0] && !f->split[1] ); #ifdef _DEBUG Assert( !pEmitted[i] ); pEmitted[i] = entity_num; #endif int k = g_OccluderPolyData.AddToTail(); doccluderpolydata_t *pOccluderPoly = &g_OccluderPolyData[k]; pOccluderPoly->planenum = f->planenum; pOccluderPoly->vertexcount = f->numpoints; pOccluderPoly->firstvertexindex = g_OccluderVertexIndices.Count(); for( k = 0; k < f->numpoints; ++k ) { g_OccluderVertexIndices.AddToTail( f->vertexnums[k] ); const Vector &p = dvertexes[f->vertexnums[k]].point; VectorMin( occluderData.mins, p, occluderData.mins ); VectorMax( occluderData.maxs, p, occluderData.maxs ); } break; } } occluderData.polycount = g_OccluderPolyData.Count() - occluderData.firstpoly; // Mark this brush as not having brush geometry so it won't be re-emitted with a brush model entities[entity_num].numbrushes = 0; } FreeTree( pOccluderTree ); }
int CAI_TacticalServices::FindLosNode(const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinThreatDist, float flMaxThreatDist, float flBlockTime, FlankType_t eFlankType, const Vector &vecFlankRefPos, float flFlankParam ) { if ( !CAI_NetworkManager::NetworksLoaded() ) return NO_NODE; AI_PROFILE_SCOPE( CAI_TacticalServices_FindLosNode ); MARK_TASK_EXPENSIVE(); int iMyNode = GetPathfinder()->NearestNodeToNPC(); if ( iMyNode == NO_NODE ) { Vector pos = GetOuter()->GetAbsOrigin(); DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z); return NO_NODE; } // ------------------------------------------------------------------------------------ // We're going to search for a shoot node by expanding to our current node's neighbors // and then their neighbors, until a shooting position is found, or all nodes are beyond MaxDist // ------------------------------------------------------------------------------------ AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() ); CNodeList list( pBuffer, GetNetwork()->NumNodes() ); CVarBitVec wasVisited(GetNetwork()->NumNodes()); // Nodes visited // mark start as visited wasVisited.Set( iMyNode ); list.Insert( AI_NearNode_t(iMyNode, 0) ); static int nSearchRandomizer = 0; // tries to ensure the links are searched in a different order each time; while ( list.Count() ) { int nodeIndex = list.ElementAtHead().nodeIndex; // remove this item from the list list.RemoveAtHead(); const Vector &nodeOrigin = GetNetwork()->GetNode(nodeIndex)->GetPosition(GetHullType()); // HACKHACK: Can't we rework this loop and get rid of this? // skip the starting node, or we probably wouldn't have called this function. if ( nodeIndex != iMyNode ) { bool skip = false; // See if the node satisfies the flanking criteria. switch ( eFlankType ) { case FLANKTYPE_NONE: break; case FLANKTYPE_RADIUS: { Vector vecDist = nodeOrigin - vecFlankRefPos; if ( vecDist.Length() < flFlankParam ) { skip = true; } break; } case FLANKTYPE_ARC: { Vector vecEnemyToRef = vecFlankRefPos - vThreatPos; VectorNormalize( vecEnemyToRef ); Vector vecEnemyToNode = nodeOrigin - vThreatPos; VectorNormalize( vecEnemyToNode ); float flDot = DotProduct( vecEnemyToRef, vecEnemyToNode ); if ( RAD2DEG( acos( flDot ) ) < flFlankParam ) { skip = true; } break; } } // Don't accept climb nodes, and assume my nearest node isn't valid because // we decided to make this check in the first place. Keep moving if ( !skip && !GetNetwork()->GetNode(nodeIndex)->IsLocked() && GetNetwork()->GetNode(nodeIndex)->GetType() != NODE_CLIMB ) { // Now check its distance and only accept if in range float flThreatDist = ( nodeOrigin - vThreatPos ).Length(); if ( flThreatDist < flMaxThreatDist && flThreatDist > flMinThreatDist ) { CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex); if ( GetOuter()->IsValidShootPosition( nodeOrigin, pNode, pNode->GetHint() ) ) { if (GetOuter()->TestShootPosition(nodeOrigin,vThreatEyePos)) { // Note when this node was used, so we don't try // to use it again right away. GetNetwork()->GetNode(nodeIndex)->Lock( flBlockTime ); #if 0 if ( GetOuter()->GetHintNode() ) { GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType())); GetOuter()->SetHintNode( NULL ); } // This used to not be set, why? (kenb) // @Note (toml 05-19-04): I think because stomping the hint can lead to // unintended side effects. The hint node is primarily a high level // tool, and certain NPCs break if it gets slammed here. If we need // this, we should propagate it out and let the schedule selector // or task decide to set the hint node GetOuter()->SetHintNode( GetNetwork()->GetNode(nodeIndex)->GetHint() ); #endif if ( ShouldDebugLos( nodeIndex ) ) { NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:los!", nodeIndex), false, 1 ); } // The next NPC who searches should use a slight different pattern nSearchRandomizer = nodeIndex; return nodeIndex; } else { if ( ShouldDebugLos( nodeIndex ) ) { NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!shoot", nodeIndex), false, 1 ); } } } else { if ( ShouldDebugLos( nodeIndex ) ) { NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!valid", nodeIndex), false, 1 ); } } } else { if ( ShouldDebugLos( nodeIndex ) ) { CFmtStr msg( "%d:%s", nodeIndex, ( flThreatDist < flMaxThreatDist ) ? "too close" : "too far" ); NDebugOverlay::Text( nodeOrigin, msg, false, 1 ); } } } } // Go through each link and add connected nodes to the list for (int link=0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks();link++) { int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks(); CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index); if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) continue; int newID = nodeLink->DestNodeID(nodeIndex); // If not already visited, add to the list if (!wasVisited.IsBitSet(newID)) { float dist = (GetLocalOrigin() - GetNetwork()->GetNode(newID)->GetPosition(GetHullType())).LengthSqr(); list.Insert( AI_NearNode_t(newID, dist) ); wasVisited.Set( newID ); } } } // We failed. No range attack node node was found return NO_NODE; }
int CAI_TacticalServices::FindCoverNode(const Vector &vNearPos, const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist ) { if ( !CAI_NetworkManager::NetworksLoaded() ) return NO_NODE; AI_PROFILE_SCOPE( CAI_TacticalServices_FindCoverNode ); MARK_TASK_EXPENSIVE(); DebugFindCover( NO_NODE, GetOuter()->EyePosition(), vThreatEyePos, 0, 255, 255 ); int iMyNode = GetPathfinder()->NearestNodeToPoint( vNearPos ); if ( iMyNode == NO_NODE ) { Vector pos = GetOuter()->GetAbsOrigin(); DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z); return NO_NODE; } if ( !flMaxDist ) { // user didn't supply a MaxDist, so work up a crazy one. flMaxDist = 784; } if ( flMinDist > 0.5 * flMaxDist) { flMinDist = 0.5 * flMaxDist; } // ------------------------------------------------------------------------------------ // We're going to search for a cover node by expanding to our current node's neighbors // and then their neighbors, until cover is found, or all nodes are beyond MaxDist // ------------------------------------------------------------------------------------ AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() ); CNodeList list( pBuffer, GetNetwork()->NumNodes() ); CVarBitVec wasVisited(GetNetwork()->NumNodes()); // Nodes visited // mark start as visited list.Insert( AI_NearNode_t(iMyNode, 0) ); wasVisited.Set( iMyNode ); float flMinDistSqr = flMinDist*flMinDist; float flMaxDistSqr = flMaxDist*flMaxDist; static int nSearchRandomizer = 0; // tries to ensure the links are searched in a different order each time; // Search until the list is empty while( list.Count() ) { // Get the node that is closest in the number of steps and remove from the list int nodeIndex = list.ElementAtHead().nodeIndex; list.RemoveAtHead(); CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex); Vector nodeOrigin = pNode->GetPosition(GetHullType()); float dist = (vNearPos - nodeOrigin).LengthSqr(); if (dist >= flMinDistSqr && dist < flMaxDistSqr) { Activity nCoverActivity = GetOuter()->GetCoverActivity( pNode->GetHint() ); Vector vEyePos = nodeOrigin + GetOuter()->EyeOffset(nCoverActivity); if ( GetOuter()->IsValidCover( nodeOrigin, pNode->GetHint() ) ) { // Check if this location will block the threat's line of sight to me if (GetOuter()->IsCoverPosition(vThreatEyePos, vEyePos)) { // -------------------------------------------------------- // Don't let anyone else use this node for a while // -------------------------------------------------------- pNode->Lock( 1.0 ); if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW ) ) { if ( GetOuter()->GetHintNode() ) { GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType())); GetOuter()->SetHintNode( NULL ); } GetOuter()->SetHintNode( pNode->GetHint() ); } // The next NPC who searches should use a slight different pattern nSearchRandomizer = nodeIndex; DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 0, 255, 0 ); return nodeIndex; } else { DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 255, 0, 0 ); } } else { DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 0, 0, 255 ); } } // Add its children to the search list // Go through each link // UNDONE: Pass in a cost function to measure each link? for ( int link = 0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks(); link++ ) { int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks(); CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index); if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) continue; int newID = nodeLink->DestNodeID(nodeIndex); // If not already on the closed list, add to it and set its distance if (!wasVisited.IsBitSet(newID)) { // Don't accept climb nodes or nodes that aren't ready to use yet if ( GetNetwork()->GetNode(newID)->GetType() != NODE_CLIMB && !GetNetwork()->GetNode(newID)->IsLocked() ) { // UNDONE: Shouldn't we really accumulate the distance by path rather than // absolute distance. After all, we are performing essentially an A* here. nodeOrigin = GetNetwork()->GetNode(newID)->GetPosition(GetHullType()); dist = (vNearPos - nodeOrigin).LengthSqr(); // use distance to threat as a heuristic to keep AIs from running toward // the threat in order to take cover from it. float threatDist = (vThreatPos - nodeOrigin).LengthSqr(); // Now check this node is not too close towards the threat if ( dist < threatDist * 1.5 ) { list.Insert( AI_NearNode_t(newID, dist) ); } } // mark visited wasVisited.Set(newID); } } } // We failed. Not cover node was found // Clear hint node used to set ducking GetOuter()->ClearHintNode(); return NO_NODE; }
int kproc(char *name, void (*func)(void*), void *arg, int flags) { Proc *p; Pgrp *pg; Fgrp *fg; Egrp *eg; int pid; void *tos; p = newproc(); if(flags & KPDUPPG) { pg = up->env->pgrp; incref(&pg->r); p->env->pgrp = pg; } if(flags & KPDUPFDG) { fg = up->env->fgrp; incref(&fg->r); p->env->fgrp = fg; } if(flags & KPDUPENVG) { eg = up->env->egrp; incref(&eg->r); p->env->egrp = eg; } p->env->uid = up->env->uid; p->env->gid = up->env->gid; kstrdup(&p->env->user, up->env->user); strcpy(p->text, name); p->func = func; p->arg = arg; lock(&procs.l); if(procs.tail != nil) { p->prev = procs.tail; procs.tail->next = p; } else { procs.head = p; p->prev = nil; } procs.tail = p; unlock(&procs.l); if(flags & KPX11){ p->kstack = nil; /* never freed; also up not defined */ tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*); }else p->kstack = stackalloc(p, &tos); pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, tos, tramp, p); if(pid < 0) panic("ourfork"); return pid; }
// Called from reflect·call or from runtime·morestack when a new // stack segment is needed. Allocate a new stack big enough for // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, // and then act as though runtime·lessstack called the function at // m->morepc. void runtime·newstack(void) { int32 framesize, argsize; Stktop *top; byte *stk, *sp; G *g1; Gobuf label; bool reflectcall; uintptr free; framesize = m->moreframesize; argsize = m->moreargsize; g1 = m->curg; if(m->morebuf.sp < g1->stackguard - StackGuard) { runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, g1->stackguard - StackGuard); runtime·throw("runtime: split stack overflow"); } if(argsize % sizeof(uintptr) != 0) { runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize); runtime·throw("runtime: stack split argsize"); } reflectcall = framesize==1; if(reflectcall) framesize = 0; if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > g1->stackguard) { // special case: called from reflect.call (framesize==1) // to call code with an arbitrary argument size, // and we have enough space on the current stack. // the new Stktop* is necessary to unwind, but // we don't need to create a new segment. top = (Stktop*)(m->morebuf.sp - sizeof(*top)); stk = g1->stackguard - StackGuard; free = 0; } else { // allocate new segment. framesize += argsize; framesize += StackExtra; // room for more functions, Stktop. if(framesize < StackMin) framesize = StackMin; framesize += StackSystem; stk = runtime·stackalloc(framesize); top = (Stktop*)(stk+framesize-sizeof(*top)); free = framesize; } //runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n", //framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, g1->stackbase); top->stackbase = g1->stackbase; top->stackguard = g1->stackguard; top->gobuf = m->morebuf; top->argp = m->moreargp; top->argsize = argsize; top->free = free; m->moreargp = nil; m->morebuf.pc = nil; m->morebuf.sp = nil; // copy flag from panic top->panic = g1->ispanic; g1->ispanic = false; g1->stackbase = (byte*)top; g1->stackguard = stk + StackGuard; sp = (byte*)top; if(argsize > 0) { sp -= argsize; runtime·memmove(sp, top->argp, argsize); } if(thechar == '5') { // caller would have saved its LR below args. sp -= sizeof(void*); *(void**)sp = nil; } // Continue as if lessstack had just called m->morepc // (the PC that decided to grow the stack). label.sp = sp; label.pc = (byte*)runtime·lessstack; label.g = m->curg; runtime·gogocall(&label, m->morepc); *(int32*)345 = 123; // never return }
//----------------------------------------------------------------------------- // Purpose: Spawn the entities I contain // Input : &vecOrigin - // &vecAngles - // pEntities - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CPointTemplate::CreateInstance( const Vector &vecOrigin, const QAngle &vecAngles, CUtlVector<CBaseEntity*> *pEntities ) { // Go through all our templated map data and spawn all the entities in it int iTemplates = m_hTemplates.Count(); if ( !iTemplates ) { Msg("CreateInstance called on a point_template that has no templates: %s\n", STRING(GetEntityName()) ); return false; } // Tell the template system we're about to start a new template Templates_StartUniqueInstance(); HierarchicalSpawn_t *pSpawnList = (HierarchicalSpawn_t*)stackalloc( iTemplates * sizeof(HierarchicalSpawn_t) ); int i; for ( i = 0; i < iTemplates; i++ ) { CBaseEntity *pEntity = NULL; char *pMapData; int iTemplateIndex = m_hTemplates[i].iTemplateIndex; // Some templates have Entity I/O connecting the entities within the template. // Unique versions of these templates need to be created whenever they're instanced. if ( AllowNameFixup() && Templates_IndexRequiresEntityIOFixup( iTemplateIndex ) ) { // This template requires instancing. // Create a new mapdata block and ask the template system to fill it in with // a unique version (with fixed Entity I/O connections). pMapData = Templates_GetEntityIOFixedMapData( iTemplateIndex ); } else { // Use the unmodified mapdata pMapData = (char*)STRING( Templates_FindByIndex( iTemplateIndex ) ); } // Create the entity from the mapdata MapEntity_ParseEntity( pEntity, pMapData, NULL ); if ( pEntity == NULL ) { Msg("Failed to initialize templated entity with mapdata: %s\n", pMapData ); return false; } // Get a matrix that'll convert from world to the new local space VMatrix matNewTemplateToWorld, matStoredLocalToWorld; matNewTemplateToWorld.SetupMatrixOrgAngles( vecOrigin, vecAngles ); MatrixMultiply( matNewTemplateToWorld, m_hTemplates[i].matEntityToTemplate, matStoredLocalToWorld ); // Get the world origin & angles from the stored local coordinates Vector vecNewOrigin; QAngle vecNewAngles; vecNewOrigin = matStoredLocalToWorld.GetTranslation(); MatrixToAngles( matStoredLocalToWorld, vecNewAngles ); // Set its origin & angles pEntity->SetAbsOrigin( vecNewOrigin ); pEntity->SetAbsAngles( vecNewAngles ); pSpawnList[i].m_pEntity = pEntity; pSpawnList[i].m_nDepth = 0; } SpawnHierarchicalList( iTemplates, pSpawnList, true ); for ( i = 0; i < iTemplates; ++i ) { if ( pSpawnList[i].m_pEntity ) { pEntities->AddToTail( pSpawnList[i].m_pEntity ); } } return true; }
void kproc(char *name, void (*func)(void*), void *arg, int flags) { int pid; Proc *p; Pgrp *pg; Fgrp *fg; Egrp *eg; void *tos; p = newproc(); if(0) print("start %s:%.8lx\n", name, p); if(p == nil) { print("kproc(%s): no memory", name); panic("kproc: no memory"); } if(flags & KPDUPPG) { pg = up->env->pgrp; incref(&pg->r); p->env->pgrp = pg; } if(flags & KPDUPFDG) { fg = up->env->fgrp; incref(&fg->r); p->env->fgrp = fg; } if(flags & KPDUPENVG) { eg = up->env->egrp; incref(&eg->r); p->env->egrp = eg; } p->env->uid = up->env->uid; p->env->gid = up->env->gid; kstrdup(&p->env->user, up->env->user); strcpy(p->text, name); p->func = func; p->arg = arg; if(flags & KPX11){ p->kstack = nil; /* never freed; also up not defined */ tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*); }else p->kstack = stackalloc(p, &tos); lock(&procs.l); if(procs.tail != nil) { p->prev = procs.tail; procs.tail->next = p; } else { procs.head = p; p->prev = nil; } procs.tail = p; unlock(&procs.l); if (__clone(tramp, tos, /*CLONE_PTRACE|*/CLONE_VM|CLONE_FS|CLONE_FILES|SIGCHLD, p) <= 0) { fprint(2, "emu: clone failed: %s\n", strerror(errno)); panic("kproc: clone failed"); } }
void libinit(char *imod) { struct termios t; struct sigaction act; sigset_t mask; struct passwd *pw; Proc *p; void *tos; char sys[64]; setsid(); gethostname(sys, sizeof(sys)); kstrdup(&ossysname, sys); pw = getpwnam("nobody"); if(pw != nil) { uidnobody = pw->pw_uid; gidnobody = pw->pw_gid; } if(dflag == 0) termset(); memset(&act, 0 , sizeof(act)); act.sa_handler = trapUSR1; sigaction(SIGUSR1, &act, nil); sigemptyset(&mask); sigaddset(&mask, SIGUSR2); sigprocmask(SIG_BLOCK, &mask, NULL); memset(&act, 0 , sizeof(act)); act.sa_handler = trapUSR2; sigaction(SIGUSR2, &act, nil); act.sa_handler = SIG_IGN; sigaction(SIGCHLD, &act, nil); /* * For the correct functioning of devcmd in the * face of exiting slaves */ signal(SIGPIPE, SIG_IGN); if(signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, cleanexit); if(signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanexit); if(sflag == 0) { act.sa_handler = trapBUS; sigaction(SIGBUS, &act, nil); act.sa_handler = trapILL; sigaction(SIGILL, &act, nil); act.sa_handler = trapSEGV; sigaction(SIGSEGV, &act, nil); act.sa_handler = trapFPE; sigaction(SIGFPE, &act, nil); } p = newproc(); p->kstack = stackalloc(p, &tos); pw = getpwuid(getuid()); if(pw != nil) kstrdup(&eve, pw->pw_name); else print("cannot getpwuid\n"); p->env->uid = getuid(); p->env->gid = getgid(); executeonnewstack(tos, emuinit, imod); }
void UserMessages::OnMessageEnd_Pre() { if (!m_InHook) { UM_RETURN_META(MRES_IGNORED); } MsgList *pList; MsgIter iter; ListenerInfo *pInfo; ResultType res; bool intercepted = false; bool handled = false; pList = &m_msgIntercepts[m_CurId]; for (iter=pList->begin(); iter!=pList->end(); ) { pInfo = (*iter); pInfo->IsHooked = true; #ifdef USE_PROTOBUF_USERMESSAGES res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter); #else res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter); #endif intercepted = true; switch (res) { case Pl_Stop: { if (pInfo->KillMe) { pList->erase(iter); m_FreeListeners.push(pInfo); _DecRefCounter(); goto supercede; } pInfo->IsHooked = false; goto supercede; } case Pl_Handled: { handled = true; if (pInfo->KillMe) { iter = pList->erase(iter); m_FreeListeners.push(pInfo); _DecRefCounter(); continue; } break; } default: { if (pInfo->KillMe) { iter = pList->erase(iter); m_FreeListeners.push(pInfo); _DecRefCounter(); continue; } break; } } pInfo->IsHooked = false; iter++; } if (!handled && intercepted) { #if SOURCE_ENGINE == SE_CSGO ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer); #else bf_write *engine_bfw; #if SOURCE_ENGINE >= SE_LEFT4DEAD engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId)); #else engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId); #endif m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten()); engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten()); ENGINE_CALL(MessageEnd)(); #endif // SE_CSGO } { #if SOURCE_ENGINE == SE_CSGO int size = m_OrigBuffer->ByteSize(); uint8 *data = (uint8 *)stackalloc(size); m_OrigBuffer->SerializePartialToArray(data, size); protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New(); pTempMsg->ParsePartialFromArray(data, size); #else bf_write *pTempMsg = m_OrigBuffer; #endif pList = &m_msgHooks[m_CurId]; for (iter=pList->begin(); iter!=pList->end(); ) { pInfo = (*iter); pInfo->IsHooked = true; pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter); if (pInfo->KillMe) { iter = pList->erase(iter); m_FreeListeners.push(pInfo); _DecRefCounter(); continue; } pInfo->IsHooked = false; iter++; } #if SOURCE_ENGINE == SE_CSGO delete pTempMsg; #endif } UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED); supercede: m_BlockEndPost = true; UM_RETURN_META(MRES_SUPERCEDE); }
// Called from reflect·call or from runtime·morestack when a new // stack segment is needed. Allocate a new stack big enough for // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, // and then act as though runtime·lessstack called the function at // m->morepc. void runtime·newstack(void) { int32 framesize, minalloc, argsize; Stktop *top; byte *stk, *sp; uintptr *src, *dst, *dstend; G *gp; Gobuf label; bool reflectcall; uintptr free; framesize = m->moreframesize; argsize = m->moreargsize; gp = m->curg; if(m->morebuf.sp < gp->stackguard - StackGuard) { runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, gp->stackguard - StackGuard); runtime·throw("runtime: split stack overflow"); } if(argsize % sizeof(uintptr) != 0) { runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize); runtime·throw("runtime: stack split argsize"); } minalloc = 0; reflectcall = framesize==1; if(reflectcall) { framesize = 0; // moreframesize_minalloc is only set in runtime·gc(), // that calls newstack via reflect·call(). minalloc = m->moreframesize_minalloc; m->moreframesize_minalloc = 0; if(framesize < minalloc) framesize = minalloc; } if(reflectcall && minalloc == 0 && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->stackguard) { // special case: called from reflect.call (framesize==1) // to call code with an arbitrary argument size, // and we have enough space on the current stack. // the new Stktop* is necessary to unwind, but // we don't need to create a new segment. top = (Stktop*)(m->morebuf.sp - sizeof(*top)); stk = (byte*)gp->stackguard - StackGuard; free = 0; } else { // allocate new segment. framesize += argsize; framesize += StackExtra; // room for more functions, Stktop. if(framesize < StackMin) framesize = StackMin; framesize += StackSystem; stk = runtime·stackalloc(framesize); top = (Stktop*)(stk+framesize-sizeof(*top)); free = framesize; } if(0) { runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n", framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, gp->stackbase); } top->stackbase = (byte*)gp->stackbase; top->stackguard = (byte*)gp->stackguard; top->gobuf = m->morebuf; top->argp = m->moreargp; top->argsize = argsize; top->free = free; m->moreargp = nil; m->morebuf.pc = nil; m->morebuf.sp = (uintptr)nil; // copy flag from panic top->panic = gp->ispanic; gp->ispanic = false; gp->stackbase = (uintptr)top; gp->stackguard = (uintptr)stk + StackGuard; sp = (byte*)top; if(argsize > 0) { sp -= argsize; dst = (uintptr*)sp; dstend = dst + argsize/sizeof(*dst); src = (uintptr*)top->argp; while(dst < dstend) *dst++ = *src++; } if(thechar == '5') { // caller would have saved its LR below args. sp -= sizeof(void*); *(void**)sp = nil; } // Continue as if lessstack had just called m->morepc // (the PC that decided to grow the stack). label.sp = (uintptr)sp; label.pc = (byte*)runtime·lessstack; label.g = m->curg; if(reflectcall) runtime·gogocallfn(&label, (FuncVal*)m->morepc); else runtime·gogocall(&label, m->morepc, m->cret); *(int32*)345 = 123; // never return }
//----------------------------------------------------------------------------- // Purpose: Tests all portals in the turret's vis for possible routes to see it's target point // Input : pOutVec - The location to aim at in order to hit the target ent, choosing least rotation if multiple // bConsiderNonPortalAimPoint - Output in pOutVec the non portal (direct) aimpoint if it requires the least rotation // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CNPC_RocketTurret::TestPortalsForLOS( Vector* pOutVec, bool bConsiderNonPortalAimPoint = false ) { // Aim at the target through the world CBaseEntity* pTarget = GetEnemy(); if ( !pTarget ) { return false; } Vector vAimPoint = pTarget->GetAbsOrigin() + (pTarget->WorldAlignMins() + pTarget->WorldAlignMaxs()) * 0.5f; int iPortalCount = CProp_Portal_Shared::AllPortals.Count(); if( iPortalCount == 0 ) { *pOutVec = vAimPoint; return false; } Vector vCurAim; AngleVectors( m_vecCurrentAngles.m_Value, &vCurAim ); vCurAim.NormalizeInPlace(); CProp_Portal **pPortals = CProp_Portal_Shared::AllPortals.Base(); Vector *portalAimPoints = (Vector *)stackalloc( sizeof( Vector ) * iPortalCount ); bool *bUsable = (bool *)stackalloc( sizeof( bool ) * iPortalCount ); float *fPortalDot = (float *)stackalloc( sizeof( float ) * iPortalCount ); // Test through any active portals: This may be a shorter distance to the target for( int i = 0; i != iPortalCount; ++i ) { CProp_Portal *pTempPortal = pPortals[i]; if( !pTempPortal->m_bActivated || (pTempPortal->m_hLinkedPortal.Get() == NULL) ) { //portalAimPoints[i] = vec3_invalid; bUsable[i] = false; continue; } bUsable[i] = FindAimPointThroughPortal( pPortals[ i ], &portalAimPoints[ i ] ); if ( 1 ) { QAngle goalAngles; Vector vecToEnemy = portalAimPoints[ i ] - EyePosition(); vecToEnemy.NormalizeInPlace(); // This value is for choosing the easiest aim point for the turret to see through. // 'Easiest' is the least rotation needed. fPortalDot[i] = DotProduct( vecToEnemy, vCurAim ); } } int iCountPortalsThatSeeTarget = 0; float fHighestDot = -1.0; if ( bConsiderNonPortalAimPoint ) { QAngle enemyRotToFace; Vector vecToEnemy = vAimPoint - EyePosition(); vecToEnemy.NormalizeInPlace(); fHighestDot = DotProduct( vecToEnemy, vCurAim ); } // Compare aim points, use the closest aim point which has direct LOS for( int i = 0; i != iPortalCount; ++i ) { if( bUsable[i] ) { // This aim point has direct LOS if ( TestLOS( portalAimPoints[ i ] ) && fHighestDot < fPortalDot[ i ] ) { *pOutVec = portalAimPoints[ i ]; fHighestDot = fPortalDot[ i ]; ++iCountPortalsThatSeeTarget; } } } return (iCountPortalsThatSeeTarget != 0); }
AI_Waypoint_t *CAI_Pathfinder::FindBestPath(int startID, int endID) { if ( !GetNetwork()->NumNodes() ) return NULL; int nNodes = GetNetwork()->NumNodes(); CAI_Node **pAInode = GetNetwork()->AccessNodes(); CVarBitVec openBS(nNodes); CVarBitVec closeBS(nNodes); // ------------- INITIALIZE ------------------------ float* nodeG = (float *)stackalloc( nNodes * sizeof(float) ); float* nodeH = (float *)stackalloc( nNodes * sizeof(float) ); float* nodeF = (float *)stackalloc( nNodes * sizeof(float) ); int* nodeP = (int *)stackalloc( nNodes * sizeof(int) ); // Node parent for (int node=0;node<nNodes;node++) { nodeG[node] = FLT_MAX; nodeP[node] = -1; } nodeG[startID] = 0; nodeH[startID] = 0.1*(pAInode[startID]->GetPosition(GetHullType())-pAInode[endID]->GetPosition(GetHullType())).Length(); // Don't want to over estimate nodeF[startID] = nodeG[startID] + nodeH[startID]; openBS.Set(startID); closeBS.Set( startID ); // --------------- FIND BEST PATH ------------------ while (!openBS.IsAllClear()) { int smallestID = CAI_Network::FindBSSmallest(&openBS,nodeF,nNodes); openBS.Clear(smallestID); CAI_Node *pSmallestNode = pAInode[smallestID]; if (GetOuter()->IsUnusableNode(smallestID, pSmallestNode->m_pHint)) continue; if (smallestID == endID) { AI_Waypoint_t* route = MakeRouteFromParents(&nodeP[0], endID); return route; } // Check this if the node is immediately in the path after the startNode // that it isn't blocked for (int link=0; link < pSmallestNode->NumLinks();link++) { CAI_Link *nodeLink = pSmallestNode->GetLinkByIndex(link); if (!IsLinkUsable(nodeLink,smallestID)) continue; // FIXME: the cost function should take into account Node costs (danger, flanking, etc). int moveType = nodeLink->m_iAcceptedMoveTypes[GetHullType()] & CapabilitiesGet(); int testID = nodeLink->DestNodeID(smallestID); Vector r1 = pSmallestNode->GetPosition(GetHullType()); Vector r2 = pAInode[testID]->GetPosition(GetHullType()); float dist = GetOuter()->GetNavigator()->MovementCost( moveType, r1, r2 ); // MovementCost takes ref parameters!! if ( dist == FLT_MAX ) continue; float new_g = nodeG[smallestID] + dist; if ( !closeBS.IsBitSet(testID) || (new_g < nodeG[testID]) ) { nodeP[testID] = smallestID; nodeG[testID] = new_g; nodeH[testID] = (pAInode[testID]->GetPosition(GetHullType())-pAInode[endID]->GetPosition(GetHullType())).Length(); nodeF[testID] = nodeG[testID] + nodeH[testID]; closeBS.Set( testID ); openBS.Set( testID ); } } } return NULL; }
int main( int argc, char **argv ) { SpewOutputFunc( VTF2TGAOutputFunc ); CommandLine()->CreateCmdLine( argc, argv ); MathLib_Init( 2.2f, 2.2f, 0.0f, 1.0f, false, false, false, false ); InitDefaultFileSystem(); const char *pVTFFileName = CommandLine()->ParmValue( "-i" ); const char *pTGAFileName = CommandLine()->ParmValue( "-o" ); bool bGenerateMipLevels = CommandLine()->CheckParm( "-mip" ) != NULL; if ( !pVTFFileName ) { Usage(); } if ( !pTGAFileName ) { pTGAFileName = pVTFFileName; } char pCurrentDirectory[MAX_PATH]; if ( _getcwd( pCurrentDirectory, sizeof(pCurrentDirectory) ) == NULL ) { fprintf( stderr, "Unable to get the current directory\n" ); return -1; } Q_StripTrailingSlash( pCurrentDirectory ); char pBuf[MAX_PATH]; if ( !Q_IsAbsolutePath( pTGAFileName ) ) { Q_snprintf( pBuf, sizeof(pBuf), "%s\\%s", pCurrentDirectory, pTGAFileName ); } else { Q_strncpy( pBuf, pTGAFileName, sizeof(pBuf) ); } Q_FixSlashes( pBuf ); char pOutFileNameBase[MAX_PATH]; Q_StripExtension( pBuf, pOutFileNameBase, MAX_PATH ); char pActualVTFFileName[MAX_PATH]; Q_strncpy( pActualVTFFileName, pVTFFileName, MAX_PATH ); if ( !Q_strstr( pActualVTFFileName, ".vtf" ) ) { Q_strcat( pActualVTFFileName, ".vtf", MAX_PATH ); } FILE *vtfFp = fopen( pActualVTFFileName, "rb" ); if( !vtfFp ) { Error( "Can't open %s\n", pActualVTFFileName ); exit( -1 ); } fseek( vtfFp, 0, SEEK_END ); int srcVTFLength = ftell( vtfFp ); fseek( vtfFp, 0, SEEK_SET ); CUtlBuffer buf; buf.EnsureCapacity( srcVTFLength ); int nBytesRead = fread( buf.Base(), 1, srcVTFLength, vtfFp ); fclose( vtfFp ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead ); IVTFTexture *pTex = CreateVTFTexture(); if (!pTex->Unserialize( buf )) { Error( "*** Error reading in .VTF file %s\n", pActualVTFFileName ); exit(-1); } Msg( "vtf width: %d\n", pTex->Width() ); Msg( "vtf height: %d\n", pTex->Height() ); Msg( "vtf numFrames: %d\n", pTex->FrameCount() ); Msg( "TEXTUREFLAGS_POINTSAMPLE=%s\n", ( pTex->Flags() & TEXTUREFLAGS_POINTSAMPLE ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_TRILINEAR=%s\n", ( pTex->Flags() & TEXTUREFLAGS_TRILINEAR ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPS=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPS ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPT=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPT ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPU=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPU ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_BORDER=%s\n", ( pTex->Flags() & TEXTUREFLAGS_BORDER ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ANISOTROPIC=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ANISOTROPIC ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_HINT_DXT5=%s\n", ( pTex->Flags() & TEXTUREFLAGS_HINT_DXT5 ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_SRGB=%s\n", ( pTex->Flags() & TEXTUREFLAGS_SRGB ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NORMAL=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NORMAL ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NOMIP=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NOMIP ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NOLOD=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NOLOD ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ALL_MIPS=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ALL_MIPS ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_PROCEDURAL=%s\n", ( pTex->Flags() & TEXTUREFLAGS_PROCEDURAL ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ONEBITALPHA=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ONEBITALPHA ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_EIGHTBITALPHA=%s\n", ( pTex->Flags() & TEXTUREFLAGS_EIGHTBITALPHA ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ENVMAP=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ENVMAP ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_RENDERTARGET=%s\n", ( pTex->Flags() & TEXTUREFLAGS_RENDERTARGET ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_DEPTHRENDERTARGET=%s\n", ( pTex->Flags() & TEXTUREFLAGS_DEPTHRENDERTARGET ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NODEBUGOVERRIDE=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NODEBUGOVERRIDE ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_SINGLECOPY=%s\n", ( pTex->Flags() & TEXTUREFLAGS_SINGLECOPY ) ? "true" : "false" ); Vector vecReflectivity = pTex->Reflectivity(); Msg( "vtf reflectivity: %f %f %f\n", vecReflectivity[0], vecReflectivity[1], vecReflectivity[2] ); Msg( "transparency: " ); if( pTex->Flags() & TEXTUREFLAGS_EIGHTBITALPHA ) { Msg( "eightbitalpha\n" ); } else if( pTex->Flags() & TEXTUREFLAGS_ONEBITALPHA ) { Msg( "onebitalpha\n" ); } else { Msg( "noalpha\n" ); } ImageFormat srcFormat = pTex->Format(); Msg( "vtf format: %s\n", ImageLoader::GetName( srcFormat ) ); int iTGANameLen = Q_strlen( pOutFileNameBase ); int iFaceCount = pTex->FaceCount(); int nFrameCount = pTex->FrameCount(); bool bIsCubeMap = pTex->IsCubeMap(); int iLastMipLevel = bGenerateMipLevels ? pTex->MipCount() - 1 : 0; for( int iFrame = 0; iFrame < nFrameCount; ++iFrame ) { for ( int iMipLevel = 0; iMipLevel <= iLastMipLevel; ++iMipLevel ) { int iWidth, iHeight, iDepth; pTex->ComputeMipLevelDimensions( iMipLevel, &iWidth, &iHeight, &iDepth ); for (int iCubeFace = 0; iCubeFace < iFaceCount; ++iCubeFace) { for ( int z = 0; z < iDepth; ++z ) { // Construct output filename char *pTempNameBuf = (char *)stackalloc( iTGANameLen + 13 ); Q_strncpy( pTempNameBuf, pOutFileNameBase, iTGANameLen + 1 ); char *pExt = Q_strrchr( pTempNameBuf, '.' ); if ( pExt ) { pExt = 0; } if ( bIsCubeMap ) { Assert( pTex->Depth() == 1 ); // shouldn't this be 1 instead of 0? static const char *pCubeFaceName[7] = { "rt", "lf", "bk", "ft", "up", "dn", "sph" }; Q_strcat( pTempNameBuf, pCubeFaceName[iCubeFace], iTGANameLen + 13 ); } if ( nFrameCount > 1 ) { char pTemp[4]; Q_snprintf( pTemp, 4, "%03d", iFrame ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if ( iLastMipLevel != 0 ) { char pTemp[8]; Q_snprintf( pTemp, 8, "_mip%d", iMipLevel ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if ( pTex->Depth() > 1 ) { char pTemp[6]; Q_snprintf( pTemp, 6, "_z%03d", z ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if( srcFormat == IMAGE_FORMAT_RGBA16161616F ) { Q_strcat( pTempNameBuf, ".pfm", iTGANameLen + 13 ); } else { Q_strcat( pTempNameBuf, ".tga", iTGANameLen + 13 ); } unsigned char *pSrcImage = pTex->ImageData( iFrame, iCubeFace, iMipLevel, 0, 0, z ); ImageFormat dstFormat; if( srcFormat == IMAGE_FORMAT_RGBA16161616F ) { dstFormat = IMAGE_FORMAT_RGB323232F; } else { if( ImageLoader::IsTransparent( srcFormat ) || (srcFormat == IMAGE_FORMAT_ATI1N ) || (srcFormat == IMAGE_FORMAT_ATI2N )) { dstFormat = IMAGE_FORMAT_BGRA8888; } else { dstFormat = IMAGE_FORMAT_BGR888; } } // dstFormat = IMAGE_FORMAT_RGBA8888; // dstFormat = IMAGE_FORMAT_RGB888; // dstFormat = IMAGE_FORMAT_BGRA8888; // dstFormat = IMAGE_FORMAT_BGR888; // dstFormat = IMAGE_FORMAT_BGRA5551; // dstFormat = IMAGE_FORMAT_BGR565; // dstFormat = IMAGE_FORMAT_BGRA4444; // printf( "dstFormat: %s\n", ImageLoader::GetName( dstFormat ) ); unsigned char *pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, dstFormat, false )]; if( !ImageLoader::ConvertImageFormat( pSrcImage, srcFormat, pDstImage, dstFormat, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( srcFormat ), ImageLoader::GetName( dstFormat ) ); exit( -1 ); } if( dstFormat != IMAGE_FORMAT_RGB323232F ) { if( ImageLoader::IsTransparent( dstFormat ) && ( dstFormat != IMAGE_FORMAT_RGBA8888 ) ) { unsigned char *tmpImage = pDstImage; pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, IMAGE_FORMAT_RGBA8888, false )]; if( !ImageLoader::ConvertImageFormat( tmpImage, dstFormat, pDstImage, IMAGE_FORMAT_RGBA8888, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( dstFormat ), ImageLoader::GetName( IMAGE_FORMAT_RGBA8888 ) ); } dstFormat = IMAGE_FORMAT_RGBA8888; } else if( !ImageLoader::IsTransparent( dstFormat ) && ( dstFormat != IMAGE_FORMAT_RGB888 ) ) { unsigned char *tmpImage = pDstImage; pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, IMAGE_FORMAT_RGB888, false )]; if( !ImageLoader::ConvertImageFormat( tmpImage, dstFormat, pDstImage, IMAGE_FORMAT_RGB888, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( dstFormat ), ImageLoader::GetName( IMAGE_FORMAT_RGB888 ) ); } dstFormat = IMAGE_FORMAT_RGB888; } CUtlBuffer outBuffer; TGAWriter::WriteToBuffer( pDstImage, outBuffer, iWidth, iHeight, dstFormat, dstFormat ); if ( !g_pFullFileSystem->WriteFile( pTempNameBuf, NULL, outBuffer ) ) { fprintf( stderr, "unable to write %s\n", pTempNameBuf ); } } else { PFMWrite( ( float * )pDstImage, pTempNameBuf, iWidth, iHeight ); } } } } } // leak leak leak leak leak, leak leak, leak leak (Blue Danube) return 0; }
FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ) { if ( !initInfo.m_pFileSystem || !initInfo.m_pDirectoryName ) return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_LoadSearchPaths: Invalid parameters specified." ); KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; FSReturnCode_t retVal = LoadGameInfoFile( initInfo.m_pDirectoryName, pMainFile, pFileSystemInfo, pSearchPaths ); if ( retVal != FS_OK ) return retVal; // All paths except those marked with |gameinfo_path| are relative to the base dir. char baseDir[MAX_PATH]; if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); initInfo.m_ModPath[0] = 0; #define GAMEINFOPATH_TOKEN "|gameinfo_path|" #define BASESOURCEPATHS_TOKEN "|all_source_engine_paths|" bool bLowViolence = IsLowViolenceBuild(); bool bFirstGamePath = true; for ( KeyValues *pCur=pSearchPaths->GetFirstValue(); pCur; pCur=pCur->GetNextValue() ) { const char *pPathID = pCur->GetName(); const char *pLocation = pCur->GetString(); if ( Q_stristr( pLocation, GAMEINFOPATH_TOKEN ) == pLocation ) { pLocation += strlen( GAMEINFOPATH_TOKEN ); FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, initInfo.m_pDirectoryName, pLocation, bLowViolence ); } else if ( Q_stristr( pLocation, BASESOURCEPATHS_TOKEN ) == pLocation ) { // This is a special identifier that tells it to add the specified path for all source engine versions equal to or prior to this version. // So in Orange Box, if they specified: // |all_source_engine_paths|hl2 // it would add the ep2\hl2 folder and the base (ep1-era) hl2 folder. // // 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 ); 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 ); } } else { FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, pLocation, bLowViolence ); } } pMainFile->deleteThis(); // // Set up search paths for add-ons // if ( IsPC() ) { #ifdef ENGINE_DLL FileSystem_UpdateAddonSearchPaths( initInfo.m_pFileSystem ); #endif } // these specialized tool paths are not used on 360 and cause a costly constant perf tax, so inhibited if ( IsPC() ) { // Create a content search path based on the game search path const char *pGameRoot = getenv( GAMEROOT_TOKEN ); const char *pContentRoot = getenv( CONTENTROOT_TOKEN ); if ( pGameRoot && pContentRoot ) { int nLen = initInfo.m_pFileSystem->GetSearchPath( "GAME", false, NULL, 0 ); char *pSearchPath = (char*)stackalloc( nLen * sizeof(char) ); initInfo.m_pFileSystem->GetSearchPath( "GAME", false, pSearchPath, nLen ); char *pPath = pSearchPath; while( pPath ) { char *pSemiColon = strchr( pPath, ';' ); if ( pSemiColon ) { *pSemiColon = 0; } Q_StripTrailingSlash( pPath ); Q_FixSlashes( pPath ); const char *pCurPath = pPath; pPath = pSemiColon ? pSemiColon + 1 : NULL; char pRelativePath[MAX_PATH]; char pContentPath[MAX_PATH]; if ( !Q_MakeRelativePath( pCurPath, pGameRoot, pRelativePath, sizeof(pRelativePath) ) ) continue; Q_ComposeFileName( pContentRoot, pRelativePath, pContentPath, sizeof(pContentPath) ); initInfo.m_pFileSystem->AddSearchPath( pContentPath, "CONTENT" ); } // Add the "platform" directory as a game searchable path char pPlatformPath[MAX_PATH]; Q_ComposeFileName( pGameRoot, "platform", pPlatformPath, sizeof(pPlatformPath) ); initInfo.m_pFileSystem->AddSearchPath( pPlatformPath, "GAME", PATH_ADD_TO_TAIL ); initInfo.m_pFileSystem->AddSearchPath( pContentRoot, "CONTENTROOT" ); initInfo.m_pFileSystem->AddSearchPath( pGameRoot, "GAMEROOT" ); } else { // Come up with some reasonable default int nLen = initInfo.m_pFileSystem->GetSearchPath( "MOD", false, NULL, 0 ); char *pSearchPath = (char*)stackalloc( nLen * sizeof(char) ); initInfo.m_pFileSystem->GetSearchPath( "MOD", false, pSearchPath, nLen ); char *pSemiColon = strchr( pSearchPath, ';' ); if ( pSemiColon ) { *pSemiColon = 0; } char pGameRootPath[MAX_PATH]; Q_strncpy( pGameRootPath, pSearchPath, sizeof(pGameRootPath) ); Q_StripTrailingSlash( pGameRootPath ); Q_StripFilename( pGameRootPath ); char pContentRootPath[MAX_PATH]; Q_strncpy( pContentRootPath, pGameRootPath, sizeof(pContentRootPath) ); char *pGame = Q_stristr( pContentRootPath, "game" ); if ( pGame ) { Q_strcpy( pGame, "content" ); } initInfo.m_pFileSystem->AddSearchPath( pContentRootPath, "CONTENTROOT" ); initInfo.m_pFileSystem->AddSearchPath( pGameRootPath, "GAMEROOT" ); } // Also, mark specific path IDs as "by request only". That way, we won't waste time searching in them // when people forget to specify a search path. initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "contentroot", true ); initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "gameroot", true ); initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "content", true ); } // Also, mark specific path IDs as "by request only". That way, we won't waste time searching in them // 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( "mod", true ); // Add the write path last. if ( initInfo.m_ModPath[0] != 0 ) { initInfo.m_pFileSystem->AddSearchPath( initInfo.m_ModPath, "DEFAULT_WRITE_PATH", PATH_ADD_TO_TAIL ); } #ifdef _DEBUG initInfo.m_pFileSystem->PrintSearchPaths(); #endif #if defined( ENABLE_RUNTIME_STACK_TRANSLATION ) && !defined( _X360 ) //copy search paths to stack tools so it can grab pdb's from all over. But only on P4 or Steam Beta builds if( (CommandLine()->FindParm( "-steam" ) == 0) || //not steam (CommandLine()->FindParm( "-internalbuild" ) != 0) ) //steam beta is ok { char szSearchPaths[4096]; //int CBaseFileSystem::GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) int iLength1 = initInfo.m_pFileSystem->GetSearchPath( "EXECUTABLE_PATH", false, szSearchPaths, 4096 ); if( iLength1 == 1 ) iLength1 = 0; int iLength2 = initInfo.m_pFileSystem->GetSearchPath( "GAMEBIN", false, szSearchPaths + iLength1, 4096 - iLength1 ); if( (iLength2 > 1) && (iLength1 > 1) ) { szSearchPaths[iLength1 - 1] = ';'; //replace first null terminator } const char *szAdditionalPath = CommandLine()->ParmValue( "-AdditionalPDBSearchPath" ); if( szAdditionalPath && szAdditionalPath[0] ) { int iLength = iLength1; if( iLength2 > 1 ) iLength += iLength2; if( iLength != 0 ) { szSearchPaths[iLength - 1] = ';'; //replaces null terminator } V_strncpy( &szSearchPaths[iLength], szAdditionalPath, 4096 - iLength ); } //Append the perforce symbol server last. Documentation says that "srv*\\perforce\symbols" should work, but it doesn't. //"symsrv*symsrv.dll*\\perforce\symbols" which the docs say is the same statement, works. { V_strncat( szSearchPaths, ";symsrv*symsrv.dll*\\\\perforce\\symbols", 4096 ); } SetStackTranslationSymbolSearchPath( szSearchPaths ); //MessageBox( NULL, szSearchPaths, "Search Paths", 0 ); } #endif return FS_OK; }
// Called from reflect·call or from runtime·morestack when a new // stack segment is needed. Allocate a new stack big enough for // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, // and then act as though runtime·lessstack called the function at // m->morepc. // 当需要一个新的栈段时调用,被reflect.call或者runtime.morestack调用 // 分配一个足够大的新栈,至少大于m->moreframesize。将m->moreargsize字节复制到新的栈帧。 // 然后伪装成在m->morepc处调用函数runtime.lessstack的样子。 void runtime·newstack(void) { int32 framesize, minalloc, argsize; Stktop *top; byte *stk, *sp; uintptr *src, *dst, *dstend; G *gp; Gobuf label; bool reflectcall; uintptr free; framesize = m->moreframesize; argsize = m->moreargsize; gp = m->curg; if(m->morebuf.sp < gp->stackguard - StackGuard) { //栈已经溢出 runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, gp->stackguard - StackGuard); runtime·throw("runtime: split stack overflow"); } if(argsize % sizeof(uintptr) != 0) { //参数未对齐 runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize); runtime·throw("runtime: stack split argsize"); } minalloc = 0; reflectcall = framesize==1; if(reflectcall) { framesize = 0; // moreframesize_minalloc is only set in runtime·gc(), // that calls newstack via reflect·call(). minalloc = m->moreframesize_minalloc; m->moreframesize_minalloc = 0; if(framesize < minalloc) framesize = minalloc; } if(reflectcall && minalloc == 0 && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->stackguard) { // special case: called from reflect.call (framesize==1) // to call code with an arbitrary argument size, // and we have enough space on the current stack. // the new Stktop* is necessary to unwind, but // we don't need to create a new segment. top = (Stktop*)(m->morebuf.sp - sizeof(*top)); stk = (byte*)gp->stackguard - StackGuard; free = 0; } else { // 分配新空间 // framesize大小,必须包含参数大小部分,为调用runtime.morestack保留部分,并且至少大于StackMin。然后还要加上StackSystem部分 framesize += argsize; framesize += StackExtra; // room for more functions, Stktop. if(framesize < StackMin) framesize = StackMin; framesize += StackSystem; stk = runtime·stackalloc(framesize); top = (Stktop*)(stk+framesize-sizeof(*top)); free = framesize; } if(0) { runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n", framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, gp->stackbase); } //将一些重要信息从结构体g中移到栈顶Stktop中 top->stackbase = (byte*)gp->stackbase; top->stackguard = (byte*)gp->stackguard; top->gobuf = m->morebuf; //只是借助m结构体临时传了一下参数,morebuf中记录的是栈空间不够的那个函数的pc,sp,g top->argp = m->moreargp; //参数 top->argsize = argsize; //参数大小 top->free = free; //可用空间大小 m->moreargp = nil; m->morebuf.pc = nil; m->morebuf.sp = (uintptr)nil; // copy flag from panic top->panic = gp->ispanic; gp->ispanic = false; gp->stackbase = (uintptr)top; gp->stackguard = (uintptr)stk + StackGuard; //每个goroutine的g->stackguard设置成指向栈底上面StackGuard的位置。 //装饰栈顶的参数区域 sp = (byte*)top; if(argsize > 0) { //将参数移过来 sp -= argsize; dst = (uintptr*)sp; dstend = dst + argsize/sizeof(*dst); src = (uintptr*)top->argp; while(dst < dstend) *dst++ = *src++; } if(thechar == '5') { //编译器标识 // caller would have saved its LR below args. sp -= sizeof(void*); *(void**)sp = nil; } // Continue as if lessstack had just called m->morepc // (the PC that decided to grow the stack). // 继续,伪装成好像是从m->morepc中调用lessstack函数的状态 // 跳转 label.sp = (uintptr)sp; label.pc = (byte*)runtime·lessstack; label.g = m->curg; if(reflectcall) runtime·gogocallfn(&label, (FuncVal*)m->morepc); else runtime·gogocall(&label, m->morepc, m->cret); //gogocall相当于一个直接的jmp,不是按函数协议跳转的 *(int32*)345 = 123; // never return }
// Hook used by runtime·malg to call runtime·stackalloc on the // scheduler stack. This exists because runtime·stackalloc insists // on being called on the scheduler stack, to avoid trying to grow // the stack while allocating a new stack segment. static void mstackalloc(G *gp) { gp->param = runtime·stackalloc((uintptr)gp->param); runtime·gogo(&gp->sched, 0); }
void EmitDispLMAlphaAndNeighbors() { int i; Msg( "Finding displacement neighbors...\n" ); // Build the CCoreDispInfos. CUtlVector<dface_t*> faces; // Create the core dispinfos and init them for use as CDispUtilsHelpers. for ( int iDisp = 0; iDisp < nummapdispinfo; ++iDisp ) { CCoreDispInfo *pDisp = new CCoreDispInfo; if ( !pDisp ) { g_CoreDispInfos.Purge(); return; } int nIndex = g_CoreDispInfos.AddToTail(); pDisp->SetListIndex( nIndex ); g_CoreDispInfos[nIndex] = pDisp; } for ( i=0; i < nummapdispinfo; i++ ) { g_CoreDispInfos[i]->SetDispUtilsHelperInfo( g_CoreDispInfos.Base(), nummapdispinfo ); } faces.SetSize( nummapdispinfo ); int nMemSize = texinfo.Count() * sizeof(int); int *pSwappedTexInfos = (int*)stackalloc( nMemSize ); memset( pSwappedTexInfos, 0xFF, nMemSize ); for( i = 0; i < numfaces; i++ ) { dface_t *pFace = &dfaces[i]; if( pFace->dispinfo == -1 ) continue; mapdispinfo_t *pMapDisp = &mapdispinfo[pFace->dispinfo]; // Set the displacement's face index. ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo]; pDisp->m_iMapFace = i; // Get a CCoreDispInfo. All we need is the triangles and lightmap texture coordinates. CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[pFace->dispinfo]; DispMapToCoreDispInfo( pMapDisp, pCoreDispInfo, pFace, pSwappedTexInfos ); faces[pFace->dispinfo] = pFace; } stackfree( pSwappedTexInfos ); // Generate and export neighbor data. ExportNeighborData( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo ); // Generate and export the active vert lists. ExportAllowedVertLists( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo ); // Now that we know which vertices are actually going to be around, snap the ones that won't // be around onto the slightly-reduced mesh. This is so the engine's ray test code and // overlay code works right. SnapRemainingVertsToSurface( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo ); Msg( "Finding lightmap sample positions...\n" ); for ( i=0; i < nummapdispinfo; i++ ) { dface_t *pFace = faces[i]; ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo]; CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[i]; pDisp->m_iLightmapSamplePositionStart = g_DispLightmapSamplePositions.Count(); CalculateLightmapSamplePositions( pCoreDispInfo, pFace, g_DispLightmapSamplePositions ); } StartPacifier( "Displacement Alpha : "); // Build lightmap alphas. int dispCount = 0; // How many we've processed. for( i = 0; i < nummapdispinfo; i++ ) { dface_t *pFace = faces[i]; Assert( pFace->dispinfo == i ); ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo]; // Allocate space for the alpha values. pDisp->m_iLightmapAlphaStart = 0; // not used anymore ++dispCount; } EndPacifier(); }