// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int AggregateCopyPropagation::ExtractCopySetInfo(CallInstr* instr, Operand*& destOp) {
    DebugValidator::IsNotNull(instr);

    // Check if we have a call to 'copyMemory' or
    // 'setMemory' that targets records or arrays.
    if(auto intrinsic = instr->GetIntrinsic()) {
        bool valid = false;
        bool isCopy;
        destOp = WithoutPointerCasts(CopyMemoryIntr::GetDestination(instr));

        if(intrinsic->Is<CopyMemoryIntr>()) {
            // The copy is valid only if the whole object
            // is copied using a constant size argument.
            auto destType = destOp->GetType()->As<PointerType>()->PointeeType();
            
            if(destType->IsRecord() || destType->IsArray()) {
                if(auto intConst = CopyMemoryIntr::GetLength(instr)->As<IntConstant>()) {
                    int size = TI::GetSize(destType, GetTarget());
                    valid = intConst->Value() == size;
                }
            }

            isCopy = true;
        }
        else if(intrinsic->Is<SetMemoryIntr>()) {
            // The copy is valid only if the whole object
            // is set using a constant size argument and a constant value.
            auto destType = destOp->GetType()->As<PointerType>()->PointeeType();

            if(destType->IsRecord() || destType->IsArray()) {
                if(auto intConst = SetMemoryIntr::GetLength(instr)->As<IntConstant>()) {
                    int size = TI::GetSize(destType, GetTarget());

                    // Check that the value that is set is a constant.
                    valid = (intConst->Value() == size) &&
                            (SetMemoryIntr::GetSource(instr)->IsIntConstant());
                }
            }

            isCopy = false;
        }

        if(valid) {
            return AddInfo(instr, isCopy);
        }
    }

    return -1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VariableAnalysis::MarkAddressTaken(Instruction* instr) {
	if(auto loadInstr = instr->As<LoadInstr>()) {
		// Volatile loads should not be eliminated.
		if(loadInstr->IsVolatile()) {
			if(auto variableRef = loadInstr->SourceOp()->As<VariableReference>()) {
				auto localVar = variableRef->GetVariable();
				
                if(localVar == nullptr) {
                    return;
                }
                
                localVar->SetIsAddresTaken(true);
			}
		}

		return; // We're done with this instruction.
	}
	else if(auto storeInstr = instr->As<StoreInstr>()) {
		// Volatile stores should not be eliminated.
		if(storeInstr->IsVolatile()) {
			if(auto variableRef = storeInstr->DestinationOp()->As<VariableReference>()) {
				auto localVar = variableRef->GetVariable();
				
                if(localVar == nullptr) {
                    return;
                }

				localVar->SetIsAddresTaken(true);
			}
		}

		// If the stored operand is a local variable we can't eliminate it.
		if(storeInstr->SourceOp()->IsLocalVariableRef()) {
			auto variableRef = storeInstr->SourceOp()->As<VariableReference>();
            variableRef->GetVariable()->SetIsAddresTaken(true);
		}

		return; // We're done with this instruction.
	}

	// Any other instruction that has a variable reference as it's operand
	// is considered to take it's address.
	for(int i = 0; i < instr->SourceOpCount(); i++) {
		if(auto variableRef = instr->GetSourceOp(i)->As<VariableReference>()) {
			auto localVar = variableRef->GetVariable();

			if(localVar == nullptr) {
                continue;
            }

			// We don't set the flag for pointers, arrays and records because
			// we have a separate step that takes care of this.
			if((localVar->IsPointer() || 
                localVar->IsRecord()  ||
				localVar->IsArray()) == false) {
                localVar->SetIsAddresTaken(true);
			}
		}
	}
}
Exemple #3
0
bool FormatRecord (const std::string &path)
{
	auto record = 0;
	if (!IsRecord(path, &record))
		throw util::exception("invalid record path");

	throw std::logic_error("not implemented");
#if 0
	auto hdd_path = path.substr(0, path.rfind(':'));
	auto hdd = HDD::OpenDisk(hdd_path);

	if (!hdd)
		return Error("open");

	// The disk signature is part of record 1, so unformatting is dangerous
	if (record == 1 && opt.nosig == 1)
		throw util::exception("unformatting record 1 would destroy BDOS signature!");

	auto olddisk = std::make_shared<DISK>();
	MEMORY mem(MGT_TRACK_SIZE);

	for (BYTE cyl = 0; cyl < NORMAL_TRACKS; ++cyl)
		for (BYTE head = 0; head < NORMAL_SIDES; ++head)
			olddisk->FormatRegularTrack(cyl, head, &fmtMGT, mem);

	return !WriteRecord(hdd.get(), record, *olddisk, true);
#endif
}
Exemple #4
0
// ---------------------------------------
void MTRecord::SetDateRange(time_t tValidFrom, time_t tValidTo)
{
    m_ValidFrom = tValidFrom;
    m_ValidTo   = tValidTo;
    // ----------------------------------------------------------
    time_t tCurrentTime = static_cast<time_t>(OTAPI_Wrap::GetTime());
    // ----------------------------------------------------------
    if ((tValidTo > 0) && (tCurrentTime > tValidTo) && !IsMail() && !IsRecord())
        SetExpired();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VariableAnalysis::InsertAggregateCandidates(OperandVariableDict& dict, 
                                                 const VariableList& varList) {
    auto unit = funct_->ParentUnit();

    for(int i = 0; i < varList.Count(); i++) {
        auto variable = varList[i];

        if((variable->IsArray()  || 
            variable->IsRecord() || 
            variable->IsPointer()) == false) {
            continue;
        }

        variable->SetIsAddresTaken(false); // Presume it's not.
        auto variableRefType = unit->Types().GetPointer(variable->GetType());
        auto variableRef = unit->References().GetVariableRef(variable, variableRefType);

        dict.Add(variableRef, OVPair(variableRef, variable));
    }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SimpleDeadCodeElimination::RemoveDeadStores(Function* function) {
    // This implements a flow-insensitive algorithm that scan the whole function 
    // and collect all the 'store' instructions that target an array/record
    // whose address is not taken. Analyzing this set we may be able to delete
    // dead 'store' instructions.
    auto& variables = function->Variables();
    storesRemoved_ = 0;

    // We process each variable, one by one, and use a very conservative approach
    // (any suspect operation renders all stores live, even if they probably aren't).
    for(int i = 0; i < variables.Count(); i++) {
        auto variable = variables[i];

        if((variable->IsArray() || variable->IsRecord()) == false) {
            continue;
        }
        else if(variable->IsAddressTaken()) {
            continue;
        }

        // Collect all 'store' instructions that write to this variable.
        StoreCollection stores;
        CollectStoreInstructions(variable, stores, function);

        if(stores.StoreList.Count() > 0) {
            DetermineLiveStores(variable, stores, function);

            // Remove all stores that are definitely dead.
            for(int j = 0; j < stores.StoreList.Count(); j++) {
                InstructionRemoved(stores.StoreList[j].Target);
                stores.StoreList[j].Target->RemoveFromBlock(true /* free */);
                storesRemoved_++;
            }
        }
    }
}
Exemple #7
0
// ---------------------------------------
bool MTRecord::FormatDescription(std::string & str_output)
{
    OTString strDescription, strStatus, strKind;

    if (IsRecord())
    {
        if (IsExpired())
            strStatus = "(EXPIRED)"; // How to tell difference between instrument that processed successfully and THEN expired, versus one that expired before processing successfully? (See next comment.)
        else if (IsInvoice())
            strStatus = "(payment sent)";  // TODO: need an "invalid records" box for expired and canceled. Otherwise we may falsely assume "payment sent" when actually it expired. (We may also falsely assume payment expired when actually it was sent.) Solution is a new box.
        else
            strStatus = "";
//          strStatus = "(record)";
    }
    // -----------------------------
    else if (IsPending())
    {
        if (IsExpired())
            strStatus = "(EXPIRED)";
        else if (IsInvoice())
            strStatus = "(unpaid)";
        else if (!IsCash())
            strStatus = "(pending)";
    }
    // -----------------------------
    if (IsCanceled())
    {
        strStatus = "(CANCELED)";

        if (IsOutgoing() || IsReceipt())
            strKind.Format("%s", "sent ");
    }
    // -----------------------------
    else
    {
        if (IsOutgoing())
            strKind.Format("%s",
                           ((IsPending() && !IsCash()) ? "outgoing " : "sent "));
        else // incoming.
            strKind.Format("%s",
                           IsPending() ? "incoming " : (IsReceipt() ? "" : "received "));
    }
    // -----------------------------
    OTString strTransNumForDisplay;

    if (!IsCash())
        strTransNumForDisplay.Format(" #%ld", GetTransNumForDisplay());
    // -----------------------------
    if (IsRecord())
    {
        if (this->IsTransfer())
            strDescription.Format("%s%s%s %s", strKind.Get(), "transfer", strTransNumForDisplay.Get(), strStatus.Get());
        else if (this->IsVoucher())
            strDescription.Format("%s%s%s %s", strKind.Get(), "payment", strTransNumForDisplay.Get(), strStatus.Get());
        else if (this->IsReceipt())
        {
            std::string str_instrument_type;

            if (0 == GetInstrumentType().compare("transferReceipt"))
                str_instrument_type = "transfer";
            else if (0 == GetInstrumentType().compare("finalReceipt"))
                str_instrument_type = "final receipt (closed)";
            else if (0 == GetInstrumentType().compare("chequeReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);

                // I paid OUT when this chequeReceipt came through. It must be a normal cheque that I wrote.
                if (lAmount <= 0) // Notice less than OR EQUAL TO 0 -- that's because a canceled cheque has a 0 value.
                    str_instrument_type = "cheque";
                else // I GOT PAID when this chequeReceipt came through. It must be an invoice I wrote, that someone paid.
                {
                    if (IsCanceled())
                        str_instrument_type = "invoice";
                    else
                        str_instrument_type = "invoice (payment received)";
                }
            }
            else if (0 == GetInstrumentType().compare("voucherReceipt"))
            {
                str_instrument_type = "payment";
            }
            else if (0 == GetInstrumentType().compare("paymentReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);

                if (!IsCanceled() && (lAmount > 0))
                    strKind.Set("received ");

                str_instrument_type = "recurring payment";
            }

            strDescription.Format("%s%s%s %s", strKind.Get(), str_instrument_type.c_str(), strTransNumForDisplay.Get(), strStatus.Get());
        }
        else
            strDescription.Format("%s%s%s %s", strKind.Get(), GetInstrumentType().c_str(), strTransNumForDisplay.Get(), strStatus.Get());
    }
    else
    {
        if (this->IsTransfer())
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), "transfer", strTransNumForDisplay.Get());
        else if (this->IsVoucher())
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), "payment", strTransNumForDisplay.Get());

        else if (this->IsReceipt())
        {
            std::string str_instrument_type;

            if (0 == GetInstrumentType().compare("transferReceipt"))
            {
                if (IsCanceled())
                    str_instrument_type = "transfer";
                else
                    str_instrument_type = "transfer (receipt)";
            }
            else if (0 == GetInstrumentType().compare("finalReceipt"))
                str_instrument_type = "final receipt";
            else if (0 == GetInstrumentType().compare("chequeReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);

                // I paid OUT when this chequeReceipt came through. It must be a normal cheque that I wrote.
                if (lAmount <= 0) // Notice less than OR EQUAL TO 0 -- that's because a canceled cheque has a 0 value.
                {
                    if (IsCanceled())
                        str_instrument_type = "cheque";
                    else
                        str_instrument_type = "cheque (receipt)";
                }
                else // I GOT PAID when this chequeReceipt came through. It must be an invoice I wrote, that someone paid.
                {
                    if (IsCanceled())
                        str_instrument_type = "invoice";
                    else
                        str_instrument_type = "sent invoice (receipt: payment received)";
                }
            }
            else if (0 == GetInstrumentType().compare("voucherReceipt"))
            {
                if (IsCanceled())
                    str_instrument_type = "payment";
                else
                    str_instrument_type = "payment (receipt)";
            }
            else if (0 == GetInstrumentType().compare("paymentReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);

                if (!IsCanceled() && (lAmount > 0))
                    strKind.Set("received ");

                str_instrument_type = "recurring payment (receipt)";
            }

            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), str_instrument_type.c_str(), strTransNumForDisplay.Get());
        }
        else
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), GetInstrumentType().c_str(), strTransNumForDisplay.Get());
    }
    // -----------------------------
    str_output = strDescription.Get();
    // -----------------------------
    return (!str_output.empty());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SimpleDeadCodeElimination::RemoveDeadCopyOperations(Function* function) {
    // After other optimizations there often remain aggregate
    // copy/set operations that are not needed anymore,
    // because the aggregate is not referenced (besides by these calls).
    // This is a flow-insensitive algorithm that counts the number
    // of times a variable is referenced, and compares it with
    // the number of times it's referenced by a copy/set call.
    // If the numbers are equal the operations are dead and the variable
    // can later be removed.
    CopySetDict copySetInfo;

    for(int i = 0; i < function->VariableCount(); i++) {
        auto variable = function->GetVariable(i);

        if(variable->IsArray() || variable->IsRecord()) {
            copySetInfo.Add(variable, CopySetInfo(variable));
        }
    }

    // If there are no aggregate variables there is
    // no reason to scan the function body.
    if(copySetInfo.Count() == 0) {
        return;
    }

    function->ForEachInstruction([&copySetInfo, this](Instruction* instr) -> bool {
        // Most instructions can't reference a variable directly.
        if(instr->IsArithmetic() || instr->IsLogical()) {
            return true;
        }

        // Check if we have a 'call' to 'copyMemory'/'setMemory'.
        if(auto callInstr = instr->As<CallInstr>()) {
            if(AnalyzeDeadCopyCall(callInstr, copySetInfo)) {
                // Don't analyze the operands again.
                return true;
            }
        }

        // Check if any operands are variable references.
        for(int i = 0; i < instr->SourceOpCount(); i++) {
            if(auto variableRef = instr->GetSourceOp(i)->As<VariableReference>()) {
                if(auto variable = variableRef->GetVariable()) {
                    if(copySetInfo.ContainsKey(variable)) {
                        // Count the access.
                        copySetInfo[variable].References++;
                    }
                }
            }
        }

        return true;
    });

    // Delete any copy/set operation that is not needed.
    copySetInfo.ForEachValue([](CopySetInfo& info) -> bool {
        if(info.References == info.CopySetReferences) {
            for(int i = 0; i < info.CopySetCalls.Count(); i++) {
                info.CopySetCalls[i]->RemoveFromBlock(true);
            }
        }
        return true;
    });
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Operand* ConstantFolder::LoadFromOffset(Initializer* initializer, const Type* sourceType,
										const Type* loadType, __int64 offset) {
	DebugValidator::IsNotNull(initializer);
	DebugValidator::IsLargerOrEqual(offset, 0);

	// If the initializer is an initializer list, try to see at which position
	// the initializer indicated by the offset is found.
	if(initializer->IsInitializerList()) {
		auto initList = static_cast<InitializerList*>(initializer);
		
		if(auto arrayType = sourceType->As<ArrayType>()) {
			// If it's an array type we can compute the index directly.
			auto elementType = arrayType->ElementType();
			__int64 elemSize = TypeInfo::GetSize(elementType, target_);
			__int64 childIndex = offset / elemSize;
			DebugValidator::IsSmaller(childIndex, arrayType->Size());

			// We need to test for the case in which the offset lies between
			// two elements in an array. Consider the following case:
			// const int a[] = {1,2,3,4};
			// *((short*)((char*)a + 3)) - data from both 1 and 2 is loaded.
			if((elementType->IsArray() || elementType->IsRecord()) == false) {
				__int64 childOffset = offset % elemSize;
				__int64 loadSize = TypeInfo::GetSize(loadType, target_);

				// Note that this also catches the case when the data to be loaded
				// is larger than the size of the array element.
				if((childOffset + loadSize) > elemSize) {
					return LoadFromMultipleArray(initList, childIndex, childOffset,
												 arrayType, loadType);
				}
			}

			return LoadFromOffset((*initList)[childIndex], arrayType->ElementType(),
								  loadType, offset - (childIndex * elemSize));
		}
		else if(auto recordType = sourceType->As<RecordType>()) {
			// For records we need to iterate all the fields 
			// until we find a suitable one.
			auto& fields = recordType->Fields();

			for(int i = 0; i < fields.Count(); i++) {
				const RecordField& field = fields[i];
				__int64 fieldOffset = field.FieldOffset;
				__int64 fieldSize = TypeInfo::GetSize(field.FieldType, target_);

				if(offset < (fieldOffset + fieldSize)) {
					// If we need to load from two fields we give up; most of the time
					// it can't be performed (there may be padding between fields),
					// it would be complicated and this situation shouldn't actually
					// occur in a standard-conforming application.
					__int64 loadSize = TypeInfo::GetSize(loadType, target_);

					if((offset + loadSize) > (fieldOffset + fieldSize)) {
                        return nullptr;
                    }

					return LoadFromOffset((*initList)[i], field.FieldType, 
										  loadType, offset - fieldOffset);
				}
			}
		}

		// The offset is invalid, give up.
		return nullptr;
	}

	if(initializer->Conversion() == InitConv_PointerToPointer) {
		// Frequently used for strings, like in the following example:
		// var a int8* = ptop("abcd", int8*)
		if(auto stringConst = initializer->Value()->As<StringConstant>()) {
			return LoadFromString(stringConst, loadType, offset);
		}

		// All other cases are not supported.
		return nullptr;
	}

	// We should load the operand from the initializer.
	return LoadFromInitializer(initializer, loadType, offset);
}
bool MultiPlayer::IsRecord(shared_ptr<OnePlayer> onePlayer)
{
	return IsRecord(onePlayer->mid);
}
Exemple #11
0
void SceneManager::FrameMove()
{
   //更新时间
  static int index = 0; 
	
	if(m_Stop)return;//暂停动画

   frameTime = m_Timer.tick();

   
   //更新粒子系统
   // Slows fireworks, but not camera
   if(kSlowMotion) frameTime *= 0.5f;
  

   if(m_Fps!=0)
   {
    frameTime = 1/(float)m_Fps; 

   }
   //更新照像机
   m_Camera.Update(m_ParticleSystem.particles,frameTime,m_ParticleSystem.last_particle);


   m_ParticleSystem.AllocNewParticle();//增加新粒子空间
  
   //是否暂停动画
   if(!kFireworks) return; //如果暂停动画返回
	
   //更新世界
   theWorld.update(frameTime);
	
   //减淡
   static float ambientlight = float(dAmbient) * 0.01f;
   for(unsigned int i=0; i<m_ParticleSystem.last_particle; ++i)
   {
	 Particle* darkener(&(m_ParticleSystem.particles[i]));
	 if(darkener->type == SMOKE) darkener->rgb[0] = darkener->rgb[1] = darkener->rgb[2] = ambientlight;
   }

	//改变火箭发射速率
    static float rocketTimer[6] = {0,0,0,0,0,0};
	static float rocketTimeConst[6] = {5.0f,25,40,35,50,55};
	static float changeRocketTimeConst[6] ={25,50,65,65,50,50};
	

	for(int i=0;i<6;i++)
	{
     changeRocketTimeConst[i] -= frameTime;
     if(changeRocketTimeConst[i] <= 0.0f)
	{
	 float temp = rsRandf(4.0f);
	 //rocketTimeConst[i] = (temp * temp) + (10.0f / float(dMaxrockets));
	 changeRocketTimeConst[i] = rsRandf(30.0f) + 10.0f;
	}
     rocketTimer[i] -= frameTime;
	}

	//发射火箭
	
	if(rocketTimer[0] <= 0.0f)//生存期结束
	{
	   Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子

	   //初始化火箭 //确定火箭类型
	   rock->xyz[0] = rsRandf(20.0f);// - 900.0f;
	   rock->xyz[1] = 5.0f;
	   rock->xyz[2] = rsRandf(20.0f);// - 900.0f;
	   rock->initRocket();
       int y =rsRandi(8);
	  

	   if(index==2)
	   {
         rock->explosiontype =6; 
	   }
	   else if(index==5)
	   {
         rock->explosiontype =6; 
	   }
	   else if(index==8)
	   {
         rock->explosiontype =6; 
	   }
	   else
	   {
	   rock->m_Fire = &m_CFire[index];
	   m_CFire[index].m_Exploded = false;//未爆炸
	    m_CFire[index].m_Boom = false; 
	   rock->explosiontype =22; 
	   }
	   index++;
	   index = index%11;
	   
	   
	 
	   if(dMaxrockets) rocketTimer[0] = rocketTimeConst[0];//火箭时间
		else rocketTimer[0] = 60.0f;  // arbitrary number since no rockets ever fire	
	}
   /*if(rocketTimer[1] <= 0.0f)//生存期结束
	{
	   Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子

	   //初始化火箭 //确定火箭类型
	   rock->xyz[0] = rsRandf(200.0f);// + 800.0f;
	   rock->xyz[1] = 5.0f;
	   rock->xyz[2] = rsRandf(200.0f);// + 500.0f;
	   rock->initRocket();
	    if(rsRandi(2))
	   rock->m_Fire = &m_CFire[1];
		else rock->m_Fire = &m_CFire[5];
	   rock->explosiontype = 22; 
       if(dMaxrockets) rocketTimer[1] = rsRandf(rocketTimeConst[1]);//火箭时间
	   else rocketTimer[1] = 60.0f;  // arbitrary number since no rockets ever fire	

	   }
	if(rocketTimer[2] <= 0.0f)//生存期结束
	{
	  Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子

	   //初始化火箭 //确定火箭类型
	   rock->xyz[0] = rsRandf(200.0f) + 700.0f;
	   rock->xyz[1] = 5.0f;
	   rock->xyz[2] = rsRandf(200.0f) - 500.0f;
	   rock->initRocket();
	   if(rsRandi(2))
	   rock->m_Fire = &m_CFire[2];
	   else rock->m_Fire = &m_CFire[6];
	   rock->explosiontype = 22; 
	   		 
	  
		if(dMaxrockets) rocketTimer[2] = rsRandf(rocketTimeConst[2]);//火箭时间
		else rocketTimer[2] = 60.0f;  // arbitrary number since no rockets ever fire	
	}
	if(rocketTimer[3] <= 0.0f)//生存期结束
	{
	   Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子

	   //初始化火箭 //确定火箭类型
	   rock->xyz[0] = rsRandf(200.0f) - 500.0f;
	   rock->xyz[1] = 5.0f;
	   rock->xyz[2] = rsRandf(200.0f) + 700.0f;
	   rock->initRocket();
	   if(rsRandi(2))
	   rock->m_Fire = &m_CFire[3];
	   else rock->m_Fire = &m_CFire[7];
	   rock->explosiontype = 22; 
	   if(dMaxrockets) rocketTimer[3] = rsRandf(rocketTimeConst[3]);//火箭时间
		else rocketTimer[3] = 60.0f;  // arbitrary number since no rockets ever fire	
	}
	if(rocketTimer[4] <= 0.0f)//生存期结束
	{
	   Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子

	   //初始化火箭 //确定火箭类型
	   rock->xyz[0] = rsRandf(200.0f) - 1000.0f;
	   rock->xyz[1] = 5.0f;
	   rock->xyz[2] = rsRandf(200.0f) + 500.0f;
	   rock->initRocket();
	   rock->explosiontype = 3; 
	   if(dMaxrockets) rocketTimer[4] = rsRandf(rocketTimeConst[4]);//火箭时间
		else rocketTimer[4] = 60.0f;  // arbitrary number since no rockets ever fire	
	}
	if(rocketTimer[5] <= 0.0f)//生存期结束
	{
	   Particle* rock = m_ParticleSystem.AddParticle();//火箭粒子

	   //初始化火箭 //确定火箭类型
	   rock->xyz[0] = rsRandf(200.0f) - 1300.0f;
	   rock->xyz[1] = 5.0f;
	   rock->xyz[2] = rsRandf(200.0f) + 500.0f;
	   rock->initRocket();
	   rock->explosiontype = 4; 
	   if(dMaxrockets) rocketTimer[5] = rsRandf(rocketTimeConst[5]);//火箭时间
		else rocketTimer[5] = 60.0f;  // arbitrary number since no rockets ever fire	
	}
	*/
	

		//更新粒子
		numRockets = 0;
		for(unsigned int i=0; i<m_ParticleSystem.last_particle; i++)
		{
		  Particle* curpart(&(m_ParticleSystem.particles[i]));
		  m_ParticleSystem.particles[i].update(frameTime,dSmoke,dClouds,dWind,dAmbient,dIllumination,&theWorld);
		  if(curpart->type == ROCKET) numRockets++;
		 
		  
		  // curpart->findDepth(m_Camera.cameraPos,billboardMat);
		  


		  if(curpart->type==IGNITOR&&curpart->life <0.93)
		  {
            if(!curpart->m_Fire->m_Exploded)//未爆炸
		{
     if(IsRecord())
	{
	  m_PlayTime.push_back(m_Frame*m_f);//记录时间
	  m_PlayStyle.push_back(BOOM1SOUND );//记录类型
	  m_PlayPos.push_back(m_Camera.cameraPos);
	  m_PlaySource.push_back(curpart->xyz);
	  soundengine->insertSoundNode(BOOM1SOUND , curpart->xyz, m_Camera.cameraPos);
      
	  m_PlayTime.push_back(m_Frame*m_f);//记录时间
	  m_PlayStyle.push_back(SUCKSOUND);//记录类型
	  m_PlayPos.push_back(m_Camera.cameraPos);
	  m_PlaySource.push_back(curpart->xyz);
      soundengine->insertSoundNode(SUCKSOUND, curpart->xyz,m_Camera.cameraPos);

	}
	else
	{
   //播放声音
  soundengine->insertSoundNode(BOOM1SOUND, curpart->xyz, m_Camera.cameraPos);
  soundengine->insertSoundNode(SUCKSOUND , curpart->xyz, m_Camera.cameraPos);
   } 
    curpart->m_Fire->m_Exploded = true;
   }
}

     if(curpart->m_Fire!=NULL&&curpart->type==ROCKET&&curpart->life <0.43)
	 {
       if(!curpart->m_Fire->m_Boom)//未爆炸
			  {
               if(IsRecord())
	        {
	         m_PlayTime.push_back(m_Frame*m_f);//记录时间
	         m_PlayStyle.push_back(BOOM1SOUND );//记录类型
	         m_PlayPos.push_back(m_Camera.cameraPos);
	         m_PlaySource.push_back(curpart->xyz);
	         soundengine->insertSoundNode(BOOM1SOUND , curpart->xyz, m_Camera.cameraPos);
     
	         }
	        else
	        {
             //播放声音
             soundengine->insertSoundNode(BOOM1SOUND, curpart->xyz, m_Camera.cameraPos);
 
           } 
                 curpart->m_Fire->m_Boom = true;
          }


	 }


		  //点燃烟花
		  if(curpart->life <= 0.0f || curpart->xyz[1] < 0.0f)
		  {
		   switch(curpart->type)
		   {
			case ROCKET:
			if(curpart->xyz[1] <= 0.0f)
			{
			  // move above ground for explosion so new particles aren't removed
			  curpart->xyz[1] = 0.1f;
			  curpart->vel[1] *= -0.7f;
			}
					
			if(curpart->explosiontype == 18)
			curpart->initSpinner();
			else
			{
			 
				
				curpart->initExplosion();
			


			}
			break;
				
			case IGNITOR:
            
	
			curpart->m_Fire->m_Ignitor++;
		    if(curpart->m_Fire->m_Ignitor==8)
			{
             curpart->m_Fire->m_Ignitor = 0;
			 curpart->explosiontype = 0;
			  curpart->initExplosion();		
			 curpart->explosiontype = 21;
			 curpart->initExplosion();
			}
			else
			{
              curpart->explosiontype = 0;
			  curpart->initExplosion();			
           
			}

			break;
			case POPPER:
			switch(curpart->explosiontype)
			{
			case 21:
            curpart->initExplosion();

				break;
			  case STAR:
			  curpart->explosiontype = 100;
			  curpart->initExplosion();
			  break;
					
			  case STREAMER:
			  curpart->explosiontype = 101;
			  curpart->initExplosion();
			  break;
					
			  case METEOR:
			  curpart->explosiontype = 102;
			  curpart->initExplosion();			
			  break;
		
			  case POPPER:
			  curpart->type = STAR;
			  curpart->rgb.set(1.0f, 0.8f, 0.6f);
			  curpart->t = m_ParticleSystem.particles[i].tr = m_ParticleSystem.particles[i].life = 0.2f;		
			}
			break;
				
			case SUCKER:
			  curpart->initShockwave();
			  break;
				
			case STRETCHER:
			  curpart->initBigmama();		
		   }
		  }
		}

   m_ParticleSystem.DeallocParticle();//删除粒子
		
}