# Correct the needed linklibs in curl-config also.
[AROS-Contrib.git] / Games / Doom / r_data.c
blob0245d7bd73e0c1ef4a88d4392570e537b4df4ed4
1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
17 // $Log$
18 // Revision 1.1 2000/02/29 18:21:05 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
22 // Revision 1.3 1997/01/29 20:10
23 // DESCRIPTION:
24 // Preparation of data for rendering,
25 // generation of lookups, caching, retrieval by name.
27 //-----------------------------------------------------------------------------
30 static const char
31 rcsid[] = "$Id$";
33 #include "i_system.h"
34 #include "z_zone.h"
36 #include "m_swap.h"
38 #include "w_wad.h"
40 #include "doomdef.h"
41 #include "r_local.h"
42 #include "p_local.h"
44 #include "doomstat.h"
45 #include "r_sky.h"
47 #ifdef LINUX
48 #include <alloca.h>
49 #endif
51 #ifdef __SASC
52 #include <stdlib.h>
53 #endif
55 #include "r_data.h"
58 // Graphics.
59 // DOOM graphics for walls and sprites
60 // is stored in vertical runs of opaque pixels (posts).
61 // A column is composed of zero or more posts,
62 // a patch or sprite is composed of zero or more columns.
63 //
68 // Texture definition.
69 // Each texture is composed of one or more patches,
70 // with patches being lumps stored in the WAD.
71 // The lumps are referenced by number, and patched
72 // into the rectangular texture space using origin
73 // and possibly other attributes.
75 typedef struct
77 short originx;
78 short originy;
79 short patch;
80 short stepdir;
81 short colormap;
82 } mappatch_t;
86 // Texture definition.
87 // A DOOM wall texture is a list of patches
88 // which are to be combined in a predefined order.
90 typedef struct
92 char name[8];
93 boolean masked;
94 short width;
95 short height;
96 void **columndirectory; // OBSOLETE
97 short patchcount;
98 mappatch_t patches[1];
99 } maptexture_t;
102 // A single patch from a texture definition,
103 // basically a rectangular area within
104 // the texture rectangle.
105 typedef struct
107 // Block origin (allways UL),
108 // which has allready accounted
109 // for the internal origin of the patch.
110 int originx;
111 int originy;
112 int patch;
113 } texpatch_t;
116 // A maptexturedef_t describes a rectangular texture,
117 // which is composed of one or more mappatch_t structures
118 // that arrange graphic patches.
119 typedef struct
121 // Keep name for switch changing, etc.
122 char name[8];
123 short width;
124 short height;
126 // All the patches[patchcount]
127 // are drawn back to front into the cached texture.
128 short patchcount;
129 texpatch_t patches[1];
131 } texture_t;
135 int firstflat;
136 int lastflat;
137 int numflats;
139 int firstpatch;
140 int lastpatch;
141 int numpatches;
143 int firstspritelump;
144 int lastspritelump;
145 int numspritelumps;
147 int numtextures;
148 texture_t** textures;
151 int* texturewidthmask;
152 // needed for texture pegging
153 fixed_t* textureheight;
154 int* texturecompositesize;
155 short** texturecolumnlump;
156 unsigned short** texturecolumnofs;
157 byte** texturecomposite;
159 // for global animation
160 int* flattranslation;
161 int* texturetranslation;
163 // needed for pre rendering
164 fixed_t* spritewidth;
165 fixed_t* spriteoffset;
166 fixed_t* spritetopoffset;
168 lighttable_t *colormaps;
172 // MAPTEXTURE_T CACHING
173 // When a texture is first needed,
174 // it counts the number of composite columns
175 // required in the texture and allocates space
176 // for a column directory and any new columns.
177 // The directory will simply point inside other patches
178 // if there is only one patch in a given column,
179 // but any columns with multiple patches
180 // will have new column_ts generated.
186 // R_DrawColumnInCache
187 // Clip and draw a column
188 // from a patch into a cached post.
190 void
191 R_DrawColumnInCache
192 ( column_t* patch,
193 byte* cache,
194 int originy,
195 int cacheheight )
197 int count;
198 int position;
199 byte* source;
200 byte* dest;
202 dest = (byte *)cache + 3;
204 while (patch->topdelta != 0xff)
206 source = (byte *)patch + 3;
207 count = patch->length;
208 position = originy + patch->topdelta;
210 if (position < 0)
212 count += position;
213 position = 0;
216 if (position + count > cacheheight)
217 count = cacheheight - position;
219 if (count > 0)
220 memcpy (cache + position, source, count);
222 patch = (column_t *)( (byte *)patch + patch->length + 4);
229 // R_GenerateComposite
230 // Using the texture definition,
231 // the composite texture is created from the patches,
232 // and each column is cached.
234 void R_GenerateComposite (int texnum)
236 byte* block;
237 texture_t* texture;
238 texpatch_t* patch;
239 patch_t* realpatch;
240 int x;
241 int x1;
242 int x2;
243 int i;
244 column_t* patchcol;
245 short* collump;
246 unsigned short* colofs;
248 texture = textures[texnum];
250 block = Z_Malloc (texturecompositesize[texnum],
251 PU_STATIC,
252 &texturecomposite[texnum]);
254 collump = texturecolumnlump[texnum];
255 colofs = texturecolumnofs[texnum];
257 // Composite the columns together.
258 patch = texture->patches;
260 for (i=0 , patch = texture->patches;
261 i<texture->patchcount;
262 i++, patch++)
264 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
265 x1 = patch->originx;
266 x2 = x1 + SWAPSHORT(realpatch->width);
268 if (x1<0)
269 x = 0;
270 else
271 x = x1;
273 if (x2 > texture->width)
274 x2 = texture->width;
276 for ( ; x<x2 ; x++)
278 // Column does not have multiple patches?
279 if (collump[x] >= 0)
280 continue;
282 patchcol = (column_t *)((byte *)realpatch
283 + SWAPLONG(realpatch->columnofs[x-x1]));
284 R_DrawColumnInCache (patchcol,
285 block + colofs[x],
286 patch->originy,
287 texture->height);
292 // Now that the texture has been built in column cache,
293 // it is purgable from zone memory.
294 Z_ChangeTag (block, PU_CACHE);
300 // R_GenerateLookup
302 void R_GenerateLookup (int texnum)
304 texture_t* texture;
305 byte* patchcount = NULL; // patchcount[texture->width]
306 texpatch_t* patch;
307 patch_t* realpatch;
308 int x;
309 int x1;
310 int x2;
311 int i;
312 short* collump;
313 unsigned short* colofs;
315 texture = textures[texnum];
317 // Composited texture not created yet.
318 texturecomposite[texnum] = 0;
320 texturecompositesize[texnum] = 0;
321 collump = texturecolumnlump[texnum];
322 colofs = texturecolumnofs[texnum];
324 // Now count the number of columns
325 // that are covered by more than one patch.
326 // Fill in the lump / offset, so columns
327 // with only a single patch are all done.
328 if ((patchcount = (byte *)malloc (texture->width)) == NULL)
329 I_Error ("malloc(%d) failed", texture->width);
330 memset (patchcount, 0, texture->width);
331 patch = texture->patches;
333 for (i=0 , patch = texture->patches;
334 i<texture->patchcount;
335 i++, patch++)
337 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
338 x1 = patch->originx;
339 x2 = x1 + SWAPSHORT(realpatch->width);
341 if (x1 < 0)
342 x = 0;
343 else
344 x = x1;
346 if (x2 > texture->width)
347 x2 = texture->width;
348 for ( ; x<x2 ; x++)
350 patchcount[x]++;
351 collump[x] = patch->patch;
352 colofs[x] = SWAPLONG(realpatch->columnofs[x-x1])+3;
356 for (x=0 ; x<texture->width ; x++)
358 if (!patchcount[x])
360 printf ("R_GenerateLookup: column without a patch (%s)\n",
361 texture->name);
362 return;
364 // I_Error ("R_GenerateLookup: column without a patch");
366 if (patchcount[x] > 1)
368 // Use the cached block.
369 collump[x] = -1;
370 colofs[x] = texturecompositesize[texnum];
372 if (texturecompositesize[texnum] > 0x10000-texture->height)
374 I_Error ("R_GenerateLookup: texture %i is >64k",
375 texnum);
378 texturecompositesize[texnum] += texture->height;
381 if (patchcount != NULL)
382 free (patchcount);
388 // R_GetColumn
390 byte*
391 R_GetColumn
392 ( int tex,
393 int col )
395 int lump;
396 int ofs;
398 col &= texturewidthmask[tex];
399 lump = texturecolumnlump[tex][col];
400 ofs = texturecolumnofs[tex][col];
402 if (lump > 0)
403 return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
405 if (!texturecomposite[tex])
406 R_GenerateComposite (tex);
408 return texturecomposite[tex] + ofs;
415 // R_InitTextures
416 // Initializes the texture list
417 // with the textures from the world map.
419 void R_InitTextures (void)
421 maptexture_t* mtexture;
422 texture_t* texture;
423 mappatch_t* mpatch;
424 texpatch_t* patch;
426 int i;
427 int j;
429 int* maptex;
430 int* maptex2;
431 int* maptex1;
433 char name[9];
434 char* names;
435 char* name_p;
437 int* patchlookup = NULL;
439 int totalwidth;
440 int nummappatches;
441 int offset;
442 int maxoff;
443 int maxoff2;
444 int numtextures1;
445 int numtextures2;
447 int* directory;
449 int temp1;
450 int temp2;
451 int temp3;
454 // Load the patch names from pnames.lmp.
455 name[8] = 0;
456 names = W_CacheLumpName ("PNAMES", PU_STATIC);
457 nummappatches = SWAPLONG( *((int *)names) );
458 name_p = names+4;
459 if ((patchlookup = malloc (nummappatches*sizeof(*patchlookup))) == NULL)
460 I_Error ("malloc(%d) failed", nummappatches*sizeof(*patchlookup));
462 for (i=0 ; i<nummappatches ; i++)
464 strncpy (name,name_p+i*8, 8);
465 patchlookup[i] = W_CheckNumForName (name);
467 Z_Free (names);
469 // Load the map texture definitions from textures.lmp.
470 // The data is contained in one or two lumps,
471 // TEXTURE1 for shareware, plus TEXTURE2 for commercial.
472 maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
473 numtextures1 = SWAPLONG(*maptex);
474 maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
475 directory = maptex+1;
477 if (W_CheckNumForName ("TEXTURE2") != -1)
479 maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
480 numtextures2 = SWAPLONG(*maptex2);
481 maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
483 else
485 maptex2 = NULL;
486 numtextures2 = 0;
487 maxoff2 = 0;
489 numtextures = numtextures1 + numtextures2;
491 textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
492 texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
493 texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
494 texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
495 texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
496 texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
497 textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
499 totalwidth = 0;
501 // Really complex printing shit...
502 temp1 = W_GetNumForName ("S_START"); // P_???????
503 temp2 = W_GetNumForName ("S_END") - 1;
504 temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
505 printf("[");
506 for (i = 0; i < temp3; i++)
507 printf(" ");
508 printf("]");
509 for (i = 0; i < temp3; i++)
510 printf("\x8");
511 printf("\x8");
513 for (i=0 ; i<numtextures ; i++, directory++)
515 if (!(i&63))
516 printf (".");
518 if (i == numtextures1)
520 // Start looking in second texture file.
521 maptex = maptex2;
522 maxoff = maxoff2;
523 directory = maptex+1;
526 offset = SWAPLONG(*directory);
528 if (offset > maxoff)
529 I_Error ("R_InitTextures: bad texture directory");
531 mtexture = (maptexture_t *) ( (byte *)maptex + offset);
533 texture = textures[i] =
534 Z_Malloc (sizeof(texture_t)
535 + sizeof(texpatch_t)*(SWAPSHORT(mtexture->patchcount)-1),
536 PU_STATIC, 0);
538 texture->width = SWAPSHORT(mtexture->width);
539 texture->height = SWAPSHORT(mtexture->height);
540 texture->patchcount = SWAPSHORT(mtexture->patchcount);
542 memcpy (texture->name, mtexture->name, sizeof(texture->name));
543 mpatch = &mtexture->patches[0];
544 patch = &texture->patches[0];
546 for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
548 patch->originx = SWAPSHORT(mpatch->originx);
549 patch->originy = SWAPSHORT(mpatch->originy);
550 patch->patch = patchlookup[SWAPSHORT(mpatch->patch)];
551 if (patch->patch == -1)
553 I_Error ("R_InitTextures: Missing patch in texture %s",
554 texture->name);
557 texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
558 texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
560 j = 1;
561 while (j*2 <= texture->width)
562 j<<=1;
564 texturewidthmask[i] = j-1;
565 textureheight[i] = texture->height<<FRACBITS;
567 totalwidth += texture->width;
570 Z_Free (maptex1);
571 if (maptex2)
572 Z_Free (maptex2);
574 // Precalculate whatever possible.
575 for (i=0 ; i<numtextures ; i++)
576 R_GenerateLookup (i);
578 // Create translation table for global animation.
579 texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
581 for (i=0 ; i<numtextures ; i++)
582 texturetranslation[i] = i;
584 if (patchlookup != NULL)
585 free (patchlookup);
591 // R_InitFlats
593 void R_InitFlats (void)
595 int i;
597 firstflat = W_GetNumForName ("F_START") + 1;
598 lastflat = W_GetNumForName ("F_END") - 1;
599 numflats = lastflat - firstflat + 1;
601 // Create translation table for global animation.
602 flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
604 for (i=0 ; i<numflats ; i++)
605 flattranslation[i] = i;
610 // R_InitSpriteLumps
611 // Finds the width and hoffset of all sprites in the wad,
612 // so the sprite does not need to be cached completely
613 // just for having the header info ready during rendering.
615 void R_InitSpriteLumps (void)
617 int i;
618 patch_t *patch;
620 firstspritelump = W_GetNumForName ("S_START") + 1;
621 lastspritelump = W_GetNumForName ("S_END") - 1;
623 numspritelumps = lastspritelump - firstspritelump + 1;
624 spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
625 spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
626 spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
628 for (i=0 ; i< numspritelumps ; i++)
630 if (!(i&63))
631 printf (".");
633 patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
634 spritewidth[i] = SWAPSHORT(patch->width)<<FRACBITS;
635 spriteoffset[i] = SWAPSHORT(patch->leftoffset)<<FRACBITS;
636 spritetopoffset[i] = SWAPSHORT(patch->topoffset)<<FRACBITS;
643 // R_InitColormaps
645 void R_InitColormaps (void)
647 int lump, length;
649 // Load in the light tables,
650 // 256 byte align tables.
651 lump = W_GetNumForName("COLORMAP");
652 length = W_LumpLength (lump) + 255;
653 colormaps = Z_Malloc (length, PU_STATIC, 0);
654 colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
655 W_ReadLump (lump,colormaps);
661 // R_InitData
662 // Locates all the lumps
663 // that will be used by all views
664 // Must be called after W_Init.
666 void R_InitData (void)
668 R_InitTextures ();
669 // printf ("\nInitTextures");
670 R_InitFlats ();
671 // printf ("\nInitFlats");
672 R_InitSpriteLumps ();
673 // printf ("\nInitSprites");
674 R_InitColormaps ();
675 // printf ("\nInitColormaps");
681 // R_FlatNumForName
682 // Retrieval, get a flat number for a flat name.
684 int R_FlatNumForName (char* name)
686 int i;
687 char namet[9];
689 i = W_CheckNumForName (name);
691 if (i == -1)
693 namet[8] = 0;
694 memcpy (namet, name,8);
695 I_Error ("R_FlatNumForName: %s not found",namet);
698 return i - firstflat;
705 // R_CheckTextureNumForName
706 // Check whether texture is available.
707 // Filter out NoTexture indicator.
709 int R_CheckTextureNumForName (char *name)
711 int i;
713 // "NoTexture" marker.
714 if (name[0] == '-')
715 return 0;
717 for (i=0 ; i<numtextures ; i++)
718 if (!strncasecmp (textures[i]->name, name, 8) )
719 return i;
721 return -1;
727 // R_TextureNumForName
728 // Calls R_CheckTextureNumForName,
729 // aborts with error message.
731 int R_TextureNumForName (char* name)
733 int i;
735 i = R_CheckTextureNumForName (name);
737 if (i==-1)
739 I_Error ("R_TextureNumForName: %s not found",
740 name);
742 return i;
749 // R_PrecacheLevel
750 // Preloads all relevant graphics for the level.
752 int flatmemory;
753 int texturememory;
754 int spritememory;
756 void R_PrecacheLevel (void)
758 char* flatpresent = NULL;
759 char* texturepresent = NULL;
760 char* spritepresent = NULL;
762 int i;
763 int j;
764 int k;
765 int lump;
767 texture_t* texture;
768 thinker_t* th;
769 spriteframe_t* sf;
771 if (demoplayback)
772 return;
774 // Precache flats.
775 if ((flatpresent = malloc(numflats)) == NULL)
776 I_Error ("malloc(%d) failed", numflats);
777 memset (flatpresent,0,numflats);
779 for (i=0 ; i<numsectors ; i++)
781 flatpresent[sectors[i].floorpic] = 1;
782 flatpresent[sectors[i].ceilingpic] = 1;
785 flatmemory = 0;
787 for (i=0 ; i<numflats ; i++)
789 if (flatpresent[i])
791 lump = firstflat + i;
792 flatmemory += lumpinfo[lump].size;
793 W_CacheLumpNum(lump, PU_CACHE);
797 // Precache textures.
798 if ((texturepresent = malloc(numtextures)) == NULL)
799 I_Error ("malloc(%d) failed", numtextures);
800 memset (texturepresent,0, numtextures);
802 for (i=0 ; i<numsides ; i++)
804 texturepresent[sides[i].toptexture] = 1;
805 texturepresent[sides[i].midtexture] = 1;
806 texturepresent[sides[i].bottomtexture] = 1;
809 // Sky texture is always present.
810 // Note that F_SKY1 is the name used to
811 // indicate a sky floor/ceiling as a flat,
812 // while the sky texture is stored like
813 // a wall texture, with an episode dependend
814 // name.
815 texturepresent[skytexture] = 1;
817 texturememory = 0;
818 for (i=0 ; i<numtextures ; i++)
820 if (!texturepresent[i])
821 continue;
823 texture = textures[i];
825 for (j=0 ; j<texture->patchcount ; j++)
827 lump = texture->patches[j].patch;
828 texturememory += lumpinfo[lump].size;
829 W_CacheLumpNum(lump , PU_CACHE);
833 // Precache sprites.
834 if ((spritepresent = malloc(numsprites)) == NULL)
835 I_Error ("malloc(%d) failed", numsprites);
836 memset (spritepresent,0, numsprites);
838 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
840 if (th->function.acp1 == (actionf_p1)P_MobjThinker)
841 spritepresent[((mobj_t *)th)->sprite] = 1;
844 spritememory = 0;
845 for (i=0 ; i<numsprites ; i++)
847 if (!spritepresent[i])
848 continue;
850 for (j=0 ; j<sprites[i].numframes ; j++)
852 sf = &sprites[i].spriteframes[j];
853 for (k=0 ; k<8 ; k++)
855 lump = firstspritelump + sf->lump[k];
856 spritememory += lumpinfo[lump].size;
857 W_CacheLumpNum(lump , PU_CACHE);
861 if (flatpresent != NULL)
862 free (flatpresent);
863 if (texturepresent != NULL)
864 free (texturepresent);
865 if (spritepresent != NULL)
866 free (spritepresent);