Beispiel #1
0
void MapLoader::InitED()
{
	FString filename = Level->info->EDName;
	FScanner sc;

	if (filename.IsEmpty()) return;
	int lump = Wads.CheckNumForFullName(filename, true, ns_global);
	if (lump == -1) return;
	sc.OpenLumpNum(lump);

	sc.SetCMode(true);
	while (sc.GetString())
	{
		if (sc.Compare("linedef"))
		{
			parseEDLinedef(sc, EDLines);
		}
		else if (sc.Compare("mapthing"))
		{
			parseMapthing(sc, EDThings);
		}
		else if (sc.Compare("sector"))
		{
			parseSector(sc, EDSectors);
		}
		else
		{
			sc.ScriptError("Unknown keyword '%s'", sc.String);
		}
	}
}
Beispiel #2
0
static void DoParse(const char *filename)
{
	if (TokenMap.CountUsed() == 0)
	{
		InitTokenMap();
	}

	FScanner sc;
	void *parser;
	int tokentype;
	int lump;
	bool failed;
	ZCCToken value;

	lump = Wads.CheckNumForFullName(filename, true);
	if (lump >= 0)
	{
		sc.OpenLumpNum(lump);
	}
	else if (FileExists(filename))
	{
		sc.OpenFile(filename);
	}
	else
	{
		Printf("Could not find script lump '%s'\n", filename);
		return;
	}
	
	parser = ZCCParseAlloc(malloc);
	failed = false;
#ifdef _DEBUG
	FILE *f = fopen("trace.txt", "w");
	char prompt = '\0';
	ZCCParseTrace(f, &prompt);
#endif
	ZCCParseState state(sc);

	while (sc.GetToken())
	{
		value.SourceLoc = sc.GetMessageLine();
		switch (sc.TokenType)
		{
		case TK_StringConst:
			value.String = state.Strings.Alloc(sc.String, sc.StringLen);
			tokentype = ZCC_STRCONST;
			break;

		case TK_NameConst:
			value.Int = sc.Name;
			tokentype = ZCC_NAMECONST;
			break;

		case TK_IntConst:
			value.Int = sc.Number;
			tokentype = ZCC_INTCONST;
			break;

		case TK_UIntConst:
			value.Int = sc.Number;
			tokentype = ZCC_UINTCONST;
			break;

		case TK_FloatConst:
			value.Float = sc.Float;
			tokentype = ZCC_FLOATCONST;
			break;

		case TK_Identifier:
			value.Int = FName(sc.String);
			tokentype = ZCC_IDENTIFIER;
			break;

		case TK_NonWhitespace:
			value.Int = FName(sc.String);
			tokentype = ZCC_NWS;
			break;

		default:
			TokenMapEntry *zcctoken = TokenMap.CheckKey(sc.TokenType);
			if (zcctoken != NULL)
			{
				tokentype = zcctoken->TokenType;
				value.Int = zcctoken->TokenName;
			}
			else
			{
				sc.ScriptMessage("Unexpected token %s.\n", sc.TokenName(sc.TokenType).GetChars());
				goto parse_end;
			}
			break;
		}
		ZCCParse(parser, tokentype, value, &state);
		if (failed)
		{
			sc.ScriptMessage("Parse failed\n");
			goto parse_end;
		}
	}
parse_end:
	value.Int = -1;
	ZCCParse(parser, ZCC_EOF, value, &state);
	ZCCParse(parser, 0, value, &state);
	ZCCParseFree(parser, free);

	PSymbolTable symbols(&GlobalSymbols);
	ZCCCompiler cc(state, NULL, symbols);
	cc.Compile();
#ifdef _DEBUG
	if (f != NULL)
	{
		fclose(f);
	}
	FString ast = ZCC_PrintAST(state.TopNode);
	FString astfile = ExtractFileBase(filename, false);
	astfile << ".ast";
	f = fopen(astfile, "w");
	if (f != NULL)
	{
		fputs(ast.GetChars(), f);
		fclose(f);
	}
#endif
}
Beispiel #3
0
FFont::FFont (const char *name, const char *nametemplate, const char *filetemplate, int lfirst, int lcount, int start, int fdlump, int spacewidth, bool notranslate, bool iwadonly)
{
	int i;
	FTextureID lump;
	char buffer[12];
	int maxyoffs;
	bool doomtemplate = (nametemplate && (gameinfo.gametype & GAME_DoomChex)) ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
	DVector2 Scale = { 1, 1 };

	noTranslate = notranslate;
	Lump = fdlump;
	GlobalKerning = false;
	FontName = name;
	Next = FirstFont;
	FirstFont = this;
	Cursor = '_';
	ActiveColors = 0;
	SpaceWidth = 0;
	FontHeight = 0;
	uint8_t pp = 0;
	for (auto &p : PatchRemap) p = pp++;
	translateUntranslated = false;
	int FixedWidth = 0;

	maxyoffs = 0;

	TMap<int, FTexture*> charMap;
	int minchar = INT_MAX;
	int maxchar = INT_MIN;
	
	// Read the font's configuration.
	// This will not be done for the default fonts, because they are not atomic and the default content does not need it.
	
	TArray<FolderEntry> folderdata;
	if (filetemplate != nullptr)
	{
		FStringf path("fonts/%s/", filetemplate);
		// If a name template is given, collect data from all resource files.
		// For anything else, each folder is being treated as an atomic, self-contained unit and mixing from different glyph sets is blocked.
		Wads.GetLumpsInFolder(path, folderdata, nametemplate == nullptr);
		
		//if (nametemplate == nullptr)
		{
			FStringf infpath("fonts/%s/font.inf", filetemplate);
			
			unsigned index = folderdata.FindEx([=](const FolderEntry &entry)
			{
				return infpath.CompareNoCase(entry.name) == 0;
			});
			
			if (index < folderdata.Size())
			{
				FScanner sc;
				sc.OpenLumpNum(folderdata[index].lumpnum);
				while (sc.GetToken())
				{
					sc.TokenMustBe(TK_Identifier);
					if (sc.Compare("Kerning"))
					{
						sc.MustGetValue(false);
						GlobalKerning = sc.Number;
					}
					else if (sc.Compare("Scale"))
					{
						sc.MustGetValue(true);
						Scale.Y = Scale.X = sc.Float;
						if (sc.CheckToken(','))
						{
							sc.MustGetValue(true);
							Scale.Y = sc.Float;
						}
					}
					else if (sc.Compare("SpaceWidth"))
					{
						sc.MustGetValue(false);
						SpaceWidth = sc.Number;
					}
					else if (sc.Compare("FontHeight"))
					{
						sc.MustGetValue(false);
						FontHeight = sc.Number;
					}
					else if (sc.Compare("CellSize"))
					{
						sc.MustGetValue(false);
						FixedWidth = sc.Number;
						sc.MustGetToken(',');
						sc.MustGetValue(false);
						FontHeight = sc.Number;
					}
					else if (sc.Compare("Translationtype"))
					{
						sc.MustGetToken(TK_Identifier);
						if (sc.Compare("console"))
						{
							TranslationType = 1;
						}
						else if (sc.Compare("standard"))
						{
							TranslationType = 0;
						}
						else
						{
							sc.ScriptError("Unknown translation type %s", sc.String);
						}
					}
				}
			}
		}
	}
	
	if (FixedWidth > 0)
	{
		ReadSheetFont(folderdata, FixedWidth, FontHeight, Scale);
		Type = Folder;
	}
	else
	{
		if (nametemplate != nullptr)
		{
			if (!iwadonly)
			{
				for (i = 0; i < lcount; i++)
				{
					int position = lfirst + i;
					mysnprintf(buffer, countof(buffer), nametemplate, i + start);

					lump = TexMan.CheckForTexture(buffer, ETextureType::MiscPatch);
					if (doomtemplate && lump.isValid() && i + start == 121)
					{ // HACKHACK: Don't load STCFN121 in doom(2), because
					  // it's not really a lower-case 'y' but a '|'.
					  // Because a lot of wads with their own font seem to foolishly
					  // copy STCFN121 and make it a '|' themselves, wads must
					  // provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load as a 'y'.
						if (!TexMan.CheckForTexture("STCFN120", ETextureType::MiscPatch).isValid() ||
							!TexMan.CheckForTexture("STCFN122", ETextureType::MiscPatch).isValid())
						{
							// insert the incorrectly named '|' graphic in its correct position.
							position = 124;
						}
					}
					if (lump.isValid())
					{
						Type = Multilump;
						if (position < minchar) minchar = position;
						if (position > maxchar) maxchar = position;
						charMap.Insert(position, TexMan.GetTexture(lump));
					}
				}
			}
			else
			{
				FTexture *texs[256] = {};
				if (lcount > 256 - start) lcount = 256 - start;
				for (i = 0; i < lcount; i++)
				{
					TArray<FTextureID> array;
					mysnprintf(buffer, countof(buffer), nametemplate, i + start);

					TexMan.ListTextures(buffer, array, true);
					for (auto entry : array)
					{
						FTexture *tex = TexMan.GetTexture(entry, false);
						if (tex && tex->SourceLump >= 0 && Wads.GetLumpFile(tex->SourceLump) <= Wads.GetIwadNum() && tex->UseType == ETextureType::MiscPatch)
						{
							texs[i] = tex;
						}
					}
				}
				if (doomtemplate)
				{
					// Handle the misplaced '|'.
					if (texs[121 - '!'] && !texs[120 - '!'] && !texs[122 - '!'] && !texs[124 - '!'])
					{
						texs[124 - '!'] = texs[121 - '!'];
						texs[121 - '!'] = nullptr;
					}
				}

				for (i = 0; i < lcount; i++)
				{
					if (texs[i])
					{
						int position = lfirst + i;
						Type = Multilump;
						if (position < minchar) minchar = position;
						if (position > maxchar) maxchar = position;
						charMap.Insert(position, texs[i]);
					}
				}
			}
		}
		if (folderdata.Size() > 0)
		{
			// all valid lumps must be named with a hex number that represents its Unicode character index.
			for (auto &entry : folderdata)
			{
				char *endp;
				auto base = ExtractFileBase(entry.name);
				auto position = strtoll(base.GetChars(), &endp, 16);
				if ((*endp == 0 || (*endp == '.' && position >= '!' && position < 0xffff)))
				{
					auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch);
					if (lump.isValid())
					{
						if ((int)position < minchar) minchar = (int)position;
						if ((int)position > maxchar) maxchar = (int)position;
						auto tex = TexMan.GetTexture(lump);
						tex->SetScale(Scale);
						charMap.Insert((int)position, tex);
						Type = Folder;
					}
				}
			}
		}
		FirstChar = minchar;
		LastChar = maxchar;
		auto count = maxchar - minchar + 1;
		Chars.Resize(count);
		int fontheight = 0;

		for (i = 0; i < count; i++)
		{
			auto lump = charMap.CheckKey(FirstChar + i);
			if (lump != nullptr)
			{
				FTexture *pic = *lump;
				if (pic != nullptr)
				{
					int height = pic->GetDisplayHeight();
					int yoffs = pic->GetDisplayTopOffset();

					if (yoffs > maxyoffs)
					{
						maxyoffs = yoffs;
					}
					height += abs(yoffs);
					if (height > fontheight)
					{
						fontheight = height;
					}
				}

				pic->SetUseType(ETextureType::FontChar);
				if (!noTranslate)
				{
					Chars[i].OriginalPic = pic;
					Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), "");
					Chars[i].TranslatedPic->CopySize(pic);
					Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
					TexMan.AddTexture(Chars[i].TranslatedPic);
				}
				else
				{
					Chars[i].TranslatedPic = pic;
				}

				Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth();
			}
			else
			{
				Chars[i].TranslatedPic = nullptr;
				Chars[i].XMove = INT_MIN;
			}
		}

		if (SpaceWidth == 0) // An explicit override from the .inf file must always take precedence
		{
			if (spacewidth != -1)
			{
				SpaceWidth = spacewidth;
			}
			else if ('N' - FirstChar >= 0 && 'N' - FirstChar < count && Chars['N' - FirstChar].TranslatedPic != nullptr)
			{
				SpaceWidth = (Chars['N' - FirstChar].XMove + 1) / 2;
			}
			else
			{
				SpaceWidth = 4;
			}
		}
		if (FontHeight == 0) FontHeight = fontheight;

		FixXMoves();
	}

	if (!noTranslate) LoadTranslations();
}
static void ReadReverbDef (int lump)
{
	FScanner sc;
	const ReverbContainer *def;
	ReverbContainer *newenv;
	REVERB_PROPERTIES props;
	char *name;
	int id1, id2, i, j;
	bool inited[NUM_REVERB_FIELDS];
	BYTE bools[32];

	sc.OpenLumpNum(lump);
	while (sc.GetString ())
	{
		name = copystring (sc.String);
		sc.MustGetNumber ();
		id1 = sc.Number;
		sc.MustGetNumber ();
		id2 = sc.Number;
		sc.MustGetStringName ("{");
		memset (inited, 0, sizeof(inited));
		props.Instance = 0;
		props.Flags = 0;
		while (sc.MustGetString (), NUM_REVERB_FIELDS > (i = sc.MustMatchString (ReverbFieldNames)))
		{
			if (ReverbFields[i].Float)
			{
				sc.MustGetFloat ();
				props.*ReverbFields[i].Float = (float)clamp (sc.Float,
					double(ReverbFields[i].Min)/1000,
					double(ReverbFields[i].Max)/1000);
			}
			else if (ReverbFields[i].Int)
			{
				sc.MustGetNumber ();
				props.*ReverbFields[i].Int = (j = clamp (sc.Number,
					ReverbFields[i].Min, ReverbFields[i].Max));
				if (i == 0 && j != sc.Number)
				{
					sc.ScriptError ("The Environment field is out of range.");
				}
			}
			else
			{
				sc.MustGetString ();
				bools[ReverbFields[i].Flag] = sc.MustMatchString (BoolNames);
			}
			inited[i] = true;
		}
		if (!inited[0])
		{
			sc.ScriptError ("Sound %s is missing an Environment field.", name);
		}

		// Add the new environment to the list, filling in uninitialized fields
		// with values from the standard environment specified.
		def = DefaultEnvironments[props.Environment];
		for (i = 0; i < NUM_REVERB_FIELDS; ++i)
		{
			if (ReverbFields[i].Float)
			{
				if (!inited[i])
				{
					props.*ReverbFields[i].Float = def->Properties.*ReverbFields[i].Float;
				}
			}
			else if (ReverbFields[i].Int)
			{
				if (!inited[i])
				{
					props.*ReverbFields[i].Int = def->Properties.*ReverbFields[i].Int;
				}
			}
			else
			{
				if (!inited[i])
				{
					int mask = 1 << ReverbFields[i].Flag;
					if (def->Properties.Flags & mask)
					{
						props.Flags |= mask;
					}
				}
				else
				{
					if (bools[ReverbFields[i].Flag])
					{
						props.Flags |= 1 << ReverbFields[i].Flag;
					}
				}
			}
		}

		newenv = new ReverbContainer;
		newenv->Next = NULL;
		newenv->Name = name;
		newenv->ID = (id1 << 8) | id2;
		newenv->Builtin = false;
		newenv->Properties = props;
		newenv->SoftwareWater = false;
		S_AddEnvironment (newenv);
	}
}