Example #1
0
void P_SetupWeapons_ntohton()
{
	unsigned int i;
	const PClass *cls;

	Weapons_ntoh.Clear();
	Weapons_hton.Clear();

	cls = NULL;
	Weapons_ntoh.Push(cls);		// Index 0 is always NULL.
	for (i = 0; i < PClass::m_Types.Size(); ++i)
	{
		PClass *cls = PClass::m_Types[i];

		if (cls->ActorInfo != NULL && cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
		{
			Weapons_ntoh.Push(cls);
		}
	}
	qsort(&Weapons_ntoh[1], Weapons_ntoh.Size() - 1, sizeof(Weapons_ntoh[0]), ntoh_cmp);
	for (i = 0; i < Weapons_ntoh.Size(); ++i)
	{
		Weapons_hton[Weapons_ntoh[i]] = i;
	}
}
Example #2
0
void UCContext::emit_native_function_call(Function *pfn, CALLFN fn)
{
 Type rt = pfn->return_type();
// *change 1.2.0 Moved from compile_function_call()
// for cdecl-style method imports, 
 if (pfn->is_cdecl() && pfn->is_method()) {
      // push mOP onto exec stack
     emit(PUSH_THIS,0);       
     //  do note that returned objects are by a another hidden arg
     // *fix 1.1.4 The return type must specifically be an _object_, not a pointer to an object!
     if (rt.is_object()) emit(SWAP,0);
 }

 emit(CALLN,DIRECT,NFBlock::create(pfn,fn));

 pfn->fun_block()->data = (void *)fn; // convenient place to keep this!

 // We need to check imported class object ptrs to see if they have a VMT....
 // Any imported class ptrs need their UC VMT patched with CHKVMT
 // *fix 1.1.0 Imported references as well as pointers!
 
 
 if (rt.is_class() && rt.is_ref_or_ptr()) {
    PClass pc = pc = rt.as_class();
	if (pc->imported() && pc->has_VMT()) 
      out(CodeGenerator::instruction_with_pointer(CHKVMT,pc));
 }
 // *add 1.2.9 Sometimes necessary to clear out upper 3bytes of 32-bit boolean values
 else
 if (rt == t_bool) {
   emit(I2B);
 }

}
Example #3
0
static void SetKeyTypes()
{
	for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
	{
		PClass *ti = PClassActor::AllActorClasses[i];

		if (ti->IsDescendantOf(RUNTIME_CLASS(AKey)))
		{
			PClassActor *tia = static_cast<PClassActor *>(ti);
			AKey *key = (AKey*)GetDefaultByType(tia);

			if (key->Icon.isValid() && key->KeyNumber>0)
			{
				KeyTypes.Push(tia);
			}
			else 
			{
				UnassignedKeyTypes.Push(tia);
			}
		}
	}
	if (KeyTypes.Size())
	{
		qsort(&KeyTypes[0], KeyTypes.Size(), sizeof(KeyTypes[0]), ktcmp);
	}
	else
	{
		// Don't leave the list empty
		PClassActor *ti = RUNTIME_CLASS(AKey);
		KeyTypes.Push(ti);
	}
}
Example #4
0
static void SetKeyTypes()
{
	for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
	{
		PClass *ti = PClassActor::AllActorClasses[i];
		auto kt = PClass::FindActor(NAME_Key);

		if (ti->IsDescendantOf(kt))
		{
			PClassActor *tia = static_cast<PClassActor *>(ti);
			AInventory *key = (AInventory*)(GetDefaultByType(tia));

			if (key->Icon.isValid() && key->special1 > 0)
			{
				KeyTypes.Push(tia);
			}
			else 
			{
				UnassignedKeyTypes.Push(tia);
			}
		}
	}
	if (KeyTypes.Size())
	{
		qsort(&KeyTypes[0], KeyTypes.Size(), sizeof(KeyTypes[0]), ktcmp);
	}
	else
	{
		// Don't leave the list empty
		KeyTypes.Push(PClass::FindActor(NAME_Key));
	}
}
Example #5
0
// miscelaneous output routines
ostream& operator << (ostream& os, Signature& sig)
{
 Signature::iterator si;
 StringList::iterator sli;
 StringList *args = sig.get_arg_names();
 if (args && args->size()==0) args = NULL;
 if (!s_ctor && !s_dtor)  // *fix 1.1.2 these don't have return types!
   os << sig.return_type() << ' ';  
 string na = s_fun_name;
 char first = na[0];
 // *fix 1.2.7 wasn't outputing 'operator' in front of '()'
 if (!isalpha(first) && first != '_' /*&& first != '('*/) na = "operator" + na;
 PClass pc = sig.class_ptr();
 if (pc != NULL) {
    string classn = pc->name();
    if (! s_full_names && pc->is_template()) classn = pc->get_template()->name();
    if (s_ctor)  na = classn; else
	if (s_dtor)  na = "~" + classn;
    if (s_full_names) na = classn + "::" + na;
 }
 os << na << '(';
 if (args != NULL) sli = args->begin();
 for(si = sig.begin(); si != sig.end(); ) {
   os << *si++;
   if (args != NULL) os << ' ' << *sli++;
   if (si != sig.end()) os << ',';
 }
 os << ')';
 if (sig.is_const()) os << " const";
 return os;
}
Example #6
0
void dissemble(PFBlock fb)
{
 Opcodes opcode;
 int rmode,rdata, k = 0;
 string name;
 Instruction *pi = fb->pstart;
 while (pi != end_of_code) {
    opcode = (Opcodes)pi->opcode;   
	// *add 1.2.4 HALT+data is not always a breakpoint!
    // (it is used as a NOP + <any useful tag data>)
    if (opcode == HALT) {
        if (pi->data < MAX_BREAKPOINTS) {
          Breakpoint *pb = Breakpoint::from_id(pi->data);
          Instruction ai = pb->saved_instruction();
          std::cout << "*";
          opcode = (Opcodes)ai.opcode;
          rmode = ai.rmode;  rdata = ai.data;
        } else { opcode = NOP; rdata = pi->data; }
    } else {
      rmode  = pi->rmode;  rdata  = pi->data;
    }
    name =  get_opcode_name(opcode);
    std::cout << k++ << ' ' <<  name << '\t';
    if (opcode == CCALL || opcode == CALL || opcode == CALLD || opcode == CALLN) {
       FBlock* pfb;
       void *data = data_ptr(rdata);
       if (opcode == CALLN)
           pfb = Builtin::imported_fblock_from_function((void*)((NFBlock *)data)->pfn);
       else pfb = PFBlock(data_ptr(rdata));     
      if (pfb) Function::from_fun_block(pfb)->dump(std::cout);      
    } else 
    if (opcode == JSWITCH) {
      int *swb = (int *)data_ptr(rdata);
      int sz = *swb++;
      int def = *swb++;
      std::cout << '(' << sz << ',' << def << ") ";
      for (int i = 0; i < sz; i++) std::cout << *swb++ << ' ' << *swb++ << ' ';
    }
    else
    if (opcode == TOSD || opcode == TPODS) {
       PClass pc = *(PClass *)data_ptr(rdata);
       std::cout << pc->name();
    }
    else {
     if (rmode) 
      switch(rmode) {
      case DIRECT: std::cout << "D ";  break;
      case SREL:   std::cout << "R ";  break;
      case OREL:   std::cout << "S ";  break;
     }
     if (rdata != 0) std::cout << rdata;
   }
   std::cout << std::endl;  
   if (opcode == RET || opcode == RETI || opcode == RETD) break;
   pi++;
 }
}
Example #7
0
DObject::~DObject ()
{
	if (!PClass::bShutdown)
	{
		PClass *type = GetClass();
		if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
		{
			DObject **probe;

			if (!(ObjectFlags & OF_YesReallyDelete))
			{
				Printf("Warning: '%s' is freed outside the GC process.\n",
					type != NULL ? type->TypeName.GetChars() : "==some object==");
			}

			// Find all pointers that reference this object and NULL them.
			StaticPointerSubstitution(this, NULL);

			// Now unlink this object from the GC list.
			for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
			{
				if (*probe == this)
				{
					*probe = ObjNext;
					if (&ObjNext == GC::SweepPos)
					{
						GC::SweepPos = probe;
					}
					break;
				}
			}

			// If it's gray, also unlink it from the gray list.
			if (this->IsGray())
			{
				for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
				{
					if (*probe == this)
					{
						*probe = GCNext;
						break;
					}
				}
			}
		}
		
		if (nullptr != type)
		{
			type->DestroySpecials(this);
		}
	}
}
Example #8
0
PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
{
	assert(size >= Size);
	PClass *type;
	bool notnew;

	const PClass *existclass = FindClass(name);

	if (existclass != nullptr)
	{
		// This is a placeholder so fill it in
		if (existclass->Size == TentativeClass)
		{
			type = const_cast<PClass*>(existclass);
			if (!IsDescendantOf(type->ParentClass))
			{
				I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
			}
			DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars());
			notnew = true;
		}
		else
		{
			// a different class with the same name already exists. Let the calling code deal with this.
			return nullptr;
		}
	}
	else
	{
		type = new PClass;
		notnew = false;
	}

	type->TypeName = name;
	type->bRuntimeClass = true;
	Derive(type, name);
	type->Size = size;
	if (size != TentativeClass)
	{
		NewClassType(type);
		type->InitializeDefaults();
		type->Virtuals = Virtuals;
	}
	else
		type->bOptional = false;

	if (!notnew)
	{
		type->InsertIntoHash(false);
	}
	return type;
}
Example #9
0
PClass *ClassReg::RegisterClass()
{
	// Skip classes that have already been registered
	if (MyClass != nullptr)
	{
		return MyClass;
	}

	// Add type to list
	PClass *cls = new PClass;

	SetupClass(cls);
	cls->InsertIntoHash(true);
	if (ParentType != nullptr)
	{
		cls->ParentClass = ParentType->RegisterClass();
	}
	return cls;
}
Example #10
0
PClass *PClass::FindClassTentative(FName name)
{
	if (name == NAME_None)
	{
		return nullptr;
	}

	PClass *found = FindClass(name);
	if (found != nullptr) return found;

	PClass *type = new PClass;
	DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());

	Derive(type, name);
	type->Size = TentativeClass;

	type->InsertIntoHash(false);
	return type;
}
Example #11
0
// Create a new class based on an existing class
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
{
	assert (size >= Size);

	PClass *type = new PClass;

	type->TypeName = name;
	type->ParentClass = this;
	type->Size = size;
	type->Pointers = NULL;
	type->ConstructNative = ConstructNative;
	type->ClassIndex = m_Types.Push (type);
	type->Meta = Meta;
	type->Defaults = new BYTE[size];
	memcpy (type->Defaults, Defaults, Size);
	if (size > Size)
	{
		memset (type->Defaults + Size, 0, size - Size);
	}
	type->FlatPointers = NULL;
	type->bRuntimeClass = true;
	type->ActorInfo = NULL;
	type->InsertIntoHash();

	// If this class has an actor info, then any classes derived from it
	// also need an actor info.
	if (this->ActorInfo != NULL)
	{
		FActorInfo *info = type->ActorInfo = new FActorInfo;
		info->Class = type;
		info->GameFilter = GAME_Any;
		info->SpawnID = 0;
		info->DoomEdNum = -1;
		info->OwnedStates = NULL;
		info->NumOwnedStates = 0;
		info->Replacement = NULL;
		info->Replacee = NULL;
		m_RuntimeActors.Push (type);
	}
	return type;
}
Example #12
0
// Like FindClass but creates a placeholder if no class
// is found. CreateDerivedClass will automatcally fill in
// the placeholder when the actual class is defined.
const PClass *PClass::FindClassTentative (FName name)
{
	if (name == NAME_None)
	{
		return NULL;
	}

	PClass *cls = TypeHash[name % HASH_SIZE];

	while (cls != 0)
	{
		int lexx = int(name) - int(cls->TypeName);
		if (lexx > 0)
		{
			cls = cls->HashNext;
		}
		else if (lexx == 0)
		{
			return cls;
		}
		else
		{
			break;
		}
	}
	PClass *type = new PClass;
	DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());

	type->TypeName = name;
	type->ParentClass = this;
	type->Size = -1;
	type->Pointers = NULL;
	type->ConstructNative = NULL;
	type->ClassIndex = m_Types.Push (type);
	type->Defaults = NULL;
	type->FlatPointers = NULL;
	type->bRuntimeClass = true;
	type->ActorInfo = NULL;
	type->InsertIntoHash();
	return type;
}
Example #13
0
void FWeaponSlots::AddExtraWeapons()
{
	unsigned int i;

	// Set fractional positions for current weapons.
	for (i = 0; i < NUM_WEAPON_SLOTS; ++i)
	{
		Slots[i].SetInitialPositions();
	}

	// Append extra weapons to the slots.
	for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
	{
		PClass *cls = PClassActor::AllActorClasses[i];

		if (!cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
		{
			continue;
		}
		PClassWeapon *acls = static_cast<PClassWeapon *>(cls);
		if ((acls->GameFilter == GAME_Any || (acls->GameFilter & gameinfo.gametype)) &&
			acls->Replacement == NULL &&		// Replaced weapons don't get slotted.
			!(((AWeapon *)(acls->Defaults))->WeaponFlags & WIF_POWERED_UP) &&
			!LocateWeapon(acls, NULL, NULL)		// Don't duplicate it if it's already present.
			)
		{
			int slot = acls->SlotNumber;
			if ((unsigned)slot < NUM_WEAPON_SLOTS)
			{
				FWeaponSlot::WeaponInfo info = { acls, acls->SlotPriority };
				Slots[slot].Weapons.Push(info);
			}
		}
	}

	// Now resort every slot to put the new weapons in their proper places.
	for (i = 0; i < NUM_WEAPON_SLOTS; ++i)
	{
		Slots[i].Sort();
	}
}
Example #14
0
static void FinishThingdef()
{
	int errorcount = StateParams.ResolveAll();

	for (unsigned i = 0;i < PClass::m_Types.Size(); i++)
	{
		PClass * ti = PClass::m_Types[i];

		// Skip non-actors
		if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;

		if (ti->Size == (unsigned)-1)
		{
			Printf("Class %s referenced but not defined\n", ti->TypeName.GetChars());
			errorcount++;
			continue;
		}

		AActor *def = GetDefaultByType(ti);

		if (!def)
		{
			Printf("No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars());
			errorcount++;
			continue;
		}
	}
	if (errorcount > 0)
	{
		I_Error("%d errors during actor postprocessing", errorcount);
	}

	// Since these are defined in DECORATE now the table has to be initialized here.
	for(int i=0;i<31;i++)
	{
		char fmt[20];
		mysnprintf(fmt, countof(fmt), "QuestItem%d", i+1);
		QuestItemClasses[i] = PClass::FindClass(fmt);
	}
}
Example #15
0
void FWeaponSlots::AddExtraWeapons()
{
	unsigned int i;

	// Set fractional positions for current weapons.
	for (i = 0; i < NUM_WEAPON_SLOTS; ++i)
	{
		Slots[i].SetInitialPositions();
	}

	// Append extra weapons to the slots.
	for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
	{
		PClass *cls = PClass::m_Types[i];

		if (cls->ActorInfo != NULL &&
			(cls->ActorInfo->GameFilter == GAME_Any || (cls->ActorInfo->GameFilter & gameinfo.gametype)) &&
			cls->ActorInfo->Replacement == NULL &&	// Replaced weapons don't get slotted.
			cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)) &&
			!(static_cast<AWeapon*>(GetDefaultByType(cls))->WeaponFlags & WIF_POWERED_UP) &&
			!LocateWeapon(cls, NULL, NULL)			// Don't duplicate it if it's already present.
			)
		{
			int slot = cls->Meta.GetMetaInt(AWMETA_SlotNumber, -1);
			if ((unsigned)slot < NUM_WEAPON_SLOTS)
			{
				fixed_t position = cls->Meta.GetMetaFixed(AWMETA_SlotPriority, INT_MAX);
				FWeaponSlot::WeaponInfo info = { cls, position };
				Slots[slot].Weapons.Push(info);
			}
		}
	}

	// Now resort every slot to put the new weapons in their proper places.
	for (i = 0; i < NUM_WEAPON_SLOTS; ++i)
	{
		Slots[i].Sort();
	}
}
Example #16
0
void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
{
	PClass *ti = info->Class;
	AActor *defaults = (AActor*)ti->Defaults;

	try
	{
		bag.statedef.FinishStates (info, defaults);
	}
	catch (CRecoverableError &err)
	{
		sc.Message(MSG_ERROR, "%s", err.GetMessage());
		bag.statedef.MakeStateDefines(NULL);
		return;
	}
	bag.statedef.InstallStates (info, defaults);
	bag.statedef.MakeStateDefines(NULL);
	if (bag.DropItemSet)
	{
		if (bag.DropItemList == NULL)
		{
			if (ti->Meta.GetMetaInt (ACMETA_DropItems) != 0)
			{
				ti->Meta.SetMetaInt (ACMETA_DropItems, 0);
			}
		}
		else
		{
			ti->Meta.SetMetaInt (ACMETA_DropItems,
				StoreDropItemChain(bag.DropItemList));
		}
	}
	if (ti->IsDescendantOf (RUNTIME_CLASS(AInventory)))
	{
		defaults->flags |= MF_SPECIAL;
	}

	// Weapons must be checked for all relevant states. They may crash the game otherwise.
	if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
	{
		FState * ready = ti->ActorInfo->FindState(NAME_Ready);
		FState * select = ti->ActorInfo->FindState(NAME_Select);
		FState * deselect = ti->ActorInfo->FindState(NAME_Deselect);
		FState * fire = ti->ActorInfo->FindState(NAME_Fire);

		// Consider any weapon without any valid state abstract and don't output a warning
		// This is for creating base classes for weapon groups that only set up some properties.
		if (ready || select || deselect || fire)
		{
			if (!ready)
			{
				sc.Message(MSG_ERROR, "Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
			}
			if (!select) 
			{
				sc.Message(MSG_ERROR, "Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
			}
			if (!deselect) 
			{
				sc.Message(MSG_ERROR, "Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
			}
			if (!fire) 
			{
				sc.Message(MSG_ERROR, "Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars());
			}
		}
	}
}
Example #17
0
void cht_Take (player_t *player, const char *name, int amount)
{
    bool takeall;
    PClassActor *type;

    if (player->mo == NULL || player->health <= 0)
    {
        return;
    }

    takeall = (stricmp (name, "all") == 0);

    if (!takeall && stricmp (name, "health") == 0)
    {
        if (player->mo->health - amount <= 0
                || player->health - amount <= 0
                || amount == 0)
        {

            cht_Suicide (player);

            if (player == &players[consoleplayer])
                C_HideConsole ();

            return;
        }

        if (amount > 0)
        {
            if (player->mo)
            {
                player->mo->health -= amount;
                player->health = player->mo->health;
            }
            else
            {
                player->health -= amount;
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "backpack") == 0)
    {
        // Take away all types of backpacks the player might own.
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            PClass *type = PClassActor::AllActorClasses[i];

            if (type->IsDescendantOf(RUNTIME_CLASS (ABackpackItem)))
            {
                AInventory *pack = player->mo->FindInventory(static_cast<PClassActor *>(type));

                if (pack)
                    pack->Destroy();
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "ammo") == 0)
    {
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            PClass *type = PClassActor::AllActorClasses[i];

            if (type->ParentClass == RUNTIME_CLASS (AAmmo))
            {
                AInventory *ammo = player->mo->FindInventory(static_cast<PClassActor *>(type));

                if (ammo)
                    ammo->DepleteOrDestroy();
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "armor") == 0)
    {
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            type = PClassActor::AllActorClasses[i];

            if (type->IsDescendantOf (RUNTIME_CLASS (AArmor)))
            {
                AInventory *armor = player->mo->FindInventory(static_cast<PClassActor *>(type));

                if (armor)
                    armor->DepleteOrDestroy();
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "keys") == 0)
    {
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            type = PClassActor::AllActorClasses[i];

            if (type->IsDescendantOf (RUNTIME_CLASS (AKey)))
            {
                AActor *key = player->mo->FindInventory(static_cast<PClassActor *>(type));

                if (key)
                    key->Destroy ();
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "weapons") == 0)
    {
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            type = PClassActor::AllActorClasses[i];

            if (type != RUNTIME_CLASS(AWeapon) &&
                    type->IsDescendantOf (RUNTIME_CLASS (AWeapon)))
            {
                AActor *weapon = player->mo->FindInventory(static_cast<PClassActor *>(type));

                if (weapon)
                    weapon->Destroy ();

                player->ReadyWeapon = nullptr;
                player->PendingWeapon = WP_NOCHANGE;
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "artifacts") == 0)
    {
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            type = PClassActor::AllActorClasses[i];

            if (type->IsDescendantOf (RUNTIME_CLASS (AInventory)))
            {
                if (!type->IsDescendantOf (RUNTIME_CLASS (APuzzleItem)) &&
                        !type->IsDescendantOf (RUNTIME_CLASS (APowerup)) &&
                        !type->IsDescendantOf (RUNTIME_CLASS (AArmor)) &&
                        !type->IsDescendantOf (RUNTIME_CLASS (AWeapon)) &&
                        !type->IsDescendantOf (RUNTIME_CLASS (AKey)))
                {
                    AActor *artifact = player->mo->FindInventory(static_cast<PClassActor *>(type));

                    if (artifact)
                        artifact->Destroy ();
                }
            }
        }

        if (!takeall)
            return;
    }

    if (takeall || stricmp (name, "puzzlepieces") == 0)
    {
        for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
        {
            type = PClassActor::AllActorClasses[i];

            if (type->IsDescendantOf (RUNTIME_CLASS (APuzzleItem)))
            {
                AActor *puzzlepiece = player->mo->FindInventory(static_cast<PClassActor *>(type));

                if (puzzlepiece)
                    puzzlepiece->Destroy ();
            }
        }

        if (!takeall)
            return;
    }

    if (takeall)
        return;

    type = PClass::FindActor (name);
    if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS (AInventory)))
    {
        if (player == &players[consoleplayer])
            Printf ("Unknown item \"%s\"\n", name);
    }
    else
    {
        player->mo->TakeInventory(type, amount ? amount : 1);
    }
    return;
}
Example #18
0
void NETWORK_Construct( USHORT usPort, bool bAllocateLANSocket )
{
	char			szString[128];
	ULONG			ulArg;
	USHORT			usNewPort;
	bool			bSuccess;

	// Initialize the Huffman buffer.
	HUFFMAN_Construct( );

#ifdef __WIN32__
	// [BB] Linux doesn't know WSADATA, so this may not be moved outside the ifdef.
	WSADATA			WSAData;
	if ( WSAStartup( 0x0101, &WSAData ))
		network_Error( "Winsock initialization failed!\n" );

	Printf( "Winsock initialization succeeded!\n" );
#endif

	ULONG ulInAddr = INADDR_ANY;
	const char* pszIPAddress = Args->CheckValue( "-useip" );
	// [BB] An IP was specfied. Check if it's valid and if it is, try to bind our socket to it.
	if ( pszIPAddress )
	{
		ULONG requestedIP = inet_addr( pszIPAddress );
		if ( requestedIP == INADDR_NONE )
		{
			sprintf( szString, "NETWORK_Construct: %s is not a valid IP address\n", pszIPAddress );
			network_Error( szString );
		}
		else
			ulInAddr = requestedIP;
	}

	g_usLocalPort = usPort;

	// Allocate a socket, and attempt to bind it to the given port.
	g_NetworkSocket = network_AllocateSocket( );
	// [BB] If we can't allocate a socket, sending / receiving net packets won't work.
	if ( g_NetworkSocket == INVALID_SOCKET )
		network_Error( "NETWORK_Construct: Couldn't allocate socket. You will not be able to host or join servers.\n" );
	else if ( network_BindSocketToPort( g_NetworkSocket, ulInAddr, g_usLocalPort, false ) == false )
	{
		bSuccess = true;
		bool bSuccessIP = true;
		usNewPort = g_usLocalPort;
		while ( network_BindSocketToPort( g_NetworkSocket, ulInAddr, ++usNewPort, false ) == false )
		{
			// Didn't find an available port. Oh well...
			if ( usNewPort == g_usLocalPort )
			{
				// [BB] We couldn't use the specified IP, so just try any.
				if ( ulInAddr != INADDR_ANY )
				{
					ulInAddr = INADDR_ANY;
					bSuccessIP = false;
					continue;
				}
				bSuccess = false;
				break;
			}
		}

		if ( bSuccess == false )
		{
			sprintf( szString, "NETWORK_Construct: Couldn't bind socket to port: %d\n", g_usLocalPort );
			network_Error( szString );
		}
		else if ( bSuccessIP == false )
		{
			sprintf( szString, "NETWORK_Construct: Couldn't bind socket to IP %s, using the default IP instead:\n", pszIPAddress );
			network_Error( szString );
		}
		else
		{
			Printf( "NETWORK_Construct: Couldn't bind to %d. Binding to %d instead...\n", g_usLocalPort, usNewPort );
			g_usLocalPort = usNewPort;
		}
	}

	ulArg = true;
	if ( ioctlsocket( g_NetworkSocket, FIONBIO, &ulArg ) == -1 )
		printf( "network_AllocateSocket: ioctl FIONBIO: %s", strerror( errno ));

	// If we're not starting a server, setup a socket to listen for LAN servers.
	if ( bAllocateLANSocket )
	{
		g_LANSocket = network_AllocateSocket( );
		if ( network_BindSocketToPort( g_LANSocket, ulInAddr, DEFAULT_BROADCAST_PORT, true ) == false )
		{
			sprintf( szString, "network_BindSocketToPort: Couldn't bind LAN socket to port: %d. You will not be able to see LAN servers in the browser.", DEFAULT_BROADCAST_PORT );
			network_Error( szString );
			// [BB] The socket won't work in this case, make sure not to use it.
			g_bLANSocketInvalid = true;
		}

		if ( ioctlsocket( g_LANSocket, FIONBIO, &ulArg ) == -1 )
			printf( "network_AllocateSocket: ioctl FIONBIO: %s", strerror( errno ));
	}

	// Init our read buffer.
	// [BB] Vortex Cortex pointed us to the fact that the smallest huffman code is only 3 bits
	// and it turns into 8 bits when it's decompressed. Thus we need to allocate a buffer that
	// can hold the biggest possible size we may get after decompressing (aka Huffman decoding)
	// the incoming UDP packet.
	NETWORK_InitBuffer( &g_NetworkMessage, ((MAX_UDP_PACKET * 8) / 3 + 1), BUFFERTYPE_READ );
	NETWORK_ClearBuffer( &g_NetworkMessage );

	// [BB] Get and save our local IP.
	if ( ( ulInAddr == INADDR_ANY ) || ( pszIPAddress == NULL ) )
		g_LocalAddress = NETWORK_GetLocalAddress( );
	// [BB] We are using a specified IP, so we don't need to figure out what IP we have, but just use the specified one.
	else
	{
		NETWORK_StringToAddress ( pszIPAddress, &g_LocalAddress );
		g_LocalAddress.usPort = htons ( NETWORK_GetLocalPort() );
	}

	// Print out our local IP address.
	Printf( "IP address %s\n", NETWORK_AddressToString( g_LocalAddress ));

	// If hosting, update the server GUI.
	if( NETWORK_GetState() == NETSTATE_SERVER )
		SERVERCONSOLE_UpdateIP( g_LocalAddress );

	// [BB] Initialize the checksum of the non-map lumps that need to be authenticated when connecting a new player.
	std::vector<std::string>	lumpsToAuthenticate;
	std::vector<LumpAuthenticationMode>	lumpsToAuthenticateMode;

	lumpsToAuthenticate.push_back( "COLORMAP" );
	lumpsToAuthenticateMode.push_back( LAST_LUMP );
	lumpsToAuthenticate.push_back( "PLAYPAL" );
	lumpsToAuthenticateMode.push_back( LAST_LUMP );
	lumpsToAuthenticate.push_back( "HTICDEFS" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "HEXNDEFS" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "STRFDEFS" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "DOOMDEFS" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "GLDEFS" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "DECORATE" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "LOADACS" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "DEHACKED" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );
	lumpsToAuthenticate.push_back( "GAMEMODE" );
	lumpsToAuthenticateMode.push_back( ALL_LUMPS );

	FString checksum, longChecksum;
	bool noProtectedLumpsAutoloaded = true;

	// [BB] All precompiled ACS libraries need to be authenticated. The only way to find all of them
	// at this point is to parse all LOADACS lumps.
	{
		int lump, lastlump = 0;
		while ((lump = Wads.FindLump ("LOADACS", &lastlump)) != -1)
		{
			FScanner sc(lump);
			while (sc.GetString())
			{
				NETWORK_AddLumpForAuthentication ( Wads.CheckNumForName (sc.String, ns_acslibrary) );
			}
		}
	}

	// [BB] First check the lumps that were marked for authentication while initializing. This
	// includes for example those lumps included by DECORATE lumps. It's much easier to mark those
	// lumps while the engine parses the DECORATE code than trying to find all included lumps from
	// the DECORATE lumps directly.
	for ( unsigned int i = 0; i < g_LumpNumsToAuthenticate.Size(); ++i )
	{
		if ( !network_GenerateLumpMD5HashAndWarnIfNeeded( g_LumpNumsToAuthenticate[i], Wads.GetLumpFullName (g_LumpNumsToAuthenticate[i]), checksum ) )
			noProtectedLumpsAutoloaded = false;
		longChecksum += checksum;
	}

	for ( unsigned int i = 0; i < lumpsToAuthenticate.size(); i++ )
	{
		switch ( lumpsToAuthenticateMode[i] ){
			case LAST_LUMP:
				int lump;
				lump = Wads.CheckNumForName(lumpsToAuthenticate[i].c_str());
				// [BB] Possibly we find the COLORMAP lump only in the colormaps name space.
				if ( ( lump == -1 ) && ( lumpsToAuthenticate[i].compare ( "COLORMAP" ) == 0 ) )
					lump = Wads.CheckNumForName("COLORMAP", ns_colormaps);
				if ( lump == -1 )
				{
					Printf ( PRINT_BOLD, "Warning: Can't find lump %s for authentication!\n", lumpsToAuthenticate[i].c_str() );
					continue;
				}
				if ( !network_GenerateLumpMD5HashAndWarnIfNeeded( lump, lumpsToAuthenticate[i].c_str(), checksum ) )
					noProtectedLumpsAutoloaded = false;

				// [BB] To make Doom and Freedoom network compatible, substitue the Freedoom PLAYPAL/COLORMAP hash
				// by the corresponding Doom hash.
				// 4804c7f34b5285c334a7913dd98fae16 Doom PLAYPAL hash
				// 061a4c0f80aa8029f2c1bc12dc2e261e Doom COLORMAP hash
				// 2e01ae6258f2a0fdad32125537efe1af Freedoom PLAYPAL hash
				// bb535e66cae508e3833a5d2de974267b Freedoom COLORMAP hash
				if ( ( stricmp ( lumpsToAuthenticate[i].c_str(), "PLAYPAL" ) == 0 ) && ( stricmp ( checksum.GetChars(), "2e01ae6258f2a0fdad32125537efe1af" ) == 0 ) )
					checksum = "4804c7f34b5285c334a7913dd98fae16";
				else if ( ( stricmp ( lumpsToAuthenticate[i].c_str(), "COLORMAP" ) == 0 ) && ( stricmp ( checksum.GetChars(), "bb535e66cae508e3833a5d2de974267b" ) == 0 ) )
					checksum = "061a4c0f80aa8029f2c1bc12dc2e261e";

				longChecksum += checksum;
				break;

			case ALL_LUMPS:
				int workingLump, lastLump;

				lastLump = 0;
				while ((workingLump = Wads.FindLump(lumpsToAuthenticate[i].c_str(), &lastLump)) != -1)
				{
					if ( !network_GenerateLumpMD5HashAndWarnIfNeeded( workingLump, lumpsToAuthenticate[i].c_str(), checksum ) )
						noProtectedLumpsAutoloaded = false;
					longChecksum += checksum;
				}
				break;
		}
	}
	CMD5Checksum::GetMD5( reinterpret_cast<const BYTE *>(longChecksum.GetChars()), longChecksum.Len(), g_lumpsAuthenticationChecksum );

	// [BB] Warn the user about problematic auto-loaded files.
	if ( noProtectedLumpsAutoloaded == false )
	{
		Printf ( PRINT_BOLD, "Warning: Above auto-loaded files contain protected lumps.\n" );
		if ( Args->CheckParm( "-host" ) )
			Printf ( PRINT_BOLD, "Clients without these files can't connect to this server.\n" );
		else
			Printf ( PRINT_BOLD, "You can't connect to servers without these files.\n" );
	}

	// [BB] Initialize the actor network class indices.
	for ( unsigned int i = 0; i < PClass::m_Types.Size(); i++ )
	{
		PClass* cls = PClass::m_Types[i];
		if ( (cls->IsDescendantOf(RUNTIME_CLASS(AActor)))
		     // [BB] The server only binaries don't know DynamicLight and derived classes.
		     && !(cls->IsDescendantOf(PClass::FindClass("DynamicLight"))) )
			cls->ActorNetworkIndex = 1 + g_ActorNetworkIndexClassPointerMap.Push ( cls );
		else
			cls->ActorNetworkIndex = 0;
	}

	// [RC/BB] Init the list of PWADs.
	network_InitPWADList( );

	// Call NETWORK_Destruct() when Skulltag closes.
	atterm( NETWORK_Destruct );

	Printf( "UDP Initialized.\n" );
}
Example #19
0
//==========================================================================
//
// Starts a new actor definition
//
//==========================================================================
FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native)
{
	const PClass *replacee = NULL;
	PClass *ti = NULL;
	FActorInfo *info = NULL;

	PClass *parent = RUNTIME_CLASS(AActor);

	if (parentName != NAME_None)
	{
		parent = const_cast<PClass *> (PClass::FindClass (parentName));
		
		const PClass *p = parent;
		while (p != NULL)
		{
			if (p->TypeName == typeName)
			{
				sc.Message(MSG_ERROR, "'%s' inherits from a class with the same name", typeName.GetChars());
				break;
			}
			p = p->ParentClass;
		}

		if (parent == NULL)
		{
			sc.Message(MSG_ERROR, "Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars());
			parent = RUNTIME_CLASS(AActor);
		}
		else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
		{
			sc.Message(MSG_ERROR, "Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars());
			parent = RUNTIME_CLASS(AActor);
		}
		else if (parent->ActorInfo == NULL)
		{
			sc.Message(MSG_ERROR, "uninitialized parent type '%s' in %s", parentName.GetChars(), typeName.GetChars());
			parent = RUNTIME_CLASS(AActor);
		}
	}

	if (native)
	{
		ti = (PClass*)PClass::FindClass(typeName);
		if (ti == NULL)
		{
			sc.Message(MSG_ERROR, "Unknown native class '%s'", typeName.GetChars());
			goto create;
		}
		else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass())
		{
			sc.Message(MSG_ERROR, "Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars());
			parent = RUNTIME_CLASS(AActor);
			goto create;
		}
		else if (ti->ActorInfo != NULL)
		{
			sc.Message(MSG_ERROR, "Redefinition of internal class '%s'", typeName.GetChars());
			goto create;
		}
		ti->InitializeActorInfo();
		info = ti->ActorInfo;
	}
	else
	{
	create:
		ti = parent->CreateDerivedClass (typeName, parent->Size);
		info = ti->ActorInfo;
	}

	// Copy class lists from parent
	info->ForbiddenToPlayerClass = parent->ActorInfo->ForbiddenToPlayerClass;
	info->RestrictedToPlayerClass = parent->ActorInfo->RestrictedToPlayerClass;
	info->VisibleToPlayerClass = parent->ActorInfo->VisibleToPlayerClass;

	if (parent->ActorInfo->DamageFactors != NULL)
	{
		// copy damage factors from parent
		info->DamageFactors = new DmgFactors;
		*info->DamageFactors = *parent->ActorInfo->DamageFactors;
	}
	if (parent->ActorInfo->PainChances != NULL)
	{
		// copy pain chances from parent
		info->PainChances = new PainChanceList;
		*info->PainChances = *parent->ActorInfo->PainChances;
	}
	if (parent->ActorInfo->ColorSets != NULL)
	{
		// copy color sets from parent
		info->ColorSets = new FPlayerColorSetMap;
		*info->ColorSets = *parent->ActorInfo->ColorSets;
	}
	info->Replacee = info->Replacement = NULL;
	info->DoomEdNum = -1;
	return info;
}
Example #20
0
void HUD_InitHud()
{
	switch (gameinfo.gametype)
	{
	case GAME_Heretic:
	case GAME_Hexen:
		healthpic = TexMan.FindTexture("ARTIPTN2");
		HudFont=FFont::FindFont("HUDFONT_RAVEN");
		break;

	case GAME_Strife:
		healthpic = TexMan.FindTexture("I_MDKT");
		HudFont=BigFont;	// Strife doesn't have anything nice so use the standard font
		break;

	default:
		healthpic = TexMan.FindTexture("MEDIA0");
		berserkpic = TexMan.FindTexture("PSTRA0");
		HudFont=FFont::FindFont("HUDFONT_DOOM");
		break;
	}

	IndexFont = V_GetFont("INDEXFONT");

	if (HudFont == NULL) HudFont = BigFont;
	if (IndexFont == NULL) IndexFont = ConFont;	// Emergency fallback

	invgems[0] = TexMan.FindTexture("INVGEML1");
	invgems[1] = TexMan.FindTexture("INVGEML2");
	invgems[2] = TexMan.FindTexture("INVGEMR1");
	invgems[3] = TexMan.FindTexture("INVGEMR2");

	fragpic = TexMan.FindTexture("HU_FRAGS");	// Sadly, I don't have anything usable for this. :(

	KeyTypes.Clear();
	UnassignedKeyTypes.Clear();

	statspace = SmallFont->StringWidth("Ac:");



	// Now read custom icon overrides
	int lump, lastlump = 0;

	while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1)
	{
		FScanner sc(lump);
		while (sc.GetString())
		{
			if (sc.Compare("Health"))
			{
				sc.MustGetString();
				FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
				if (tex.isValid()) healthpic = TexMan[tex];
			}
			else if (sc.Compare("Berserk"))
			{
				sc.MustGetString();
				FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
				if (tex.isValid()) berserkpic = TexMan[tex];
			}
			else
			{
				PClass *ti = PClass::FindClass(sc.String);
				if (!ti)
				{
					Printf("Unknown item class '%s' in ALTHUDCF\n", sc.String);
				}
				else if (!ti->IsDescendantOf(RUNTIME_CLASS(AInventory)))
				{
					Printf("Invalid item class '%s' in ALTHUDCF\n", sc.String);
					ti=NULL;
				}
				sc.MustGetString();
				FTextureID tex;

				if (!sc.Compare("0") && !sc.Compare("NULL") && !sc.Compare(""))
				{
					tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
				}
				else tex.SetInvalid();

				if (ti) SetHUDIcon(static_cast<PClassInventory*>(ti), tex);
			}
		}
	}
}
Example #21
0
void UCContext::compile(PExpr ex, int flags)
{
  static Label l1(this),l2(this);
  int tcode,ttype,opcode,op = ex->op();
  PExpr e1 = ex->arg1(), e2 = ex->arg2();
  Type t = ex->type();  
  //t.strip_qualifiers();
  opcode = equiv_op[op];
  if (opcode) {
  // the type of an operator usually tells us what code to emit
  // except in the case of relational ops!
      if (t.is_bool()) t = e1->type(); 
      // *fix 0.9.3 -- ptr check missing!
      if (t.is_double() && ! t.is_pointer())
         opcode = float_equiv[opcode];
      compile(e1);
      if (e2) compile(e2);
      emit(opcode,NONE,0);
      return;
  } 
  tcode = size_code(t);

  // at this point we can remove any non-trival typecast...
  if (passthrough_conversion(t,e1)) e1 = e1->arg1();

  switch(op) {
  case ARRAY: {
    bool is_entry = e1->is_entry();
    int  array_size = is_entry ? Parser::array_size(e1->entry()) : 0;
    if (t.is_pointer()) {
      t.decr_pointer();
      tcode = size_code(t);
    }
    compile(e2);    // put index on stack
    // *add 1.2.5 Check for array bounds, if requested
    if (Parser::debug.range_check && array_size > 1) {
        emit_push_int(array_size);
        emit(CALLN,DIRECT,Builtin::range_check_function());
    }
    if (t.is_class()) {
      int sz = t.size();
      if (sz > sizeof(double)) {
        emit_push_int(sz);
        emit(MUL);    // TOS will be index*sizeof(T)
        compile(e1);  // will give us the addr      
        emit(ADD);
        break;
       } else {
        if (sz == 4) tcode = 2; else tcode = 3;
       }
    } 
    if (is_entry) {
       if (array_size > 1) emit(ADDCC + tcode,e1);
       else emit(ADDPC + tcode,e1);
    } else {
      compile(e1);
      if (tcode==0) emit(ADD); 
      else emit(ADDSW+tcode-1);
    }
  } break;
  case DOT:
     push_object_ptr(this,e1);
     compile(e2,flags);  
     emit(DOS);
   break;
  case CCONTEXT: // constructor call, w/ or w/out object disposal
  { 
      Function *pf = e2->function();
	  PClass pc = pf->class_context();
      compile_function_call(this,FUNCTION,flags,e2,true,e1,pc->has_VMT() ? -1 : 0); 

    // *fix 1.0.0 Any temporaries must be unwound before pushing obj on ODS
	// (only if we are a plain auto var)
      if (t==t_void) Parser::check_temp_context(); 

      // *fix 1.2.0L allow for override (needed for GCC imports) 
      if (Parser::temp_context()->no_auto_dtor() ) emit(DOS);
      else {	        
        if (e1->is_entry()) {
           PEntry pe = e1->entry();
	       if (pc->destructor() == NULL && ! pc->has_VMT()) emit(DOS);
           else {
               // Local 'auto' objects get pushed onto the ODS;
               // *add 1.2.3 Put statically created objects in the static ODL (Object Destructor List)
               bool is_auto = pe->is_stack_relative();
               bool is_direct = pe->is_direct();
               if (! is_auto && ! is_direct) emit(DOS); 
               else if (is_auto) {
                   // *fix 1.2.3 Only set the first object if it _will_ be on the ODS
                   Expressions::set_first_object(e1);  // set as the first object on the stack frame
                   emit_data_instruction(TOSD,(ulong)pc);
               }
               else { // if (is_direct)
                // *change 1.2.9 The static ODS has been retired; instead, we keep
                // program and global ODLs which are evaluated at program close and
                // session close respectively.
                 if (pc->destructor())
                   LoadedModuleList::ODL_add(pe->global_ptr(),pc->destructor());
               } 
           }
        }	  
        else emit(TOSX);
      }    
  }
  break;
  case FCONTEXT:  // function returning an object requiring destruction 
  // *change 1.0.0 We use TPODS instruction before functions returning objects...
  	 push_object_ptr(this, e1);
	 Expressions::set_first_object(e1);  // set as the first object on the stack frame
     emit_data_instruction(TPODS,(ulong)t.as_class());
  break;
  case DCONTEXT: // dynamic scalar ctor or dtor call.
  { 
      Function *pf = e1->function();
	  PClass pc = pf->class_context();
	  int icb = (pc->has_VMT() && pf->is_constructor()) ? -1 : 0;
      compile_function_call(this,METHOD_CALL,flags,e1,true,NULL,icb,true); 
      emit(TOSX);
  }
  break;
  case VCONTEXT: // vector ctor or dtor;  static if we're passed an array entry
  {
      Function *pf = e2->function();
      int arr_sz;
      PEntry pe;
	  if (e1) {
           pe = e1->entry();
		   arr_sz = Parser::array_size(pe);
	  } else arr_sz = 0;
	  bool is_dynamic = arr_sz == 0;
      // *change 1.2.9 For each object in the _static_ array, add to the ODL;
      // The vector ctor instruction no longer pushes the ODS for static objects.
      if (! is_dynamic && pe->is_direct()) {
          PClass pc = pf->class_context();
          if (pc->destructor()) {
            char* ptr = (char*)pe->global_ptr();
            int tsz = pe->type.size();
            for (int i = 0; i < arr_sz; i++) {
              LoadedModuleList::ODL_add(ptr,pc->destructor());
              ptr += tsz;
            }
          }
      } 
      int icb = ConstructBlock::make(e1,arr_sz,is_dynamic,pf->fun_block());              
      compile_function_call(this,FUNCTION,flags,e2,true,e1,icb,is_dynamic);      
  }
  break;
  case PASS_BY_VALUE: { // needed to match MSVC object model
       int sz = t.size();
       emit(STALC,NONE,sz/sizeof(int));  // allocate on stack (pushes object stack!)
	   compile(e1);           // construct object
	   emit(DOS);             // pop OS 
       // *fix 1.2.0 There was code to reverse stuff on stack, but the UC stack now grows 
       // downwards, like most processor stacks.  This stuff has been broken since 1.1.0!!
     }
  break;

  case ADDR:
    compile(e1,AS_PTR);
    break;
  case DEREF:
    // Special case: dereferencing a pointer to an object
    // *fix 0.9.7 left stack droppings because we didn't use flags (DROP!)
    // *hack 0.9.8 AS_PTR case is different. Surely there is some pattern here?
    // *hack 1.1.2 Being on the RHS of a reference init. is now explicit!
    if (flags & AS_PTR) {
        if (! (flags & AS_REF) && t.is_class() && !t.is_pointer() && !t.is_plain_reference())
			compile(e1,flags);
        else 
          compile(e1);      
    } else {
        if (t.is_class() && !t.is_pointer()) compile(e1,flags);
        else {
          compile(e1);
          // Special case: a function ptr
          if (t.is_function()) break;
          emit_reference(NULL,flags,tcode); 
        }
    }
    break;
   case IREF:  // objects and arrays produce references
    t = ex->entry()->type; // redundant??
    if (t.is_object() || Parser::array_size(ex->entry()) > 1) emit( PEA, ex);
    else {
       if (t.is_reference()) tcode = POINTER_SZ;  // *fix 0.9.7 deref. double references
       emit_reference(ex,flags,tcode);
    }
    break;
   case ASSIGN:
    if (!e1) { // special case when ref is already on stack!
       emit(DUP);        // dup the pointer
       compile(e2);      // compile expr
       emit(is_double_number(e2->type()) ? SWAPD : SWAP);     // so ptr is TOS
       emit_reference(NULL,LVALUE,tcode);
    } else {
    // *fix 1.2.0 Assignments were not coded correctly in lvalue situations (e.g 'int& ri = (i = 10)')
      bool do_push = !(flags & DROP_VALUE), as_ref = (flags & AS_REF);
      compile(e2);
      if (do_push & ! as_ref) emit_stack_op(DUP,e2->type());
      compile(e1,LVALUE);
      if (do_push & as_ref) compile(e1,AS_PTR);
    }
    break;
   case INCR:      case DECR:
   case INCR_PTR:  case DECR_PTR:
   // 
    opcode = 0;
    if (t.is_pointer()) {
      t.decr_pointer();
      ttype = size_code(t);
    } else ttype = tcode;
    if (e1->is_entry()) { 
       Type at = e1->entry()->type;
       if (at.is_class()) {
        int sz = t.size();
        if (sz == sizeof(int)) ttype = 2; else
        if (sz == sizeof(double)) ttype = 3;
        else ttype = -1;
       }
       if (ttype != -1) {
        if (!(at.is_ref_or_ptr() && (op==INCR || op==DECR)))
         opcode = choose(op,INCR,INCC,DECR,DECC,INCR_PTR,INCPC,DECR_PTR,DECPC,0);
       } else { // ptr to struct!! Encode p = p + sizeof(T)
          if (e2!=NULL) emit_reference(e1,0,2); // postfix
          emit_reference(e1,0,2);
          emit_push_int(t.size());
          emit(op==INCR_PTR ? ADD : SUB);
          if(e2==NULL) emit(DUP); // prefix
          emit_reference(e1,LVALUE,2);
          break;
       }
    }
    if (opcode == 0) {
       opcode = (op==INCR || op==INCR_PTR) ? INCSC : DECSC;
       compile(e1,AS_PTR);                   // forced to yield a reference
       if (!(flags & DROP_VALUE)) emit(DUP); // dup if we're pushing value
       e1 = NULL;                            // force stack-relative push/pop!
    }
    if (e2==NULL) emit(opcode + ttype, e1);  // prefix
    if (!(flags & DROP_VALUE)) { 
      emit_reference(e1,flags,tcode);
      // w/ postfix, must keep the reference on TOS!
      if (e2!=NULL && e1==NULL) emit(SWAP,NONE,0);
    }
    if (e2!=NULL) emit(opcode + ttype, e1);  // postfix 
    break;

   case FUNCTION:  case DCALL: case EXPR:  case METHOD_CALL:  case EXPR_METHOD:
    compile_function_call(this,op,flags,ex);
    break;
   case BCAST:
    compile(e1);
    op = builtin_conversion(t,e1->type());
    if (op) emit(op);
    break;
   case LOG_OR: case LOG_AND:
    {
    Label l1(this);
    compile(e1);     
    jump(op==LOG_OR ? JNZND : JZND,&l1);
    compile(e2);
    Parser::check_temp_context(); // *fix 0.9.6 NB to do this _before_ any jumps
    l1.here();
    }
    break;
   case ARITH_IF:
    { Label l1(this),l2(this);
     compile(e1);
     jump(JZ,&l1);
     compile(e2->arg1(),flags);
     jump(JMP,&l2);
     l1.here();
     compile(e2->arg2(),flags);
     l2.here();  
    } break;
   case COMMA: 
   case APPEND:
     compile(e1,op == COMMA ? DROP_VALUE : 0);
     compile(e2,flags);
     break;
   case COPY_BLOCK:
     compile(e1);
     if (!(flags & DROP_VALUE)) emit(DUP);
     compile(e2);
     emit(COPY,NONE,e1->type().size());
     break;
   case INIT_REF: // *hack 1.1.2 Make reference init. case more explicit! (see DEREF)
     compile(e2,AS_PTR | AS_REF);
     compile(e1,LVALUE);
     break;
   case DYNACAST:
     compile(e1);
     emit_dynamic_cast(t);
     break;
   case REF_STUB: // make a reference out of a non-reference (not needed for constants)
     compile(e1); // put expression on stack
     compile(e2,LVALUE); // pop into temp variable 
     compile(e2,AS_PTR); // push addr of temp
     break;
   default:
     cerr << "Unrecognized opcode: " << op << endl;
     //throw string("compile failed");
     break;
   }
}
Example #22
0
// Create a new class based on an existing class
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
{
	assert (size >= Size);
	PClass *type;
	bool notnew;

	const PClass *existclass = FindClass(name);

	// This is a placeholder so fill it in
	if (existclass != NULL && existclass->Size == (unsigned)-1)
	{
		type = const_cast<PClass*>(existclass);
		if (!IsDescendantOf(type->ParentClass))
		{
			I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
		}
		DPrintf("Defining placeholder class %s\n", name.GetChars());
		notnew = true;
	}
	else
	{
		type = new PClass;
		notnew = false;
	}

	type->TypeName = name;
	type->ParentClass = this;
	type->Size = size;
	type->Pointers = NULL;
	type->ConstructNative = ConstructNative;
	if (!notnew)
	{
		type->ClassIndex = m_Types.Push (type);
	}
	type->Meta = Meta;

	// Set up default instance of the new class.
	type->Defaults = new BYTE[size];
	memcpy (type->Defaults, Defaults, Size);
	if (size > Size)
	{
		memset (type->Defaults + Size, 0, size - Size);
	}

	type->FlatPointers = NULL;
	type->bRuntimeClass = true;
	type->ActorInfo = NULL;
	type->Symbols.SetParentTable (&this->Symbols);
	if (!notnew) type->InsertIntoHash();

	// If this class has an actor info, then any classes derived from it
	// also need an actor info.
	if (this->ActorInfo != NULL)
	{
		FActorInfo *info = type->ActorInfo = new FActorInfo;
		info->Class = type;
		info->GameFilter = GAME_Any;
		info->SpawnID = 0;
		info->DoomEdNum = -1;
		info->OwnedStates = NULL;
		info->NumOwnedStates = 0;
		info->Replacement = NULL;
		info->Replacee = NULL;
		info->StateList = NULL;
		info->DamageFactors = NULL;
		info->PainChances = NULL;
		m_RuntimeActors.Push (type);
	}
	return type;
}
Example #23
0
FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, char *name)
{
	PClassActor *type = mytype;
	FState *state;
	char *namestart = name;
	char *label, *offset, *pt;
	int v;

	// Check for classname
	if ((pt = strstr (name, "::")) != NULL)
	{
		const char *classname = name;
		*pt = '\0';
		name = pt + 2;

		// The classname may either be "Super" to identify this class's immediate
		// superclass, or it may be the name of any class that this one derives from.
		if (stricmp (classname, "Super") == 0)
		{
			type = dyn_cast<PClassActor>(type->ParentClass);
			actor = GetDefaultByType(type);
		}
		else
		{
			// first check whether a state of the desired name exists
			PClass *stype = PClass::FindClass (classname);
			if (stype == NULL)
			{
				I_Error ("%s is an unknown class.", classname);
			}
			if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
			{
				I_Error ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
			}
			if (!stype->IsAncestorOf (type))
			{
				I_Error ("%s is not derived from %s so cannot access its states.",
					type->TypeName.GetChars(), stype->TypeName.GetChars());
			}
			if (type != stype)
			{
				type = static_cast<PClassActor *>(stype);
				actor = GetDefaultByType (type);
			}
		}
	}
	label = name;
	// Check for offset
	offset = NULL;
	if ((pt = strchr (name, '+')) != NULL)
	{
		*pt = '\0';
		offset = pt + 1;
	}
	v = offset ? strtol (offset, NULL, 0) : 0;

	// Get the state's address.
	if (type == mytype)
	{
		state = FindState (label);
	}
	else
	{
		state = type->FindStateByString(label, true);
	}

	if (state != NULL)
	{
		state += v;
	}
	else if (v != 0)
	{
		I_Error ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
	}
	else
	{
		Printf (TEXTCOLOR_RED "Attempt to get invalid state %s from actor %s.\n", label, type->TypeName.GetChars());
	}
	delete[] namestart;		// free the allocated string buffer
	return state;
}