summaryrefslogtreecommitdiff
path: root/texture.c
diff options
context:
space:
mode:
Diffstat (limited to 'texture.c')
-rw-r--r--texture.c594
1 files changed, 594 insertions, 0 deletions
diff --git a/texture.c b/texture.c
new file mode 100644
index 0000000..eb29d01
--- /dev/null
+++ b/texture.c
@@ -0,0 +1,594 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Stores lists of the graphical information from the WADs
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+#include "globals.h"
+
+#include <string.h>
+
+#include "texture.h"
+#include "wad.h"
+#include "mem.h"
+#include "gfx.h"
+#include "platgui.h"
+#include "gui.h"
+#include "vstring.h"
+
+
+PLAT_IMG_PICKLIST *flat_picklist=NULL;
+PLAT_IMG_PICKLIST *texture_picklist=NULL;
+
+/* The height and width of a texture are actually stored along with the
+ texture name
+*/
+#define TXTNUMWID 8
+#define TXTHEIGHT 10
+#define TXTWIDTH 20
+#define TXTMALLOC 31
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static int CmpText(const void *a,const void *b)
+{
+ const PLAT_IMG_PICKLIST *p1,*p2;
+
+ p1=a;
+ p2=b;
+
+ return(StrCaseCmp(p1->text,p2->text));
+}
+
+
+static Byte *GetShort(Byte *p,Short *s)
+{
+ *s=(Short)(*p++);
+ *s|=((Short)(*p++))<<8;
+ return(p);
+}
+
+
+static Byte *GetLong(Byte *p,Long *l)
+{
+ *l=(Long)(*p++);
+ *l|=((Long)(*p++))<<8;
+ *l|=((Long)(*p++))<<16;
+ *l|=((Long)(*p++))<<24;
+ return(p);
+}
+
+static Byte *GetName(Byte *p,char *s)
+{
+ int f;
+
+ for(f=0;f<8;f++)
+ *s++=*p++;
+
+ *s=0;
+ return(p);
+}
+
+
+static void BMPlot(int x,int y,int c,GFX_BITMAP *bm)
+{
+ if ((x>=0)&&(x<bm->w)&&(y>=0)&&(y<bm->h))
+ *(bm->data+(x)+(y*bm->w))=c;
+}
+
+
+static void DecodeLump(Byte *lump, int ox, int oy, GFX_BITMAP *bm)
+{
+ Short lw,lh,lox,loy;
+ Byte *base;
+ Byte *col;
+ Long off;
+ int x,y,f;
+ Byte cno;
+
+ base=lump;
+ lump=GetShort(lump,&lw);
+ lump=GetShort(lump,&lh);
+ lump=GetShort(lump,&lox);
+ lump=GetShort(lump,&loy);
+
+ lox=MAX(lox,0);
+ loy=MAX(loy,0);
+
+ for(x=0;x<lw;x++)
+ {
+ lump=GetLong(lump,&off);
+ col=base+off;
+
+ while(*col!=0xff)
+ {
+ y=*col++;
+ cno=*col++;
+ col++;
+
+ for(f=0;f<cno;f++)
+ {
+ BMPlot(ox+x,oy+y,(int)*col,bm);
+ col++;
+ y++;
+ }
+
+ col++;
+ }
+ }
+}
+
+
+static GFX_IMAGE GetTexture(Byte *t_ent, Byte *pn, GFX_BITMAP *bm)
+{
+ char name[9];
+ Short no,w,h,xo,yo,pno;
+ int f;
+ Byte *patch;
+
+ /* Skip over name and 2 always zero fields
+ */
+ t_ent+=8+2+2;
+
+ /* Get height and width of texture (limited to max size of bitmap)
+ */
+ t_ent=GetShort(t_ent,&w);
+ bm->w=MIN(w,MAX_GFXBM_W);
+
+ t_ent=GetShort(t_ent,&h);
+ bm->h=MIN(h,MAX_GFXBM_H);
+
+ /* Once we have the width and height, return if the actual image is not to
+ be loaded
+ */
+ if (!load_textures)
+ return(NULL);
+
+ /* Skip over always zero fields
+ */
+ t_ent+=4;
+
+ /* The bitmap is filled with the transparent colour
+ */
+ memset(bm->data,243,w*h);
+
+ /* Get no of patches that make up this texture
+ */
+ t_ent=GetShort(t_ent,&no);
+
+ /* Read each patch and add to the texture
+ */
+ for(f=0;f<no;f++)
+ {
+ /* Patch offsets and number then skip remaining
+ */
+ t_ent=GetShort(t_ent,&xo);
+ t_ent=GetShort(t_ent,&yo);
+ t_ent=GetShort(t_ent,&pno);
+ t_ent+=4;
+
+ /* Get the name from the Pname entry and load the lump
+ */
+ GetName(pn+4+8*pno,name);
+
+ if (!(patch=GetLump(name,NULL)))
+ GFX_exit(EXIT_FAILURE,"Failed to find patch %s\n",name);
+
+ /* Decode the graphics lump and load it into the bitmap
+ */
+ DecodeLump(patch,xo,yo,bm);
+
+ Release(patch);
+ }
+
+ return(GFX_create_image(bm));
+}
+
+
+static void ReadTextures(char *name,Byte *texture,
+ Byte *pn,int *i,GFX_BITMAP *bm)
+{
+ Long no;
+ Long off;
+ Byte *base;
+ int f;
+
+ base=texture;
+
+ /* Get the no of the textures
+ */
+ texture=GetLong(texture,&no);
+
+ /* Loop through all the textures and create the picklist entry
+ */
+ for(f=0;f<no;f++)
+ {
+ texture=GetLong(texture,&off);
+
+ texture_picklist[*i].text=Grab(TXTMALLOC);
+
+ GetName(base+off,texture_picklist[*i].text);
+
+ GuiDrawInfoBox((load_textures ?
+ "Please wait. Reading wall texture graphics":
+ "Please wait. Reading wall texture names"),
+ GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Lump %s|Texture %s|%d%% complete",
+ name,texture_picklist[*i].text,
+ f*100/no);
+ GFX_redraw();
+
+ texture_picklist[*i].img=GetTexture(base+off,pn,bm);
+ sprintf(texture_picklist[*i].text+TXTWIDTH,
+ "%*.*d",TXTNUMWID,TXTNUMWID,bm->w);
+ sprintf(texture_picklist[*i].text+TXTHEIGHT,
+ "%*.*d",TXTNUMWID,TXTNUMWID,bm->h);
+
+
+ (*i)++;
+ }
+}
+
+
+/* ------------------------------ EXPORTED FUNCTIONS
+*/
+
+void ReadWADFlats(void)
+{
+ WadDir *wd;
+ Iterator i;
+ int found;
+ int done;
+ GFX_BITMAP bm;
+ Byte *pal;
+ int no;
+ int ip;
+ int f;
+
+ if (!(pal=GetLump("PLAYPAL",NULL)))
+ GFX_exit(EXIT_FAILURE,"There MUST be a PLAYPAL lump in the WADs!!\n");
+
+ if (flat_picklist)
+ {
+ ip=0;
+ while(flat_picklist[ip].text)
+ {
+ Release(flat_picklist[ip].text);
+ if (flat_picklist[ip].img)
+ GFX_destroy_image(flat_picklist[ip].img);
+ }
+
+ Release(flat_picklist);
+ }
+
+ /* Get number of flats (Naughty.. Means we read through dir twice...)
+ */
+ i=GetWadDir();
+
+ found=FALSE;
+ done=FALSE;
+ no=0;
+
+ while((i)&&(!done))
+ {
+ wd=IteratorData(i);
+
+ if (!found)
+ found=!StrCaseCmp(wd->name,"F_START");
+ else
+ if (!(done=!StrCaseCmp(wd->name,"F_END")))
+ if (wd->size==0x1000)
+ no++;
+
+ i=IteratorNext(i);
+ }
+
+ IteratorClear(i);
+ flat_picklist=Grab(sizeof(PLAT_IMG_PICKLIST)*(no+1));
+ flat_picklist[no].text=NULL;
+ flat_picklist[no].img=NULL;
+
+ /* Palette and size for bitmap
+ */
+ bm.w=64;
+ bm.h=64;
+
+ for(f=0;f<256;f++)
+ {
+ int r,g,b;
+
+ r=(int)(pal[f*3]*gfx_brighten);
+ g=(int)(pal[f*3+1]*gfx_brighten);
+ b=(int)(pal[f*3+2]*gfx_brighten);
+
+ r=MIN(255,r);
+ g=MIN(255,g);
+ b=MIN(255,b);
+
+ bm.pal[f]=V_RGB(r,g,b);
+ }
+
+ /* Load in the names and graphics
+ */
+ i=GetWadDir();
+
+ found=FALSE;
+ done=FALSE;
+ ip=0;
+
+ while((i)&&(!done))
+ {
+ wd=IteratorData(i);
+
+ if (!found)
+ found=!StrCaseCmp(wd->name,"F_START");
+ else
+ if (!(done=!StrCaseCmp(wd->name,"F_END")))
+ if (wd->size==0x1000)
+ {
+ flat_picklist[ip].text=Strdup(wd->name);
+
+ if (load_flats)
+ {
+ /* GFX_BITMAP and DOOM flats are actually in the same
+ format
+ */
+ if (!(bm.data=GetLump(wd->name,NULL)))
+ GFX_exit(EXIT_FAILURE,
+ "Failed to load flat %s\n",wd->name);
+
+ flat_picklist[ip].img=GFX_create_image(&bm);
+
+ Release(bm.data);
+ }
+ else
+ flat_picklist[ip].img=NULL;
+
+ GuiDrawInfoBox((load_flats ?
+ "Please wait. Reading flat graphics":
+ "Please wait. Reading flat names"),
+ GUI_CENTRE,GUI_CENTRE,TRUE,
+ "Flat %s|%d%% complete",
+ wd->name,ip*100/no);
+ GFX_redraw();
+
+ ip++;
+ }
+
+ i=IteratorNext(i);
+ }
+
+ IteratorClear(i);
+ Release(pal);
+
+ /* Sort the list if requested
+ */
+ if (sort_flats)
+ qsort(flat_picklist,no-1,sizeof(PLAT_IMG_PICKLIST),CmpText);
+
+ /* Set the client indexes
+ */
+ for(f=0;f<no;f++)
+ flat_picklist[f].client_index=f;
+}
+
+
+void ReadWADTextures(void)
+{
+ Long t1_size,t2_size;
+ int no;
+ Byte *t1=NULL;
+ Byte *t2=NULL;
+ Byte *pn=NULL;
+ Byte *pal=NULL;
+ GFX_BITMAP bm;
+ int ip;
+ int f;
+
+ if (!(pal=GetLump("PLAYPAL",NULL)))
+ GFX_exit(EXIT_FAILURE,"There MUST be a PLAYPAL lump in the WADs!!\n");
+
+ if (!(t1=GetLump("TEXTURE1",NULL)))
+ GFX_exit(EXIT_FAILURE,"There MUST be a TEXTURE1 lump in the WADs!!\n");
+
+ if ((game==DOOM)||(game==ULTIMATE_DOOM))
+ if (!(t2=GetLump("TEXTURE2",NULL)))
+ GFX_exit(EXIT_FAILURE,
+ "There MUST be a TEXTURE2 lump in the WADs!!\n");
+
+ if (!(pn=GetLump("PNAMES",NULL)))
+ GFX_exit(EXIT_FAILURE,"There MUST be a PNAMES lump in the WADs!!\n");
+
+ if (texture_picklist)
+ {
+ ip=0;
+ while(texture_picklist[ip].text)
+ {
+ Release(texture_picklist[ip].text);
+ if (texture_picklist[ip].img)
+ GFX_destroy_image(texture_picklist[ip].img);
+ }
+
+ Release(texture_picklist);
+ }
+
+ /* Calculate the size of the resulting picklist + extra two -
+ one for the empty '-' texture and the other for the end of list marker.
+ */
+ GetLong(t1,&t1_size);
+
+ if (t2)
+ GetLong(t2,&t2_size);
+ else
+ t2_size=0;
+
+ no=t1_size+t2_size+2;
+
+ texture_picklist=Grab(sizeof(PLAT_IMG_PICKLIST)*no);
+
+ /* Storage and palette for bitmap
+ */
+ bm.data=Grab(MAX_GFXBM_W*MAX_GFXBM_H);
+
+ for(f=0;f<256;f++)
+ {
+ int r,g,b;
+
+ r=(int)(pal[f*3]*gfx_brighten);
+ g=(int)(pal[f*3+1]*gfx_brighten);
+ b=(int)(pal[f*3+2]*gfx_brighten);
+
+ r=MIN(255,r);
+ g=MIN(255,g);
+ b=MIN(255,b);
+
+ bm.pal[f]=V_RGB(r,g,b);
+ }
+
+ /* Create '-' texture
+ */
+ ip=0;
+
+ texture_picklist[ip].text=Grab(TXTMALLOC);
+ strcpy(texture_picklist[ip].text,empty_texture);
+ sprintf(texture_picklist[ip].text+TXTHEIGHT,
+ "%*.*d",TXTNUMWID,TXTNUMWID,0);
+ sprintf(texture_picklist[ip].text+TXTWIDTH,
+ "%*.*d",TXTNUMWID,TXTNUMWID,0);
+
+ texture_picklist[ip].img=NULL;
+ ip++;
+
+ /* Read the patches from TEXTURE1 and possible TEXTURE2
+ */
+ ReadTextures("TEXTURE1",t1,pn,&ip,&bm);
+
+ if (t2)
+ ReadTextures("TEXTURE2",t2,pn,&ip,&bm);
+
+ /* Create end of picklist marker
+ */
+ texture_picklist[ip].text=NULL;
+
+ Release(bm.data);
+ Release(t1);
+ Release(t2);
+ Release(pn);
+ Release(pal);
+
+ /* Sort the list if requested
+ */
+ if (sort_textures)
+ qsort(&texture_picklist[1],no-2,sizeof(PLAT_IMG_PICKLIST),CmpText);
+
+ /* Set the client indexes
+ */
+ for(f=0;f<no;f++)
+ texture_picklist[f].client_index=f;
+}
+
+
+void TextureSize(char *name, int *width, int *height)
+{
+ int f;
+
+ f=0;
+ while(texture_picklist[f].text)
+ {
+ if (STREQ(texture_picklist[f].text,name))
+ {
+ if (width)
+ *width=atoi(texture_picklist[f].text+TXTWIDTH);
+
+ if (height)
+ *height=atoi(texture_picklist[f].text+TXTHEIGHT);
+
+ return;
+ }
+
+ f++;
+ }
+
+ if (width)
+ *width=0;
+
+ if (height)
+ *height=0;
+}
+
+
+GFX_IMAGE DecodeGraphicsLump(char *lump)
+{
+ Byte *obj;
+ Byte *base;
+ Byte *pal;
+ GFX_BITMAP bm;
+ GFX_IMAGE img;
+ int f;
+ Short w,h;
+
+ if (!(obj=GetLump(lump,NULL)))
+ return(NULL);
+
+ if (!(pal=GetLump("PLAYPAL",NULL)))
+ GFX_exit(EXIT_FAILURE,"There MUST be a PLAYPAL lump in the WADs!!\n");
+
+ base=obj;
+ obj=GetShort(obj,&w);
+ obj=GetShort(obj,&h);
+
+ bm.w=w;
+ bm.h=h;
+ bm.data=Grab(w*h);
+
+ for(f=0;f<256;f++)
+ {
+ int r,g,b;
+
+ r=(int)(pal[f*3]*gfx_brighten);
+ g=(int)(pal[f*3+1]*gfx_brighten);
+ b=(int)(pal[f*3+2]*gfx_brighten);
+
+ r=MIN(255,r);
+ g=MIN(255,g);
+ b=MIN(255,b);
+
+ bm.pal[f]=V_RGB(r,g,b);
+ }
+
+ DecodeLump(base,0,0,&bm);
+
+ img=GFX_create_image(&bm);
+
+ Release(bm.data);
+ Release(base);
+ Release(pal);
+
+ return(img);
+}
+
+
+/* END OF FILE */
+