diff options
Diffstat (limited to 'texture.c')
-rw-r--r-- | texture.c | 594 |
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 */ + |