예제 #1
0
void FTextureManager::InitPalettedVersions()
{
	int lump, lastlump = 0;

	PalettedVersions.Clear();
	while ((lump = Wads.FindLump("PALVERS", &lastlump)) != -1)
	{
		FMemLump data = Wads.ReadLump(lump);
		Scanner sc((const char*)data.GetMem(), data.GetSize());

		while (sc.GetNextToken())
		{
			FTextureID pic1 = CheckForTexture(sc->str, FTexture::TEX_Any);
			if (!pic1.isValid())
			{
				sc.ScriptMessage(Scanner::WARNING, "Unknown texture %s to replace", sc->str.GetChars());
			}
			sc.GetNextToken();
			FTextureID pic2 = CheckForTexture(sc->str, FTexture::TEX_Any);
			if (!pic2.isValid())
			{
				sc.ScriptMessage(Scanner::WARNING, "Unknown texture %s to use as replacement", sc->str.GetChars());
			}
			if (pic1.isValid() && pic2.isValid())
			{
				PalettedVersions[pic1.GetIndex()] = pic2.GetIndex();
			}
		}
	}
}
예제 #2
0
/* Blake Stone strings are stored in text chunks. They're referenced by an
 * index. Strings are stored separated by ^XX at the end of a line.
 */
void Language::SetupBlakeStrings(const char* lumpname, const char* prefix)
{
    int lumpnum = Wads.CheckNumForName(lumpname);
    if(lumpnum == -1)
        return;

    FMemLump wadLump = Wads.ReadLump(lumpnum);

    unsigned int num = 1; // Start at prefix_1
    unsigned int pos = 0;
    unsigned int start = 0;
    const char* data = reinterpret_cast<const char*>(wadLump.GetMem());
    static const WORD endToken = ('X'<<8)|'X'; // Since both chars are the same this should be endian safe
    while(pos+2 < wadLump.GetSize())
    {
        if(data[pos] == '^' && *(WORD*)(data+pos+1) == endToken)
        {
            FString name;
            FString str(data+start, pos-start);
            name.Format("%s%d", prefix, num++);

            strings[name] = str;

            pos += 3;
            while((data[pos] == '\n' || data[pos] == '\r') && pos < wadLump.GetSize())
                ++pos;
            start = pos;
        }
        else
            ++pos;
    }
}
예제 #3
0
void FScanner :: OpenLumpNum (int lump)
{
	Close ();
	{
		FMemLump mem = Wads.ReadLump(lump);
		ScriptBuffer = mem.GetString();
	}
	ScriptName = Wads.GetLumpFullPath(lump);
	LumpNum = lump;
	PrepareScript ();
}
예제 #4
0
static void R_CreateSkinTranslation (const char *palname)
{
	FMemLump lump = Wads.ReadLump (palname);
	const BYTE *otherPal = (BYTE *)lump.GetMem();
 
	for (int i = 0; i < 256; ++i)
	{
		OtherGameSkinRemap[i] = ColorMatcher.Pick (otherPal[0], otherPal[1], otherPal[2]);
		OtherGameSkinPalette[i] = PalEntry(otherPal[0], otherPal[1], otherPal[2]);
		otherPal += 3;
	}
}
예제 #5
0
static FModel * FindModel(const char * path, const char * modelfile)
{
	FModel * model;
	FString fullname;

	fullname.Format("%s%s", path, modelfile);
	int lump = Wads.CheckNumForFullName(fullname);

	if (lump<0)
	{
		Printf("FindModel: '%s' not found\n", fullname.GetChars());
		return NULL;
	}

	for(int i = 0; i< (int)Models.Size(); i++)
	{
		if (!stricmp(fullname, Models[i]->filename)) return Models[i];
	}

	int len = Wads.LumpLength(lump);
	FMemLump lumpd = Wads.ReadLump(lump);
	char * buffer = (char*)lumpd.GetMem();

	if (!memcmp(buffer, "DMDM", 4))
	{
		model = new FDMDModel;
	}
	else if (!memcmp(buffer, "IDP2", 4))
	{
		model = new FMD2Model;
	}
	else if (!memcmp(buffer, "IDP3", 4))
	{
		model = new FMD3Model;
	}
	else
	{
		Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars());
		delete buffer;
		return NULL;
	}

	if (!model->Load(path, buffer, len))
	{
		delete model;
		delete buffer;
		return NULL;
	}
	model->filename = copystring(fullname);
	Models.Push(model);
	return model;
}
예제 #6
0
/*
=================
=
= HelpScreens
=
=================
*/
void HelpScreens (void)
{
    int lumpNum = Wads.CheckNumForName("HELPART", ns_global);
    if(lumpNum != -1)
    {
        FMemLump lump = Wads.ReadLump(lumpNum);

        backgroundFlat = TexMan(gameinfo.FinaleFlat);
        ShowArticle((char*)lump.GetMem());
    }

    VW_FadeOut();
}
예제 #7
0
// Fix for certain special patches on single-patch textures.
void FPatchTexture::HackHack (int newheight)
{
	BYTE *out;
	int x;

	Unload ();
	if (Spans != NULL)
	{
		FreeSpans (Spans);
	}

	{
		FMemLump lump = Wads.ReadLump (SourceLump);
		const patch_t *patch = (const patch_t *)lump.GetMem();

		Width = LittleShort(patch->width);
		Height = newheight;
		LeftOffset = 0;
		TopOffset = 0;

		Pixels = new BYTE[Width * Height];

		// Draw the image to the buffer
		for (x = 0, out = Pixels; x < Width; ++x)
		{
			const BYTE *in = (const BYTE *)patch + LittleLong(patch->columnofs[x]) + 3;

			for (int y = newheight; y > 0; --y)
			{
				*out = *in != 255 ? *in : Near255;
				out++, in++;
			}
			out += newheight;
		}
	}

	// Create the spans
	Spans = (Span **)M_Malloc (sizeof(Span *)*Width + sizeof(Span)*Width*2);

	Span *span = (Span *)&Spans[Width];

	for (x = 0; x < Width; ++x)
	{
		Spans[x] = span;
		span[0].Length = newheight;
		span[0].TopOffset = 0;
		span[1].Length = 0;
		span[1].TopOffset = 0;
		span += 2;
	}
}
예제 #8
0
void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
{
	int firstdup = (int)Textures.Size();

	if (lump1 >= 0)
	{
		FMemLump texdir = Wads.ReadLump (lump1);
		AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump1), lump1, patcheslump, firstdup, true);
	}
	if (lump2 >= 0)
	{
		FMemLump texdir = Wads.ReadLump (lump2);
		AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump2), lump2, patcheslump, firstdup, false);
	}
}
예제 #9
0
void FAutomapTexture::MakeTexture ()
{
	int x, y;
	FMemLump data = Wads.ReadLump (SourceLump);
	const BYTE *indata = (const BYTE *)data.GetMem();

	Pixels = new BYTE[Width * Height];

	for (x = 0; x < Width; ++x)
	{
		for (y = 0; y < Height; ++y)
		{
			Pixels[x*Height+y] = indata[x+320*y];
		}
	}
}
예제 #10
0
void FMD3Model::LoadGeometry()
{
	FMemLump lumpdata = Wads.ReadLump(mLumpNum);
	const char *buffer = (const char *)lumpdata.GetMem();
	md3_header_t * hdr = (md3_header_t *)buffer;
	md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces));

	for(int i=0;i<numSurfaces;i++)
	{
		MD3Surface * s = &surfaces[i];
		md3_surface_t * ss = surf;

		surf = (md3_surface_t *)(((char*)surf) + LittleLong(surf->Ofs_End));

		// copy triangle indices
		md3_triangle_t * tris = (md3_triangle_t*)(((char*)ss)+LittleLong(ss->Ofs_Triangles));
		s->tris = new MD3Triangle[s->numTriangles];

		for(int i=0;i<s->numTriangles;i++) for (int j=0;j<3;j++)
		{
			s->tris[i].VertIndex[j]=LittleLong(tris[i].vt_index[j]);
		}

		// Load texture coordinates
		md3_texcoord_t * tc = (md3_texcoord_t*)(((char*)ss)+LittleLong(ss->Ofs_Texcoord));
		s->texcoords = new MD3TexCoord[s->numVertices];

		for(int i=0;i<s->numVertices;i++)
		{
			s->texcoords[i].s = tc[i].s;
			s->texcoords[i].t = tc[i].t;
		}

		// Load vertices and texture coordinates
		md3_vertex_t * vt = (md3_vertex_t*)(((char*)ss)+LittleLong(ss->Ofs_XYZNormal));
		s->vertices = new MD3Vertex[s->numVertices * numFrames];

		for(int i=0;i<s->numVertices * numFrames;i++)
		{
			s->vertices[i].x = LittleShort(vt[i].x)/64.f;
			s->vertices[i].y = LittleShort(vt[i].y)/64.f;
			s->vertices[i].z = LittleShort(vt[i].z)/64.f;
			UnpackVector( LittleShort(vt[i].n), s->vertices[i].nx, s->vertices[i].ny, s->vertices[i].nz);
		}
	}
}
예제 #11
0
byte* SD_PrepareSound(int which)
{
    int size = Wads.LumpLength(which);
    if(size == 0)
        return NULL;

    FMemLump soundLump = Wads.ReadLump(which);

    byte* out = reinterpret_cast<byte*> (Mix_LoadWAV_RW(SDL_RWFromMem(soundLump.GetMem(), size), 1));
    if(!out)
        return NULL;

    // TEMPORARY WORK AROUND FOR MEMORY ERROR
    byte* nout = new byte[sizeof(Mix_Chunk)];
    memcpy(nout, out, sizeof(Mix_Chunk));
    return nout;
}
예제 #12
0
TArray<uint8_t> FAutomapTexture::CreatePalettedPixels(int conversion)
{
	int x, y;
	FMemLump data = Wads.ReadLump (SourceLump);
	const uint8_t *indata = (const uint8_t *)data.GetMem();

	TArray<uint8_t> Pixels(Width * Height, true);

	const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
	for (x = 0; x < Width; ++x)
	{
		for (y = 0; y < Height; ++y)
		{
			auto p = indata[x + 320 * y];
			Pixels[x*Height + y] = remap[p];
		}
	}
	return Pixels;
}
예제 #13
0
void FPatchTexture::HackHack (int newheight)
{
	// Check if this patch is likely to be a problem.
	// It must be 256 pixels tall, and all its columns must have exactly
	// one post, where each post has a supposed length of 0.
	FMemLump lump = Wads.ReadLump (SourceLump);
	const patch_t *realpatch = (patch_t *)lump.GetMem();
	const DWORD *cofs = realpatch->columnofs;
	int x, x2 = LittleShort(realpatch->width);

	if (LittleShort(realpatch->height) == 256)
	{
		for (x = 0; x < x2; ++x)
		{
			const column_t *col = (column_t*)((BYTE*)realpatch+LittleLong(cofs[x]));
			if (col->topdelta != 0 || col->length != 0)
			{
				break;	// It's not bad!
			}
			col = (column_t *)((BYTE *)col + 256 + 4);
			if (col->topdelta != 0xFF)
			{
				break;	// More than one post in a column!
			}
		}
		if (x == x2)
		{ 
			// If all the columns were checked, it needs fixing.
			Unload ();
			if (Spans != NULL)
			{
				FreeSpans (Spans);
			}

			Height = newheight;
			LeftOffset = 0;
			TopOffset = 0;

			hackflag = true;
			bMasked = false;	// Hacked textures don't have transparent parts.
		}
	}
}
예제 #14
0
void FTextureManager::InitSwitchList ()
{
	const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny;
	int lump = Wads.CheckNumForName ("SWITCHES");

	if (lump != -1)
	{
		FMemLump lumpdata = Wads.ReadLump (lump);
		const char *alphSwitchList = (const char *)lumpdata.GetMem();
		const char *list_p;
		FSwitchDef *def1, *def2;

		for (list_p = alphSwitchList; list_p[18] || list_p[19]; list_p += 20)
		{
			// [RH] Check for switches that aren't really switches
			if (stricmp (list_p, list_p+9) == 0)
			{
				Printf ("Switch %s in SWITCHES has the same 'on' state\n", list_p);
				continue;
			}
			// [RH] Skip this switch if its textures can't be found.
			if (CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags).Exists() &&
				CheckForTexture (list_p + 9 /* .name2 */, FTexture::TEX_Wall, texflags).Exists())
			{
				def1 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef));
				def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef));
				def1->PreTexture = def2->frames[0].Texture = CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags);
				def2->PreTexture = def1->frames[0].Texture = CheckForTexture (list_p + 9, FTexture::TEX_Wall, texflags);
				def1->Sound = def2->Sound = 0;
				def1->NumFrames = def2->NumFrames = 1;
				def1->frames[0].TimeMin = def2->frames[0].TimeMin = 0;
				def1->frames[0].TimeRnd = def2->frames[0].TimeRnd = 0;
				AddSwitchPair(def1, def2);
			}
		}
	}

	mSwitchDefs.ShrinkToFit ();
	qsort (&mSwitchDefs[0], mSwitchDefs.Size(), sizeof(FSwitchDef *), SortSwitchDefs);
}
예제 #15
0
void FIMGZTexture::MakeTexture ()
{
	FMemLump lump = Wads.ReadLump (SourceLump);
	const ImageHeader *imgz = (const ImageHeader *)lump.GetMem();
	const BYTE *data = (const BYTE *)&imgz[1];

	if (Width != 0xFFFF)
	{
		Width = LittleShort(imgz->Width);
		Height = LittleShort(imgz->Height);
		LeftOffset = LittleShort(imgz->LeftOffset);
		TopOffset = LittleShort(imgz->TopOffset);
	}

	BYTE *dest_p;
	int dest_adv = Height;
	int dest_rew = Width * Height - 1;

	CalcBitSize ();
	Pixels = new BYTE[Width*Height];
	dest_p = Pixels;

	// Convert the source image from row-major to column-major format
	if (!imgz->Compression)
	{
		for (int y = Height; y != 0; --y)
		{
			for (int x = Width; x != 0; --x)
			{
				*dest_p = *data;
				dest_p += dest_adv;
				data++;
			}
			dest_p -= dest_rew;
		}
	}
	else
	{
		// IMGZ compression is the same RLE used by IFF ILBM files
		int runlen = 0, setlen = 0;
		BYTE setval = 0;  // Shut up, GCC

		for (int y = Height; y != 0; --y)
		{
			for (int x = Width; x != 0; )
			{
				if (runlen != 0)
				{
					BYTE color = *data;
					*dest_p = color;
					dest_p += dest_adv;
					data++;
					x--;
					runlen--;
				}
				else if (setlen != 0)
				{
					*dest_p = setval;
					dest_p += dest_adv;
					x--;
					setlen--;
				}
				else
				{
					SBYTE code = *data++;
					if (code >= 0)
					{
						runlen = code + 1;
					}
					else if (code != -128)
					{
						setlen = (-code) + 1;
						setval = *data++;
					}
				}
			}
			dest_p -= dest_rew;
		}
	}
}
예제 #16
0
void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname)
{
	int remapLump, lastLump;
	char src[9];
	//bool is32bit;
	//int width, height;
	//int type, mode;
	TArray<FTextureID> tlist;

	lastLump = 0;
	src[8] = '\0';

	while ((remapLump = Wads.FindLump(lumpname, &lastLump)) != -1)
	{
		if (Wads.GetLumpFile(remapLump) == wadnum)
		{
			FMemLump lmp = Wads.ReadLump(remapLump);
			Scanner sc((const char*)lmp.GetMem(), lmp.GetSize());
			sc.SetScriptIdentifier(Wads.GetLumpFullName(remapLump));
			while (sc.CheckToken(TK_Identifier))
			{
				/*if (sc.Compare("remap")) // remap an existing texture
				{
					sc.MustGetString();

					// allow selection by type
					if (sc.Compare("wall")) type=FTexture::TEX_Wall, mode=FTextureManager::TEXMAN_Overridable;
					else if (sc.Compare("flat")) type=FTexture::TEX_Flat, mode=FTextureManager::TEXMAN_Overridable;
					else if (sc.Compare("sprite")) type=FTexture::TEX_Sprite, mode=0;
					else type = FTexture::TEX_Any, mode = 0;

					if (type != FTexture::TEX_Any) sc.MustGetString();

					sc.String[8]=0;

					tlist.Clear();
					int amount = ListTextures(sc.String, tlist);
					FName texname = sc.String;

					sc.MustGetString();
					int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches);
					if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics);

					if (tlist.Size() == 0)
					{
						Printf("Attempting to remap non-existent texture %s to %s\n",
							texname.GetChars(), sc.String);
					}
					else if (lumpnum == -1)
					{
						Printf("Attempting to remap texture %s to non-existent lump %s\n",
							texname.GetChars(), sc.String);
					}
					else
					{
						for(unsigned int i = 0; i < tlist.Size(); i++)
						{
							FTexture * oldtex = Textures[tlist[i].GetIndex()].Texture;
							int sl;

							// only replace matching types. For sprites also replace any MiscPatches
							// based on the same lump. These can be created for icons.
							if (oldtex->UseType == type || type == FTexture::TEX_Any ||
								(mode == TEXMAN_Overridable && oldtex->UseType == FTexture::TEX_Override) ||
								(type == FTexture::TEX_Sprite && oldtex->UseType == FTexture::TEX_MiscPatch &&
								(sl=oldtex->GetSourceLump()) >= 0 && Wads.GetLumpNamespace(sl) == ns_sprites)
								)
							{
								FTexture * newtex = FTexture::CreateTexture (lumpnum, FTexture::TEX_Any);
								if (newtex != NULL)
								{
									// Replace the entire texture and adjust the scaling and offset factors.
									newtex->bWorldPanning = true;
									newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
									newtex->LeftOffset = FixedMul(oldtex->GetScaledLeftOffset(), newtex->xScale);
									newtex->TopOffset = FixedMul(oldtex->GetScaledTopOffset(), newtex->yScale);
									ReplaceTexture(tlist[i], newtex, true);
								}
							}
						}
					}
				}
				else if (sc.Compare("define")) // define a new "fake" texture
				{
					sc.GetString();
					
					FString base = ExtractFileBase(sc.String, false);
					if (!base.IsEmpty())
					{
						strncpy(src, base, 8);

						int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches);
						if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics);

						sc.GetString();
						is32bit = !!sc.Compare("force32bit");
						if (!is32bit) sc.UnGet();

						sc.GetNumber();
						width = sc.Number;
						sc.GetNumber();
						height = sc.Number;

						if (lumpnum>=0)
						{
							FTexture *newtex = FTexture::CreateTexture(lumpnum, FTexture::TEX_Override);

							if (newtex != NULL)
							{
								// Replace the entire texture and adjust the scaling and offset factors.
								newtex->bWorldPanning = true;
								newtex->SetScaledSize(width, height);
								memcpy(newtex->Name, src, sizeof(newtex->Name));

								FTextureID oldtex = TexMan.CheckForTexture(src, FTexture::TEX_MiscPatch);
								if (oldtex.isValid()) 
								{
									ReplaceTexture(oldtex, newtex, true);
									newtex->UseType = FTexture::TEX_Override;
								}
								else AddTexture(newtex);
							}
						}
					}				
					//else Printf("Unable to define hires texture '%s'\n", tex->Name);
				}
				else */if (sc->str.CompareNoCase("texture") == 0)
				{
					ParseXTexture(sc, FTexture::TEX_Override);
				}
				else if (sc->str.CompareNoCase("sprite") == 0)
				{
					ParseXTexture(sc, FTexture::TEX_Sprite);
				}
				else if (sc->str.CompareNoCase("walltexture") == 0)
				{
					ParseXTexture(sc, FTexture::TEX_Wall);
				}
				else if (sc->str.CompareNoCase("flat") == 0)
				{
					ParseXTexture(sc, FTexture::TEX_Flat);
				}
				else if (sc->str.CompareNoCase("graphic") == 0)
				{
					ParseXTexture(sc, FTexture::TEX_MiscPatch);
				}
				else if(sc->str.CompareNoCase("artindex") == 0)
				{
					sc.MustGetToken(TK_IntConst);
					int index = sc->number;
					sc.MustGetToken(',');
					sc.MustGetToken(TK_StringConst);
					if(index > 255)
						sc.ScriptMessage(Scanner::ERROR, "Can't assign art index over 255.\n");
					artIndex[index].textureName = sc->str;
				}
				else
				{
					sc.ScriptMessage(Scanner::ERROR, "Texture definition expected, found '%s'", sc->str.GetChars());
				}
			}
		}
	}
}
예제 #17
0
static unsigned FindModel(const char * path, const char * modelfile)
{
	FModel * model = nullptr;
	FString fullname;

	fullname.Format("%s%s", path, modelfile);
	int lump = Wads.CheckNumForFullName(fullname);

	if (lump<0)
	{
		Printf("FindModel: '%s' not found\n", fullname.GetChars());
		return -1;
	}

	for(unsigned i = 0; i< Models.Size(); i++)
	{
		if (!Models[i]->mFileName.CompareNoCase(fullname)) return i;
	}

	int len = Wads.LumpLength(lump);
	FMemLump lumpd = Wads.ReadLump(lump);
	char * buffer = (char*)lumpd.GetMem();

	if (!memcmp(buffer, "DMDM", 4))
	{
		model = new FDMDModel;
	}
	else if (!memcmp(buffer, "IDP2", 4))
	{
		model = new FMD2Model;
	}
	else if (!memcmp(buffer, "IDP3", 4))
	{
		model = new FMD3Model;
	}

	if (model != nullptr)
	{
		if (!model->Load(path, lump, buffer, len))
		{
			delete model;
			return -1;
		}
	}
	else
	{
		// try loading as a voxel
		FVoxel *voxel = R_LoadKVX(lump);
		if (voxel != nullptr)
		{
			model = new FVoxelModel(voxel, true);
		}
		else
		{
			Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars());
			return -1;
		}
	}
	// The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized
	model->mFileName = fullname;
	return Models.Push(model);
}
예제 #18
0
void R_InitPicAnims (void)
{
	const BITFIELD texflags = FTextureManager::TEXMAN_Overridable;
		// I think better not! This is only for old ANIMATED definition that
		// don't know about ZDoom's more flexible texture system.
		// | FTextureManager::TEXMAN_TryAny;

	if (Wads.CheckNumForName ("ANIMATED") != -1)
	{
		FMemLump animatedlump = Wads.ReadLump ("ANIMATED");
		const char *animdefs = (const char *)animatedlump.GetMem();
		const char *anim_p;
		FTextureID pic1, pic2;
		int animtype;
		DWORD animspeed;

		// Init animation
		animtype = FAnimDef::ANIM_Forward;

		for (anim_p = animdefs; *anim_p != -1; anim_p += 23)
		{
			if (*anim_p /* .istexture */ & 1)
			{
				// different episode ?
				if (!(pic1 = TexMan.CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Wall, texflags)).Exists() ||
					!(pic2 = TexMan.CheckForTexture (anim_p + 1 /* .endname */, FTexture::TEX_Wall, texflags)).Exists())
					continue;		

				// [RH] Bit 1 set means allow decals on walls with this texture
				TexMan[pic2]->bNoDecals = TexMan[pic1]->bNoDecals = !(*anim_p & 2);
			}
			else
			{
				if (!(pic1 = TexMan.CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Flat, texflags)).Exists() ||
					!(pic2 = TexMan.CheckForTexture (anim_p + 1 /* .startname */, FTexture::TEX_Flat, texflags)).Exists())
					continue;
			}
			if (pic1 == pic2)
			{
				// This animation only has one frame. Skip it. (Doom aborted instead.)
				Printf ("Animation %s in ANIMATED has only one frame", anim_p + 10);
				continue;
			}

			FTexture *tex1 = TexMan[pic1];
			FTexture *tex2 = TexMan[pic2];

			if (tex1->UseType != tex2->UseType)
			{
				// not the same type - 
				continue;
			}

			if (debuganimated)
			{
				Printf("Defining animation '%s' (texture %d, lump %d, file %d) to '%s' (texture %d, lump %d, file %d)\n",
					tex1->Name, pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()),
					tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump()));
			}

			// [RH] Allow for backward animations as well as forward.
			if (pic1 > pic2)
			{
				swap (pic1, pic2);
				animtype = FAnimDef::ANIM_Backward;
			}

			// Speed is stored as tics, but we want ms so scale accordingly.
			animspeed = /* .speed */
				Scale ((BYTE(anim_p[19]) << 0) |
					   (BYTE(anim_p[20]) << 8) |
					   (BYTE(anim_p[21]) << 16) |
					   (BYTE(anim_p[22]) << 24), 1000, 35);

			R_AddSimpleAnim (pic1, pic2 - pic1 + 1, animtype, animspeed);
		}
	}
	// [RH] Load any ANIMDEFS lumps
	R_InitAnimDefs ();
	Anims.FixAnimations ();
}
예제 #19
0
void FPatchTexture::MakeTexture ()
{
	BYTE *remap, remaptable[256];
	int numspans;
	const column_t *maxcol;
	int x;

	FMemLump lump = Wads.ReadLump (SourceLump);
	const patch_t *patch = (const patch_t *)lump.GetMem();

	maxcol = (const column_t *)((const BYTE *)patch + Wads.LumpLength (SourceLump) - 3);

	// Check for badly-sized patches
#if 0	// Such textures won't be created so there's no need to check here
	if (LittleShort(patch->width) <= 0 || LittleShort(patch->height) <= 0)
	{
		lump = Wads.ReadLump ("-BADPATC");
		patch = (const patch_t *)lump.GetMem();
		Printf (PRINT_BOLD, "Patch %s has a non-positive size.\n", Name);
	}
	else if (LittleShort(patch->width) > 2048 || LittleShort(patch->height) > 2048)
	{
		lump = Wads.ReadLump ("-BADPATC");
		patch = (const patch_t *)lump.GetMem();
		Printf (PRINT_BOLD, "Patch %s is too big.\n", Name);
	}
#endif

	if (bNoRemap0)
	{
		memcpy (remaptable, GPalette.Remap, 256);
		remaptable[0] = 0;
		remap = remaptable;
	}
	else
	{
		remap = GPalette.Remap;
	}


	if (hackflag)
	{
		Pixels = new BYTE[Width * Height];
		BYTE *out;

		// Draw the image to the buffer
		for (x = 0, out = Pixels; x < Width; ++x)
		{
			const BYTE *in = (const BYTE *)patch + LittleLong(patch->columnofs[x]) + 3;

			for (int y = Height; y > 0; --y)
			{
				*out = remap[*in];
				out++, in++;
			}
		}
		return;
	}

	// Add a little extra space at the end if the texture's height is not
	// a power of 2, in case somebody accidentally makes it repeat vertically.
	int numpix = Width * Height + (1 << HeightBits) - Height;

	numspans = Width;

	Pixels = new BYTE[numpix];
	memset (Pixels, 0, numpix);

	// Draw the image to the buffer
	for (x = 0; x < Width; ++x)
	{
		BYTE *outtop = Pixels + x*Height;
		const column_t *column = (const column_t *)((const BYTE *)patch + LittleLong(patch->columnofs[x]));
		int top = -1;

		while (column < maxcol && column->topdelta != 0xFF)
		{
			if (column->topdelta <= top)
			{
				top += column->topdelta;
			}
			else
			{
				top = column->topdelta;
			}

			int len = column->length;
			BYTE *out = outtop + top;

			if (len != 0)
			{
				if (top + len > Height)	// Clip posts that extend past the bottom
				{
					len = Height - top;
				}
				if (len > 0)
				{
					numspans++;

					const BYTE *in = (const BYTE *)column + 3;
					for (int i = 0; i < len; ++i)
					{
						out[i] = remap[in[i]];
					}
				}
			}
			column = (const column_t *)((const BYTE *)column + column->length + 4);
		}
	}
}
예제 #20
0
void FTextureManager::InitAnimated (void)
{
	const BITFIELD texflags = TEXMAN_Overridable;
		// I think better not! This is only for old ANIMATED definitions that
		// don't know about ZDoom's more flexible texture system.
		// | FTextureManager::TEXMAN_TryAny;

	int lumpnum = Wads.CheckNumForName ("ANIMATED");
	if (lumpnum != -1)
	{
		FMemLump animatedlump = Wads.ReadLump (lumpnum);
		int animatedlen = Wads.LumpLength(lumpnum);
		const char *animdefs = (const char *)animatedlump.GetMem();
		const char *anim_p;
		FTextureID pic1, pic2;
		int animtype;
		DWORD animspeed;

		// Init animation
		animtype = FAnimDef::ANIM_Forward;

		for (anim_p = animdefs; *anim_p != -1; anim_p += 23)
		{
			// make sure the current chunk of data is inside the lump boundaries.
			if (anim_p + 22 >= animdefs + animatedlen)
			{
				I_Error("Tried to read past end of ANIMATED lump.");
			}
			if (*anim_p /* .istexture */ & 1)
			{
				// different episode ?
				if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Wall, texflags)).Exists() ||
					!(pic2 = CheckForTexture (anim_p + 1 /* .endname */, FTexture::TEX_Wall, texflags)).Exists())
					continue;		

				// [RH] Bit 1 set means allow decals on walls with this texture
				Texture(pic2)->bNoDecals = Texture(pic1)->bNoDecals = !(*anim_p & 2);
			}
			else
			{
				if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Flat, texflags)).Exists() ||
					!(pic2 = CheckForTexture (anim_p + 1 /* .startname */, FTexture::TEX_Flat, texflags)).Exists())
					continue;
			}

			FTexture *tex1 = Texture(pic1);
			FTexture *tex2 = Texture(pic2);

			animspeed = (BYTE(anim_p[19]) << 0)  | (BYTE(anim_p[20]) << 8) |
						(BYTE(anim_p[21]) << 16) | (BYTE(anim_p[22]) << 24);

			// SMMU-style swirly hack? Don't apply on already-warping texture
			if (animspeed > 65535 && tex1 != NULL && !tex1->bWarped)
			{
				FTexture *warper = new FWarp2Texture (tex1);
				ReplaceTexture (pic1, warper, false);
			}
			// These tests were not really relevant for swirling textures, or even potentially
			// harmful, so they have been moved to the else block.
			else
			{
				if (tex1->UseType != tex2->UseType)
				{
					// not the same type - 
					continue;
				}

				if (debuganimated)
				{
					Printf("Defining animation '%s' (texture %d, lump %d, file %d) to '%s' (texture %d, lump %d, file %d)\n",
						tex1->Name, pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()),
						tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump()));
				}

				if (pic1 == pic2)
				{
					// This animation only has one frame. Skip it. (Doom aborted instead.)
					Printf ("Animation %s in ANIMATED has only one frame\n", anim_p + 10);
					continue;
				}
				// [RH] Allow for backward animations as well as forward.
				else if (pic1 > pic2)
				{
					swapvalues (pic1, pic2);
					animtype = FAnimDef::ANIM_Backward;
				}

				// Speed is stored as tics, but we want ms so scale accordingly.
				AddSimpleAnim (pic1, pic2 - pic1 + 1, animtype, Scale (animspeed, 1000, 35));
			}
		}
	}
}
예제 #21
0
static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerColorSet *colorset,
	FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable, FRemapTable *pillartable)
{
	int i;
	BYTE start = skin->range0start;
	BYTE end = skin->range0end;
	float r, g, b;
	float bases, basev;
	float sdelta, vdelta;
	float range;

	// Set up the base translation for this skin. If the skin was created
	// for the current game, then this is just an identity translation.
	// Otherwise, it remaps the colors from the skin's original palette to
	// the current one.
	if (skin->othergame)
	{
		memcpy (table->Remap, OtherGameSkinRemap, table->NumEntries);
		memcpy (table->Palette, OtherGameSkinPalette, sizeof(*table->Palette) * table->NumEntries);
	}
	else
	{
		for (i = 0; i < table->NumEntries; ++i)
		{
			table->Remap[i] = i;
		}
		memcpy(table->Palette, GPalette.BaseColors, sizeof(*table->Palette) * table->NumEntries);
	}
	for (i = 1; i < table->NumEntries; ++i)
	{
		table->Palette[i].a = 255;
	}

	// [GRB] Don't translate skins with color range 0-0 (APlayerPawn default)
	if (start == 0 && end == 0)
	{
		table->Inactive = true;
		table->UpdateNative();
		return;
	}

	table->Inactive = false;
	range = (float)(end-start+1);

	bases = s;
	basev = v;

	if (colorset != NULL && colorset->Lump >= 0 && Wads.LumpLength(colorset->Lump) < 256)
	{ // Bad table length. Ignore it.
		colorset = NULL;
	}

	if (colorset != NULL)
	{
		bool identity = true;
		// Use the pre-defined range instead of a custom one.
		if (colorset->Lump < 0)
		{
			identity &= SetRange(table, start, end, colorset->FirstColor, colorset->LastColor);
			for (i = 0; i < colorset->NumExtraRanges; ++i)
			{
				identity &= SetRange(table,
					colorset->Extra[i].RangeStart, colorset->Extra[i].RangeEnd,
					colorset->Extra[i].FirstColor, colorset->Extra[i].LastColor);
			}
		}
		else
		{
			FMemLump translump = Wads.ReadLump(colorset->Lump);
			const BYTE *trans = (const BYTE *)translump.GetMem();
			for (i = start; i <= end; ++i)
			{
				table->Remap[i] = GPalette.Remap[trans[i]];
				identity &= (trans[i] == i);
				table->Palette[i] = GPalette.BaseColors[table->Remap[i]];
				table->Palette[i].a = 255;
			}
		}
		// If the colorset created an identity translation mark it as inactive
		table->Inactive = identity;
	}
	else if (gameinfo.gametype & GAME_DoomStrifeChex)
	{
		// Build player sprite translation
		s -= 0.23f;
		v += 0.1f;
		sdelta = 0.23f / range;
		vdelta = -0.94112f / range;

		for (i = start; i <= end; i++)
		{
			float uses, usev;
			uses = clamp (s, 0.f, 1.f);
			usev = clamp (v, 0.f, 1.f);
			HSVtoRGB (&r, &g, &b, h, uses, usev);
			SetRemap(table, i, r, g, b);
			s += sdelta;
			v += vdelta;
		}
	}
	else if (gameinfo.gametype == GAME_Heretic)
	{
		float vdelta = 0.418916f / range;

		// Build player sprite translation
		for (i = start; i <= end; i++)
		{
			v = vdelta * (float)(i - start) + basev - 0.2352937f;
			v = clamp (v, 0.f, 1.f);
			HSVtoRGB (&r, &g, &b, h, s, v);
			SetRemap(table, i, r, g, b);
		}

		// Build rain/lifegem translation
		if (alttable)
		{
			bases = MIN (bases*1.3f, 1.f);
			basev = MIN (basev*1.3f, 1.f);
			for (i = 145; i <= 168; i++)
			{
				s = MIN (bases, 0.8965f - 0.0962f*(float)(i - 161));
				v = MIN (1.f, (0.2102f + 0.0489f*(float)(i - 144)) * basev);
				HSVtoRGB (&r, &g, &b, h, s, v);
				SetRemap(alttable, i, r, g, b);
				SetPillarRemap(pillartable, i, h, s, v);
			}
			alttable->UpdateNative();
		}
	}
	else if (gameinfo.gametype == GAME_Hexen)
	{
		if (memcmp (sprites[skin->sprite].name, "PLAY", 4) == 0)
		{ // The fighter is different! He gets a brown hairy loincloth, but the other
		  // two have blue capes.
			float vs[9] = { .28f, .32f, .38f, .42f, .47f, .5f, .58f, .71f, .83f };

			// Build player sprite translation
			//h = 45.f;
			v = MAX (0.1f, v);

			for (i = start; i <= end; i++)
			{
				HSVtoRGB (&r, &g, &b, h, s, vs[(i-start)*9/(int)range]*basev);
				SetRemap(table, i, r, g, b);
			}
		}
		else
		{
			float ms[18] = { .95f, .96f, .89f, .97f, .97f, 1.f, 1.f, 1.f, .97f, .99f, .87f, .77f, .69f, .62f, .57f, .47f, .43f };
			float mv[18] = { .16f, .19f, .22f, .25f, .31f, .35f, .38f, .41f, .47f, .54f, .60f, .65f, .71f, .77f, .83f, .89f, .94f, 1.f };

			// Build player sprite translation
			v = MAX (0.1f, v);

			for (i = start; i <= end; i++)
			{
				HSVtoRGB (&r, &g, &b, h, ms[(i-start)*18/(int)range]*bases, mv[(i-start)*18/(int)range]*basev);
				SetRemap(table, i, r, g, b);
			}
		}
	}
	if (gameinfo.gametype == GAME_Hexen && alttable != NULL)
	{
		// Build Hexen's lifegem translation.
		
		// Is the player's translation range the same as the gem's and we are using a
		// predefined translation? If so, then use the same one for the gem. Otherwise,
		// build one as per usual.
		if (colorset != NULL && start == 164 && end == 185)
		{
			*alttable = *table;
		}
		else
		{
			for (i = 164; i <= 185; ++i)
			{
				const PalEntry *base = &GPalette.BaseColors[i];
				float dummy;

				RGBtoHSV (base->r/255.f, base->g/255.f, base->b/255.f, &dummy, &s, &v);
				HSVtoRGB (&r, &g, &b, h, s*bases, v*basev);
				SetRemap(alttable, i, r, g, b);
			}
		}
		alttable->UpdateNative();
	}
	table->UpdateNative();
}
예제 #22
0
void FPatchTexture::MakeTexture ()
{
	BYTE *remap, remaptable[256];
	Span *spanstuffer, *spanstarter;
	const column_t *maxcol;
	bool warned;
	int numspans;
	int x;

	FMemLump lump = Wads.ReadLump (SourceLump);
	const patch_t *patch = (const patch_t *)lump.GetMem();

	maxcol = (const column_t *)((const BYTE *)patch + Wads.LumpLength (SourceLump) - 3);

	// Check for badly-sized patches
	if (LittleShort(patch->width) <= 0 || LittleShort(patch->height) <= 0)
	{
		lump = Wads.ReadLump ("-BADPATC");
		patch = (const patch_t *)lump.GetMem();
		Printf (PRINT_BOLD, "Patch %s has a non-positive size.\n", Name);
	}
	else if (LittleShort(patch->width) > 2048 || LittleShort(patch->height) > 2048)
	{
		lump = Wads.ReadLump ("-BADPATC");
		patch = (const patch_t *)lump.GetMem();
		Printf (PRINT_BOLD, "Patch %s is too big.\n", Name);
	}

	// Add a little extra space at the end if the texture's height is not
	// a power of 2, in case somebody accidentally makes it repeat vertically.
	int numpix = Width * Height + (1 << HeightBits) - Height;

	numspans = Width;

	Pixels = new BYTE[numpix];
	memset (Pixels, 0, numpix);

	if (bNoRemap0)
	{
		memcpy (remaptable, GPalette.Remap, 256);
		remaptable[0] = 0;
		remap = remaptable;
	}
	else
	{
		remap = GPalette.Remap;
	}

	// Draw the image to the buffer
	for (x = 0; x < Width; ++x)
	{
		BYTE *outtop = Pixels + x*Height;
		const column_t *column = (const column_t *)((const BYTE *)patch + LittleLong(patch->columnofs[x]));
		int top = -1;

		while (column < maxcol && column->topdelta != 0xFF)
		{
			if (column->topdelta <= top)
			{
				top += column->topdelta;
			}
			else
			{
				top = column->topdelta;
			}

			int len = column->length;
			BYTE *out = outtop + top;

			if (len != 0)
			{
				if (top + len > Height)	// Clip posts that extend past the bottom
				{
					len = Height - top;
				}
				if (len > 0)
				{
					numspans++;

					const BYTE *in = (const BYTE *)column + 3;
					for (int i = 0; i < len; ++i)
					{
						out[i] = remap[in[i]];
					}
				}
			}
			column = (const column_t *)((const BYTE *)column + column->length + 4);
		}
	}

	// Create the spans
	if (Spans != NULL)
	{
		return;
	}

	Spans = (Span **)M_Malloc (sizeof(Span*)*Width + sizeof(Span)*numspans);
	spanstuffer = (Span *)((BYTE *)Spans + sizeof(Span*)*Width);
	warned = false;

	for (x = 0; x < Width; ++x)
	{
		const column_t *column = (const column_t *)((const BYTE *)patch + LittleLong(patch->columnofs[x]));
		int top = -1;

		Spans[x] = spanstuffer;
		spanstarter = spanstuffer;

		while (column < maxcol && column->topdelta != 0xFF)
		{
			if (column->topdelta <= top)
			{
				top += column->topdelta;
			}
			else
			{
				top = column->topdelta;
			}

			int len = column->length;

			if (len != 0)
			{
				if (top + len > Height)	// Clip posts that extend past the bottom
				{
					len = Height - top;
				}
				if (len > 0)
				{
					// There is something of this post to draw. If it starts at the same
					// place where the previous span ends, add it to that one. If it starts
					// before the other one ends, that's bad, but deal with it. If it starts
					// after the previous one ends, create another span.

					// Assume we need to create another span.
					spanstuffer->TopOffset = top;
					spanstuffer->Length = len;

					// Now check if that's really the case.
					if (spanstuffer > spanstarter)
					{
						if ((spanstuffer - 1)->TopOffset + (spanstuffer - 1)->Length == top)
						{
							(--spanstuffer)->Length += len;
						}
						else
						{
							int prevbot;

							while (spanstuffer > spanstarter &&
								spanstuffer->TopOffset < (prevbot = 
								(spanstuffer - 1)->TopOffset + (spanstuffer - 1)->Length))
							{
								if (spanstuffer->TopOffset < (spanstuffer - 1)->TopOffset)
								{
									(spanstuffer - 1)->TopOffset = spanstuffer->TopOffset;
								}
								(spanstuffer - 1)->Length = MAX(prevbot,
									spanstuffer->TopOffset + spanstuffer->Length)
									- (spanstuffer - 1)->TopOffset;
								spanstuffer--;
								if (!warned)
								{
									warned = true;
									Printf (PRINT_BOLD, "Patch %s is malformed.\n", Name);
								}
							}
						}
					}
					spanstuffer++;
				}
			}
			column = (const column_t *)((const BYTE *)column + column->length + 4);
		}

		spanstuffer->Length = spanstuffer->TopOffset = 0;
		spanstuffer++;
	}
}
예제 #23
0
void DIntermissionScreen::Init(FIntermissionAction *desc, bool first)
{
	int lumpnum;

	if (desc->mCdTrack == 0 || !S_ChangeCDMusic (desc->mCdTrack, desc->mCdId))
	{
		if (desc->mMusic.IsEmpty())
		{
			// only start the default music if this is the first action in an intermission
			if (first) S_ChangeMusic (gameinfo.finaleMusic, gameinfo.finaleOrder, desc->mMusicLooping);
		}
		else
		{
			S_ChangeMusic (desc->mMusic, desc->mMusicOrder, desc->mMusicLooping);
		}
	}
	mDuration = desc->mDuration;

	const char *texname = desc->mBackground;
	if (*texname == '@')
	{
		char *pp;
		unsigned int v = strtoul(texname+1, &pp, 10) - 1;
		if (*pp == 0 && v < gameinfo.finalePages.Size())
		{
			texname = gameinfo.finalePages[v].GetChars();
		}
		else if (gameinfo.finalePages.Size() > 0)
		{
			texname = gameinfo.finalePages[0].GetChars();
		}
		else
		{
			texname = gameinfo.TitlePage.GetChars();
		}
	}
	else if (*texname == '$')
	{
		texname = GStrings[texname+1];
	}
	if (texname[0] != 0)
	{
		mBackground = TexMan.CheckForTexture(texname, FTexture::TEX_MiscPatch);
		mFlatfill = desc->mFlatfill;
	}
	S_Sound (CHAN_VOICE | CHAN_UI, desc->mSound, 1.0f, ATTN_NONE);
	if (desc->mPalette.IsNotEmpty() && (lumpnum = Wads.CheckNumForFullName(desc->mPalette, true)) > 0)
	{
		PalEntry *palette;
		const BYTE *orgpal;
		FMemLump lump;
		int i;

		lump = Wads.ReadLump (lumpnum);
		orgpal = (BYTE *)lump.GetMem();
		palette = screen->GetPalette ();
		for (i = 256; i > 0; i--, orgpal += 3)
		{
			*palette++ = PalEntry (orgpal[0], orgpal[1], orgpal[2]);
		}
		screen->UpdatePalette ();
		mPaletteChanged = true;
		NoWipe = 1;
		M_EnableMenu(false);
	}
	mOverlays.Resize(desc->mOverlays.Size());
	for (unsigned i=0; i < mOverlays.Size(); i++)
	{
		mOverlays[i].x = desc->mOverlays[i].x;
		mOverlays[i].y = desc->mOverlays[i].y;
		mOverlays[i].mCondition = desc->mOverlays[i].mCondition;
		mOverlays[i].mPic = TexMan.CheckForTexture(desc->mOverlays[i].mName, FTexture::TEX_MiscPatch);
	}
	mTicker = 0;
}
예제 #24
0
void Language::ReadLump(int lump, const char* language)
{
    FMemLump wadLump = Wads.ReadLump(lump);
    Scanner sc((const char*)(wadLump.GetMem()), wadLump.GetSize());
    sc.SetScriptIdentifier(Wads.GetLumpFullName(lump));

    int token = TK_NoToken;
    bool skip = false;
    bool noReplace = false;
    while(sc.GetNextToken())
    {
        token = sc->token;
        if(token == '[')
        {
            // match with language
            sc.MustGetToken(TK_Identifier);
            if(sc->str.Compare(language) != 0)
                skip = true;
            else
            {
                skip = false;
                noReplace = false;
            }

            if(sc.CheckToken(TK_Identifier))
            {
                if(sc->str.Compare("default") == 0)
                {
                    // if not the correct language, go in no replace mode.
                    if(skip)
                    {
                        skip = false;
                        noReplace = true;
                    }
                }
                else
                {
                    printf("Unexpected identifier '%s'\n", sc->str.GetChars());
                    exit(0);
                }
            }

            sc.MustGetToken(']');
        }
        else if(token == TK_Identifier)
        {
            FName index = sc->str;
            sc.MustGetToken('=');
            sc.MustGetToken(TK_StringConst);
            if(!skip)
            {
                if(!noReplace || (noReplace && strings.CheckKey(index) == NULL))
                    strings[index] = sc->str;
            }
            sc.MustGetToken(';');
        }
        else
        {
            sc.ScriptMessage(Scanner::ERROR, "Unexpected token.\n");
            exit(0);
        }
    }
}