1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
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
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
24 // Preparation of data for rendering,
25 // generation of lookups, caching, retrieval by name.
27 //-----------------------------------------------------------------------------
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.
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.
86 // Texture definition.
87 // A DOOM wall texture is a list of patches
88 // which are to be combined in a predefined order.
96 void **columndirectory
; // OBSOLETE
98 mappatch_t patches
[1];
102 // A single patch from a texture definition,
103 // basically a rectangular area within
104 // the texture rectangle.
107 // Block origin (allways UL),
108 // which has allready accounted
109 // for the internal origin of the patch.
116 // A maptexturedef_t describes a rectangular texture,
117 // which is composed of one or more mappatch_t structures
118 // that arrange graphic patches.
121 // Keep name for switch changing, etc.
126 // All the patches[patchcount]
127 // are drawn back to front into the cached texture.
129 texpatch_t patches
[1];
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.
202 dest
= (byte
*)cache
+ 3;
204 while (patch
->topdelta
!= 0xff)
206 source
= (byte
*)patch
+ 3;
207 count
= patch
->length
;
208 position
= originy
+ patch
->topdelta
;
216 if (position
+ count
> cacheheight
)
217 count
= cacheheight
- position
;
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
)
246 unsigned short* colofs
;
248 texture
= textures
[texnum
];
250 block
= Z_Malloc (texturecompositesize
[texnum
],
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
;
264 realpatch
= W_CacheLumpNum (patch
->patch
, PU_CACHE
);
266 x2
= x1
+ SWAPSHORT(realpatch
->width
);
273 if (x2
> texture
->width
)
278 // Column does not have multiple patches?
282 patchcol
= (column_t
*)((byte
*)realpatch
283 + SWAPLONG(realpatch
->columnofs
[x
-x1
]));
284 R_DrawColumnInCache (patchcol
,
292 // Now that the texture has been built in column cache,
293 // it is purgable from zone memory.
294 Z_ChangeTag (block
, PU_CACHE
);
302 void R_GenerateLookup (int texnum
)
305 byte
* patchcount
= NULL
; // patchcount[texture->width]
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
;
337 realpatch
= W_CacheLumpNum (patch
->patch
, PU_CACHE
);
339 x2
= x1
+ SWAPSHORT(realpatch
->width
);
346 if (x2
> texture
->width
)
351 collump
[x
] = patch
->patch
;
352 colofs
[x
] = SWAPLONG(realpatch
->columnofs
[x
-x1
])+3;
356 for (x
=0 ; x
<texture
->width
; x
++)
360 printf ("R_GenerateLookup: column without a patch (%s)\n",
364 // I_Error ("R_GenerateLookup: column without a patch");
366 if (patchcount
[x
] > 1)
368 // Use the cached block.
370 colofs
[x
] = texturecompositesize
[texnum
];
372 if (texturecompositesize
[texnum
] > 0x10000-texture
->height
)
374 I_Error ("R_GenerateLookup: texture %i is >64k",
378 texturecompositesize
[texnum
] += texture
->height
;
381 if (patchcount
!= NULL
)
398 col
&= texturewidthmask
[tex
];
399 lump
= texturecolumnlump
[tex
][col
];
400 ofs
= texturecolumnofs
[tex
][col
];
403 return (byte
*)W_CacheLumpNum(lump
,PU_CACHE
)+ofs
;
405 if (!texturecomposite
[tex
])
406 R_GenerateComposite (tex
);
408 return texturecomposite
[tex
] + ofs
;
416 // Initializes the texture list
417 // with the textures from the world map.
419 void R_InitTextures (void)
421 maptexture_t
* mtexture
;
437 int* patchlookup
= NULL
;
454 // Load the patch names from pnames.lmp.
456 names
= W_CacheLumpName ("PNAMES", PU_STATIC
);
457 nummappatches
= SWAPLONG( *((int *)names
) );
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
);
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"));
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);
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);
506 for (i
= 0; i
< temp3
; i
++)
509 for (i
= 0; i
< temp3
; i
++)
513 for (i
=0 ; i
<numtextures
; i
++, directory
++)
518 if (i
== numtextures1
)
520 // Start looking in second texture file.
523 directory
= maptex
+1;
526 offset
= SWAPLONG(*directory
);
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),
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",
557 texturecolumnlump
[i
] = Z_Malloc (texture
->width
*2, PU_STATIC
,0);
558 texturecolumnofs
[i
] = Z_Malloc (texture
->width
*2, PU_STATIC
,0);
561 while (j
*2 <= texture
->width
)
564 texturewidthmask
[i
] = j
-1;
565 textureheight
[i
] = texture
->height
<<FRACBITS
;
567 totalwidth
+= texture
->width
;
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
)
593 void R_InitFlats (void)
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
;
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)
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
++)
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
;
645 void R_InitColormaps (void)
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
);
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)
669 // printf ("\nInitTextures");
671 // printf ("\nInitFlats");
672 R_InitSpriteLumps ();
673 // printf ("\nInitSprites");
675 // printf ("\nInitColormaps");
682 // Retrieval, get a flat number for a flat name.
684 int R_FlatNumForName (char* name
)
689 i
= W_CheckNumForName (name
);
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
)
713 // "NoTexture" marker.
717 for (i
=0 ; i
<numtextures
; i
++)
718 if (!strncasecmp (textures
[i
]->name
, name
, 8) )
727 // R_TextureNumForName
728 // Calls R_CheckTextureNumForName,
729 // aborts with error message.
731 int R_TextureNumForName (char* name
)
735 i
= R_CheckTextureNumForName (name
);
739 I_Error ("R_TextureNumForName: %s not found",
750 // Preloads all relevant graphics for the level.
756 void R_PrecacheLevel (void)
758 char* flatpresent
= NULL
;
759 char* texturepresent
= NULL
;
760 char* spritepresent
= NULL
;
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;
787 for (i
=0 ; i
<numflats
; 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
815 texturepresent
[skytexture
] = 1;
818 for (i
=0 ; i
<numtextures
; i
++)
820 if (!texturepresent
[i
])
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
);
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;
845 for (i
=0 ; i
<numsprites
; i
++)
847 if (!spritepresent
[i
])
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
)
863 if (texturepresent
!= NULL
)
864 free (texturepresent
);
865 if (spritepresent
!= NULL
)
866 free (spritepresent
);