/* Texture display by Rapha‰l Quinet , Trevor Phillips , and Christian Johannes Schladetsch You are allowed to use any parts of this code in another program, as long as you give credits to the authors in the documentation and in the program itself. Read the file README.1ST for more information. This program comes with absolutely no warranty. TEXTURES.C - Textures in 256 colors. */ /* the includes */ #include "deu.h" #include "wstructs.h" #include typedef struct _resource { char *name; void *data; struct _resource *next; } resource; resource *ResourceList; Bool ForgetAfter = TRUE; /* whether DisplayPic should de-allocate the picture resource after displaying it */ /* display a floor or ceiling texture at coords x0, y0 and not beyond x1, y1 */ void DisplayFloorTexture( BCINT x0, BCINT y0, BCINT x1, BCINT y1, char *texname) { MDirPtr dir; unsigned char huge *pixels; dir = FindMasterDir( MasterDir, texname); if (dir == NULL) { SetColor( DARKGRAY); DrawScreenLine( x0, y0, x1, y1); DrawScreenLine( x0, y1, x1, y0); return; } BasicWadSeek( dir->wadfile, dir->dir.start); #if defined(__TURBOC__) pixels = (unsigned char huge*) GetFarMemory( 4100 * sizeof( char)); BasicWadRead( dir->wadfile, &(pixels[ 4]), 4096L); if (GfxMode < -1) { /* Probably a bug in the VESA driver... */ /* It requires "size-1" instead of "size"! */ ((UBCINT huge *)pixels)[ 0] = 63; ((UBCINT huge *)pixels)[ 1] = 63; } else { ((UBCINT huge *)pixels)[ 0] = 64; ((UBCINT huge *)pixels)[ 1] = 64; } #elif defined(__GNUC__) /* bcc2grx's getimage-bitmap has a lot more info in it's header than borland's */ pixels = (unsigned char*) GetFarMemory( 4096+sizeof(GrContext)); getimage( x0, y0, x0+63, y0+63, pixels); /* Hack! */ BasicWadRead( dir->wadfile, pixels+sizeof(GrContext), 4096L); #endif putimage( x0, y0, pixels, COPY_PUT); FreeFarMemory( pixels); } /* display a picture "picname" at coords x0, y0 and not beyond x1, y1 */ /* SO 2/4/95: DisplayPic now uses GetResource to get the sprite/patch to display. It checks the variable ForgetAfter to see whether it should call ForgetResource after displaying; this should be set by the caller. ChooseSprite sets this to TRUE; DisplayWallTexture sets it to FALSE. DisplayWallTexture then takes the responsibility for calling ForgetResource for all the patches in the texture being displayed. This enables us to buffer all the patches in case they are used more than once in a texture (e.g. LITE5 in Doom (extreme case!)) */ void DisplayPic( BCINT x0, BCINT y0, BCINT x1, BCINT y1, char *picname) { PHeader *h; PColumn **columns, *c; BCINT x, y; BYTE *pixels; long p_resource; if(bioskey(1)) return; p_resource = (long)GetResource(picname); if(!p_resource) return; h = (PHeader *)p_resource; columns = (PColumn **)(p_resource + sizeof(PHeader)); for(x = 0; x < h->width; x++) { if(x > (x1 - x0)) continue; c = (PColumn *)((long)columns[x] + p_resource); while(c->yofs != 255) { pixels = (BYTE *)((long)c + (long)sizeof(PColumn) + (long)c->npixels + 1L); for(y = c->npixels; y >= 0; y--) { if((y + c->yofs) > (y1 - y0)) pixels--; else putpixel(x + x0, y + y0 + c->yofs, *pixels--); } c = (PColumn *)((long)c + (long)(c->npixels) + 4L); } } if(ForgetAfter) ForgetResource(picname); } void *GetResource(char *name) { void *t = NULL; resource *p, *new = (resource *)NULL; MDirPtr r; for(p = ResourceList; p; p = p->next) if(!strcmp(name, p->name)) return p->data; r = FindMasterDir(MasterDir, name); if(r && (t = GetMemory(r->dir.size))) { BasicWadSeek(r->wadfile, r->dir.start); BasicWadRead(r->wadfile, t, r->dir.size); new = (resource *)GetMemory(sizeof(resource)); assert(new); new->data = t; new->name = strdup(name); new->next = ResourceList; ResourceList = new; return t; } return NULL; } void ForgetResource(char *name) { resource *p, *q = NULL; for(p = ResourceList; p->next; q = p, p = p->next) { if(!strcmp(p->name, name)) { if(p == ResourceList) ResourceList = p->next; else q->next = p->next; FreeMemory(p->data); FreeMemory(p->name); FreeMemory(p); return; } } } void ForgetAllResources() { resource *p, *q; for(p = ResourceList; p; p = q) { q = p->next; FreeMemory(p->data); FreeMemory(p->name); FreeMemory(p); } } Texture *FindTexture(char *name) { Texture *t; SList p; for(p = Texture_sections; p; p = p->next) { t = FindTextureIn(name, GetResource(p->string)); if(t) return t; } return NULL; } Texture *FindTextureIn(char *name, void *tblock) { long i, *offsets = tblock; Texture *t; if(tblock) for(i = 1; i <= offsets[0]; i++) { t = (Texture *)((long)offsets[i] + (long)tblock); if(!strncmp(t->name, name, 8)) return t; } return NULL; } /* display a wall texture at coords x0, y0 */ void DisplayWallTexture( BCINT x0, BCINT y0, BCINT x1, BCINT y1, char *texname) { BCINT n, xsize, ysize; Texture *tinfo; PatchDesc *pinfo; char picname[9]; long patchname; void *Pnames; if (bioskey( 1) != 0) return; /* speedup */ Pnames = GetResource("PNAMES"); /* clear the box where the texture size will be drawn - see below */ SetColor(DARKGRAY); DrawScreenBox( x0 - 171, y0 + 40, x0 - 82, y0 + 70); if (!(tinfo = FindTexture(texname))) return; /* read the info for this texture */ xsize = tinfo->width; ysize = tinfo->height; SetColor( BLACK); DrawScreenText( x0 - 171, y0 + 40, "%dx%d", xsize, ysize); if (tinfo->nPatches == 1) DrawScreenText( x0 - 171, y0 + 60, "Transparent"); else DrawScreenText( x0 - 171, y0 + 60, "%d Patches", tinfo->nPatches); if (bioskey( 1) != 0) return; /* speedup */ if (x1 - x0 > xsize) x1 = x0 + xsize; if (y1 - y0 > ysize) y1 = y0 + ysize; /* not really necessary, except when xofs or yofs < 0 */ setviewport( x0, y0, x1, y1, TRUE); /* display the texture */ pinfo = (PatchDesc *)((long)tinfo + sizeof(Texture)); ForgetAfter = FALSE; for (n = 0; n < tinfo->nPatches; n++, pinfo++) { /* OK, now look up the pic's name in Pnames. */ patchname = (long)Pnames + 4L + ((long)(pinfo->PatchNumber) * 8); strncpy(picname, (char *)patchname, 8); picname[ 8] = '\0'; /* coords changed because of the "setviewport" */ DisplayPic( pinfo->xOffset, pinfo->yOffset, x1 - x0, y1 - y0, strupr( picname)); } /* de-allocate all patches */ pinfo = (PatchDesc *)((long)tinfo + sizeof(Texture)); for (n = 0; n < tinfo->nPatches; n++, pinfo++) { patchname = (long)Pnames + 4L + ((long)(pinfo->PatchNumber) * 8); strncpy(picname, (char *)patchname, 8); picname[ 8] = '\0'; ForgetResource(picname); } /* restore the normal viewport */ setviewport( 0, 0, ScrMaxX, ScrMaxY, TRUE); } /* Function to get the size of a wall texture It's a lot smaller now that we have functions to get a pointer to the texture structure automagically :-) */ void GetWallTextureSize( BCINT *xsize_r, BCINT *ysize_r, char *texname) { Texture *t = FindTexture(texname); if(t) { *xsize_r = t->width; *ysize_r = t->height; } else { /* texture data not found */ *xsize_r = -1; *ysize_r = -1; } } /* choose a floor or ceiling texture */ void ChooseFloorTexture( BCINT x0, BCINT y0, char *prompt, BCINT listsize, char **list, char *name) { if (UseMouse) HideMousePointer(); SwitchToVGA256(); /* if we only have a 320x200x256 VGA driver, we must change x0 and y0. Yuck! */ if (GfxMode > -2) { x0 = -1; y0 = -1; } InputNameFromListWithFunc( x0, y0, prompt, listsize, list, 5, name, 64, 64, DisplayFloorTexture); SwitchToVGA16(); if (UseMouse) ShowMousePointer(); } /* choose a wall texture */ void ChooseWallTexture( BCINT x0, BCINT y0, char *prompt, BCINT listsize, char **list, char *name) { if (UseMouse) HideMousePointer(); SwitchToVGA256(); /* if we only have a 320x200x256 VGA driver, we must change x0 and y0. Yuck! */ if (GfxMode > -2) { x0 = 0; y0 = -1; } InputNameFromListWithFunc( x0, y0, prompt, listsize, list, 11, name, 256, 128, DisplayWallTexture); SwitchToVGA16(); if (UseMouse) ShowMousePointer(); } /* function used by qsort to sort the sprite names */ int SortSprites( const void *a, const void *b) { return strcmp( *((char **)a), *((char **)b)); } /* choose a "sprite" */ void ChooseSprite( BCINT x0, BCINT y0, char *prompt, char *sname) { MDirPtr dir; BCINT n, listsize; char **list; char name[ 9]; /* count the names */ dir = FindMasterDir( MasterDir, "S_START"); dir = dir->next; for (n = 0; dir && strcmp(dir->dir.name, "S_END"); n++) dir = dir->next; listsize = n; /* get the actual names from master dir. */ dir = FindMasterDir( MasterDir, "S_START"); dir = dir->next; list = (char**) GetMemory( listsize * sizeof( char *)); for (n = 0; n < listsize; n++) { list[ n] = (char*) GetMemory( 9 * sizeof( char)); strncpy( list[ n], dir->dir.name, 8); list[ n][ 8] = '\0'; dir = dir->next; } qsort( list, listsize, sizeof( char *), SortSprites); if (sname != NULL) strncpy( name, sname, 8); else strcpy( name, list[ 0]); /* if (UseMouse) HideMousePointer(); */ SwitchToVGA256(); /* if we only have a 320x200x256 VGA driver, we must change x0 and y0. Yuck! */ if (GfxMode > -2) { x0 = 0; y0 = -1; } ForgetAfter = TRUE; InputNameFromListWithFunc( x0, y0, prompt, listsize, list, 11, name, 256, 128, DisplayPic); /* SwitchToVGA16(); if (UseMouse) ShowMousePointer(); */ for (n = 0; n < listsize; n++) FreeMemory( list[ n]); FreeMemory( list); }