home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the DOOM Programming Gurus / Tricks_of_the_Doom_Programming_Gurus.iso / bonus / editors / deth / source / textures.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-03  |  10.0 KB  |  426 lines

  1. /*
  2.    Texture display by RaphaĆ«l Quinet <quinet@montefiore.ulg.ac.be>,
  3.    Trevor Phillips <rphillip@cc.curtin.edu.au>,
  4.    and Christian Johannes Schladetsch <s924706@yallara.cs.rmit.OZ.AU>
  5.    
  6.    You are allowed to use any parts of this code in another program, as
  7.    long as you give credits to the authors in the documentation and in
  8.    the program itself.  Read the file README.1ST for more information.
  9.    
  10.    This program comes with absolutely no warranty.
  11.    
  12.    TEXTURES.C - Textures in 256 colors.
  13.    */
  14.  
  15. /* the includes */
  16. #include "deu.h"
  17. #include "wstructs.h"
  18. #include <assert.h>
  19.  
  20. typedef struct _resource {
  21.     char *name;
  22.     void *data;
  23.     struct _resource *next;
  24. } resource;
  25.  
  26. resource *ResourceList;
  27.  
  28. Bool ForgetAfter = TRUE;
  29. /* whether DisplayPic should de-allocate the picture resource
  30.    after displaying it */
  31.  
  32. /*
  33.    display a floor or ceiling texture at coords x0, y0 and not beyond x1, y1
  34.    */
  35.  
  36. void DisplayFloorTexture( BCINT x0, BCINT y0, BCINT x1, BCINT y1, char *texname)
  37. {
  38.     MDirPtr             dir;
  39.     unsigned char huge *pixels;
  40.     
  41.     dir = FindMasterDir( MasterDir, texname);
  42.     if (dir == NULL) {
  43.         SetColor( DARKGRAY);
  44.         DrawScreenLine( x0, y0, x1, y1);
  45.         DrawScreenLine( x0, y1, x1, y0);
  46.         return;
  47.     }
  48.     BasicWadSeek( dir->wadfile, dir->dir.start);
  49.     
  50. #if defined(__TURBOC__)
  51.     
  52.     pixels = (unsigned char huge*) GetFarMemory( 4100 * sizeof( char));
  53.     BasicWadRead( dir->wadfile, &(pixels[ 4]), 4096L);
  54.     if (GfxMode < -1) {
  55.         /* Probably a bug in the VESA driver...    */
  56.         /* It requires "size-1" instead of "size"! */
  57.         ((UBCINT huge *)pixels)[ 0] = 63;
  58.         ((UBCINT huge *)pixels)[ 1] = 63;
  59.     }
  60.     else {
  61.         ((UBCINT huge *)pixels)[ 0] = 64;
  62.         ((UBCINT huge *)pixels)[ 1] = 64;
  63.     }
  64.     
  65. #elif defined(__GNUC__)
  66.     
  67.     /* bcc2grx's getimage-bitmap has a lot more info in it's header
  68.        than borland's */
  69.     
  70.     pixels = (unsigned char*) GetFarMemory( 4096+sizeof(GrContext));
  71.     getimage( x0, y0, x0+63, y0+63, pixels);   /* Hack! */
  72.     BasicWadRead( dir->wadfile, pixels+sizeof(GrContext), 4096L);
  73.     
  74. #endif
  75.     
  76.     putimage( x0, y0, pixels, COPY_PUT);
  77.     FreeFarMemory( pixels);
  78. }
  79.  
  80. /*
  81.    display a picture "picname" at coords x0, y0 and not beyond x1, y1
  82.    */
  83.  
  84.  
  85. /* SO 2/4/95:
  86.    DisplayPic now uses GetResource to get the sprite/patch to display.
  87.    It checks the variable ForgetAfter to see whether it should
  88.    call ForgetResource after displaying; this should be set by
  89.    the caller.
  90.    ChooseSprite sets this to TRUE; DisplayWallTexture sets it to FALSE.
  91.    DisplayWallTexture then takes the responsibility for calling
  92.    ForgetResource for all the patches in the texture being displayed.
  93.    This enables us to buffer all the patches in case they are used
  94.    more than once in a texture (e.g. LITE5 in Doom (extreme case!)) */
  95.  
  96. void DisplayPic( BCINT x0, BCINT y0, BCINT x1, BCINT y1, char *picname)
  97. {    
  98.     PHeader *h;
  99.     PColumn **columns, *c;
  100.     BCINT x, y;
  101.     BYTE *pixels;
  102.     long p_resource;
  103.  
  104.     if(bioskey(1))
  105.         return;
  106.  
  107.     p_resource = (long)GetResource(picname);
  108.     if(!p_resource)
  109.         return;
  110.     
  111.     h = (PHeader *)p_resource;
  112.     columns = (PColumn **)(p_resource + sizeof(PHeader));
  113.     
  114.     for(x = 0; x < h->width; x++) {
  115.         if(x > (x1 - x0))
  116.             continue;
  117.         
  118.         c = (PColumn *)((long)columns[x] + p_resource);
  119.         while(c->yofs != 255) {
  120.             pixels = (BYTE *)((long)c + (long)sizeof(PColumn) +
  121.                               (long)c->npixels + 1L);
  122.  
  123.             for(y = c->npixels; y >= 0; y--) {
  124.                 if((y + c->yofs) > (y1 - y0))
  125.                     pixels--;
  126.                 else
  127.                     putpixel(x + x0, y + y0 + c->yofs, *pixels--);
  128.             }
  129.             c = (PColumn *)((long)c + (long)(c->npixels) + 4L);
  130.         } 
  131.     }
  132.  
  133.     if(ForgetAfter)
  134.         ForgetResource(picname);
  135. }
  136.  
  137. void *GetResource(char *name)
  138. {
  139.     void *t = NULL;
  140.     resource *p, *new = (resource *)NULL;
  141.     MDirPtr r;
  142.  
  143.     for(p = ResourceList; p; p = p->next)
  144.         if(!strcmp(name, p->name))
  145.             return p->data;
  146.     
  147.     r = FindMasterDir(MasterDir, name);
  148.     if(r && (t = GetMemory(r->dir.size))) {
  149.         BasicWadSeek(r->wadfile, r->dir.start);
  150.         BasicWadRead(r->wadfile, t, r->dir.size);
  151.  
  152.         new = (resource *)GetMemory(sizeof(resource));
  153.         assert(new);
  154.         new->data = t;
  155.         new->name = strdup(name);
  156.         new->next = ResourceList;
  157.         ResourceList = new;
  158.         return t;
  159.     }
  160.     return NULL;
  161. }
  162.  
  163. void ForgetResource(char *name)
  164. {
  165.     resource *p, *q = NULL;
  166.  
  167.     for(p = ResourceList; p->next; q = p, p = p->next) {
  168.         if(!strcmp(p->name, name)) {
  169.             if(p == ResourceList)
  170.                 ResourceList = p->next;
  171.             else
  172.                 q->next = p->next;
  173.             
  174.             FreeMemory(p->data);
  175.             FreeMemory(p->name);
  176.             FreeMemory(p);
  177.  
  178.             return;
  179.         }
  180.     }
  181. }
  182.  
  183. void ForgetAllResources()
  184. {
  185.     resource *p, *q;
  186.     for(p = ResourceList; p; p = q) {
  187.         q = p->next;
  188.         FreeMemory(p->data);
  189.         FreeMemory(p->name);
  190.         FreeMemory(p);
  191.     }
  192. }
  193.  
  194.  
  195. Texture *FindTexture(char *name)
  196. {
  197.     Texture *t;
  198.     SList p;
  199.  
  200.     for(p = Texture_sections; p; p = p->next) {
  201.         t = FindTextureIn(name, GetResource(p->string));
  202.         if(t)
  203.             return t;
  204.     }
  205.     return NULL;
  206. }
  207.  
  208. Texture *FindTextureIn(char *name, void *tblock)
  209. {
  210.     long i, *offsets = tblock;
  211.     Texture *t;
  212.  
  213.     if(tblock)
  214.         for(i = 1; i <= offsets[0]; i++) {
  215.             t = (Texture *)((long)offsets[i] + (long)tblock);
  216.             if(!strncmp(t->name, name, 8))
  217.                 return t;
  218.         }
  219.  
  220.     return NULL;
  221. }
  222.  
  223. /*
  224.    display a wall texture at coords x0, y0
  225.    */
  226.  
  227. void DisplayWallTexture( BCINT x0, BCINT y0, BCINT x1, BCINT y1, char *texname) {
  228.     BCINT    n, xsize, ysize;
  229.     Texture  *tinfo;
  230.     PatchDesc *pinfo;
  231.     char     picname[9];
  232.     long patchname;
  233.     void *Pnames;
  234.     
  235.     if (bioskey( 1) != 0)
  236.         return; /* speedup */
  237.  
  238.     Pnames = GetResource("PNAMES");
  239.  
  240.     /* clear the box where the texture size will be drawn - see below */
  241.     SetColor(DARKGRAY);
  242.     DrawScreenBox( x0 - 171, y0 + 40, x0 - 82, y0 + 70);
  243.  
  244.     if (!(tinfo = FindTexture(texname)))
  245.         return;
  246.  
  247.     /* read the info for this texture */
  248.         xsize = tinfo->width;
  249.         ysize = tinfo->height;
  250.     
  251.     SetColor( BLACK);
  252.     DrawScreenText( x0 - 171, y0 + 40, "%dx%d", xsize, ysize);
  253.     
  254.     if (tinfo->nPatches == 1)
  255.         DrawScreenText( x0 - 171, y0 + 60, "Transparent");
  256.     else
  257.         DrawScreenText( x0 - 171, y0 + 60, "%d Patches", tinfo->nPatches);
  258.  
  259.     if (bioskey( 1) != 0)
  260.         return; /* speedup */
  261.     
  262.     if (x1 - x0 > xsize)
  263.         x1 = x0 + xsize;
  264.     if (y1 - y0 > ysize)
  265.         y1 = y0 + ysize;
  266.  
  267.     /* not really necessary, except when xofs or yofs < 0 */
  268.     setviewport( x0, y0, x1, y1, TRUE);
  269.  
  270.     /* display the texture */
  271.     pinfo = (PatchDesc *)((long)tinfo + sizeof(Texture));
  272.     ForgetAfter = FALSE;
  273.     for (n = 0; n < tinfo->nPatches; n++, pinfo++) {
  274.  
  275.         /* OK, now look up the pic's name in Pnames. */
  276.         patchname = (long)Pnames + 4L + ((long)(pinfo->PatchNumber) * 8);
  277.  
  278.         strncpy(picname, (char *)patchname, 8);
  279.         picname[ 8] = '\0';
  280.         /* coords changed because of the "setviewport" */
  281.         DisplayPic( pinfo->xOffset, pinfo->yOffset,
  282.                     x1 - x0, y1 - y0, strupr( picname));
  283.     }
  284.     
  285.     /* de-allocate all patches */
  286.     pinfo = (PatchDesc *)((long)tinfo + sizeof(Texture));
  287.     for (n = 0; n < tinfo->nPatches; n++, pinfo++) {
  288.         patchname = (long)Pnames + 4L + ((long)(pinfo->PatchNumber) * 8);
  289.         strncpy(picname, (char *)patchname, 8);
  290.         picname[ 8] = '\0';
  291.         ForgetResource(picname);
  292.     }
  293.     /* restore the normal viewport */
  294.     setviewport( 0, 0, ScrMaxX, ScrMaxY, TRUE);
  295. }
  296.  
  297.  
  298.  
  299. /*
  300.    Function to get the size of a wall texture
  301.    It's a lot smaller now that we have functions to get a pointer
  302.    to the texture structure automagically :-)
  303.    */
  304.  
  305. void GetWallTextureSize( BCINT *xsize_r, BCINT *ysize_r, char *texname)
  306. {
  307.     Texture *t = FindTexture(texname);
  308.  
  309.     if(t) {
  310.         *xsize_r = t->width;
  311.         *ysize_r = t->height;
  312.     }
  313.     else {
  314.         /* texture data not found */
  315.         *xsize_r = -1;
  316.         *ysize_r = -1;
  317.     }
  318. }
  319.  
  320.  
  321.  
  322.  
  323. /*
  324.    choose a floor or ceiling texture
  325.    */
  326.  
  327. void ChooseFloorTexture( BCINT x0, BCINT y0, char *prompt, BCINT listsize, char **list, char *name)
  328. {
  329.     if (UseMouse)
  330.         HideMousePointer(); 
  331.     SwitchToVGA256();
  332.     /* if we only have a 320x200x256 VGA driver, we must change x0 and y0.  Yuck! */
  333.     if (GfxMode > -2) {
  334.         x0 = -1;
  335.         y0 = -1;
  336.     }
  337.     InputNameFromListWithFunc( x0, y0, prompt, listsize, list, 5, name, 64, 64, DisplayFloorTexture);
  338.     SwitchToVGA16();
  339.     if (UseMouse)
  340.         ShowMousePointer();
  341. }
  342.  
  343.  
  344.  
  345. /*
  346.    choose a wall texture
  347.    */
  348.  
  349. void ChooseWallTexture( BCINT x0, BCINT y0, char *prompt, BCINT listsize, char **list, char *name)
  350. {
  351.     if (UseMouse)
  352.         HideMousePointer();
  353.     SwitchToVGA256();
  354.     /* if we only have a 320x200x256 VGA driver, we must change x0 and y0.  Yuck! */
  355.     if (GfxMode > -2) {
  356.         x0 = 0;
  357.         y0 = -1;
  358.     }
  359.     InputNameFromListWithFunc( x0, y0, prompt, listsize, list, 11, name, 256, 128, DisplayWallTexture);
  360.     SwitchToVGA16();
  361.     if (UseMouse)
  362.         ShowMousePointer();
  363. }
  364.  
  365.  
  366.  
  367. /*
  368.    function used by qsort to sort the sprite names
  369.    */
  370. int SortSprites( const void *a, const void *b)
  371. {
  372.     return strcmp( *((char **)a), *((char **)b));
  373. }
  374.  
  375.  
  376.  
  377. /*
  378.    choose a "sprite"
  379.    */
  380.  
  381. void ChooseSprite( BCINT x0, BCINT y0, char *prompt, char *sname)
  382. {
  383.     MDirPtr dir;
  384.     BCINT n, listsize;
  385.     char **list;
  386.     char name[ 9];
  387.     
  388.     /* count the names */
  389.     dir = FindMasterDir( MasterDir, "S_START");
  390.     dir = dir->next;
  391.     for (n = 0; dir && strcmp(dir->dir.name, "S_END"); n++)
  392.         dir = dir->next;
  393.     listsize = n;
  394.     /* get the actual names from master dir. */
  395.     dir = FindMasterDir( MasterDir, "S_START");
  396.     dir = dir->next;
  397.     list = (char**) GetMemory( listsize * sizeof( char *));
  398.     for (n = 0; n < listsize; n++) {
  399.         list[ n] = (char*) GetMemory( 9 * sizeof( char));
  400.         strncpy( list[ n], dir->dir.name, 8);
  401.         list[ n][ 8] = '\0';
  402.         dir = dir->next;
  403.     }
  404.     qsort( list, listsize, sizeof( char *), SortSprites);
  405.     if (sname != NULL)
  406.         strncpy( name, sname, 8);
  407.     else
  408.         strcpy( name, list[ 0]);
  409.     /*   if (UseMouse)
  410.          HideMousePointer(); */
  411.     SwitchToVGA256();
  412.     /* if we only have a 320x200x256 VGA driver, we must change x0 and y0.  Yuck! */
  413.     if (GfxMode > -2) {
  414.         x0 = 0;
  415.         y0 = -1;
  416.     }
  417.     ForgetAfter = TRUE;
  418.     InputNameFromListWithFunc( x0, y0, prompt, listsize, list, 11, name, 256, 128, DisplayPic);
  419.     /*   SwitchToVGA16();
  420.          if (UseMouse)
  421.          ShowMousePointer(); */
  422.     for (n = 0; n < listsize; n++)
  423.         FreeMemory( list[ n]);
  424.     FreeMemory( list);
  425. }
  426.