doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

r_data.c (11909B)


      1 #include  <stdlib.h>
      2 #include  <alloca.h>
      3 
      4 #include "m_swap.h"
      5 #include "i_system.h"
      6 #include "z_zone.h"
      7 #include "w_wad.h"
      8 #include "doomdef.h"
      9 #include "r_local.h"
     10 #include "p_local.h"
     11 #include "doomstat.h"
     12 #include "r_data.h"
     13 
     14 typedef struct {
     15 	short originx;
     16 	short originy;
     17 	short patch;
     18 	short stepdir;
     19 	short colormap;
     20 } mappatch_t;
     21 
     22 typedef struct {
     23 	char       name[8];
     24 	boolean    masked;
     25 	short      width;
     26 	short      height;
     27 	char       columndirectory[4]; /* obsolete btw */
     28 	short      patchcount;
     29 	mappatch_t patches[1];
     30 } maptexture_t;
     31 
     32 typedef struct {
     33 	int originx;
     34 	int originy;
     35 	int patch;
     36 } texpatch_t;
     37 
     38 typedef struct {
     39 	char	name[8];
     40 	short	width;
     41 	short	height;
     42 	short	patchcount;
     43 	texpatch_t	patches[1];
     44 } texture_t;
     45 
     46 int		firstflat;
     47 int		lastflat;
     48 int		numflats;
     49 int		firstpatch;
     50 int		lastpatch;
     51 int		numpatches;
     52 int		firstspritelump;
     53 int		lastspritelump;
     54 int		numspritelumps;
     55 int		numtextures;
     56 int		flatmemory;
     57 int		texturememory;
     58 int		spritememory;
     59 texture_t**      textures_g;
     60 int*             texturewidthmask_g;
     61 fixed_t*         textureheight_g;
     62 int*             texturecompositesize_g;
     63 short**          texturecolumnlump_g;
     64 unsigned short** texturecolumnofs_g;
     65 byte**			texturecomposite_g;
     66 int*		flattranslation;
     67 int*		texturetranslation;
     68 fixed_t*	spritewidth;
     69 fixed_t*	spriteoffset;
     70 fixed_t*	spritetopoffset;
     71 lighttable_t	*colormaps;
     72 
     73 void
     74 R_DrawColumnInCache(column_t* patch, byte* cache, int originy, int cacheheight)
     75 {
     76 	byte*	source;
     77 	int		count, position;
     78 
     79 	while (patch->topdelta != 0xff) {
     80 		source = (byte *)patch + 3;
     81 		count = patch->length;
     82 		position = originy + patch->topdelta;
     83 		if (position < 0) {
     84 			count += position;
     85 			position = 0;
     86 		}
     87 		if (position + count > cacheheight)
     88 			count = cacheheight - position;
     89 		if (count > 0)
     90 			memcpy (cache + position, source, count);
     91 		patch = (column_t *)(  (byte *)patch + patch->length + 4);
     92 	}
     93 }
     94 
     95 void
     96 R_GenerateComposite(int texnum)
     97 {
     98 	byte*           block;
     99 	texture_t*      texture;
    100 	texpatch_t*     patch;
    101 	patch_t*        realpatch;
    102 	column_t*       patchcol;
    103 	short*          collump;
    104 	unsigned short*	colofs;
    105 	int             x, x1, x2, i;
    106 
    107 	texture = textures_g[texnum];
    108 	block = Z_Malloc(texturecompositesize_g[texnum], PU_STATIC, &texturecomposite_g[texnum]);
    109 	collump = texturecolumnlump_g[texnum];
    110 	colofs = texturecolumnofs_g[texnum];
    111 	patch = texture->patches;
    112 	for (i = 0, patch = texture->patches; i < texture->patchcount; ++i, ++patch) {
    113 		realpatch = W_CacheLumpNum(patch->patch, PU_CACHE);
    114 		x1 = patch->originx;
    115 		x2 = x1 + realpatch->width;
    116 		if (x1 < 0)
    117 			x = 0;
    118 		else x = x1;
    119 		if (x2 > texture->width)
    120 			x2 = texture->width;
    121 		for (; x < x2; ++x) {
    122 			if (collump[x] >= 0)
    123 				continue;
    124 			patchcol = (column_t *)((byte *)realpatch + realpatch->columnofs[x-x1]);
    125 			R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy, texture->height);
    126 		}
    127 	}
    128 	Z_ChangeTag(block, PU_CACHE);
    129 }
    130 
    131 void
    132 R_GenerateLookup(int texnum)
    133 {
    134 	texture_t*      texture;
    135 	byte*           patchcount;
    136 	texpatch_t*     patch;
    137 	patch_t*        realpatch;
    138 	short*          collump;
    139 	unsigned short* colofs;
    140 	int             x, x1, x2, i;
    141 
    142 	texture = textures_g[texnum];
    143 	texturecomposite_g[texnum] = 0;
    144 	texturecompositesize_g[texnum] = 0;
    145 	collump = texturecolumnlump_g[texnum];
    146 	colofs = texturecolumnofs_g[texnum];
    147 	patchcount = (byte*)alloca(texture->width);
    148 	memset(patchcount, 0, texture->width);
    149 	patch = texture->patches;
    150 	for (i = 0, patch = texture->patches; i < texture->patchcount; ++i, ++patch) {
    151 		realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
    152 		x1 = patch->originx;
    153 		x2 = x1 + realpatch->width;
    154 		if (x1 < 0)
    155 			x = 0;
    156 		else x = x1;
    157 		if (x2 > texture->width)
    158 			x2 = texture->width;
    159 		for (; x < x2 ; ++x) {
    160 			++patchcount[x];
    161 			collump[x] = patch->patch;
    162 			colofs[x] = realpatch->columnofs[x-x1]+3;
    163 		}
    164 	}
    165 	for (x = 0; x < texture->width; ++x) {
    166 		if (!patchcount[x]) {
    167 			printf ("R_GenerateLookup: column without a patch (%s)\n", texture->name);
    168 			return;
    169 		}
    170 		if (patchcount[x] > 1) {
    171 			collump[x] = -1;
    172 			colofs[x] = texturecompositesize_g[texnum];
    173 			if (texturecompositesize_g[texnum] > 0x10000-texture->height)
    174 				I_Error ("R_GenerateLookup: texture %i is >64k", texnum);
    175 			texturecompositesize_g[texnum] += texture->height;
    176 		}
    177 	}
    178 }
    179 
    180 byte*
    181 R_GetColumn(int tex, int col)
    182 {
    183 	int lump, ofs;
    184 
    185 	col &= texturewidthmask_g[tex];
    186 	lump = texturecolumnlump_g[tex][col];
    187 	ofs = texturecolumnofs_g[tex][col];
    188 	if (lump > 0)
    189 		return (byte*)W_CacheLumpNum(lump,PU_CACHE)+ofs;
    190 	if (!texturecomposite_g[tex])
    191 		R_GenerateComposite (tex);
    192 	return texturecomposite_g[tex] + ofs;
    193 }
    194 
    195 void
    196 R_InitTextures()
    197 {
    198 	maptexture_t* mtexture;
    199 	texture_t*    texture;
    200 	mappatch_t*   mpatch;
    201 	texpatch_t*   patch;
    202 	int*          maptex, *maptex1, *maptex2, *patchlookup, *directory;
    203 	char*         names, *name_p;
    204 	char          name[9];
    205 	int           i, j, totalwidth, num_mappatches, offset, maxoff, maxoff2, numtextures1, numtextures2, temp1, temp2, temp3;
    206 
    207 	name[8] = 0;
    208 	names = W_CacheLumpName("PNAMES", PU_STATIC);
    209 	num_mappatches = *((int*)names);
    210 	name_p = names+4;
    211 	patchlookup = alloca(num_mappatches*sizeof(*patchlookup));
    212 	for (i = 0; i < num_mappatches; ++i) {
    213 		strncpy(name, name_p+i*8, 8);
    214 		patchlookup[i] = W_CheckNumForName(name);
    215 	}
    216 	Z_Free(names);
    217 	maptex = maptex1 = W_CacheLumpName("TEXTURE1", PU_STATIC);
    218 	numtextures1 = *maptex;
    219 	maxoff = W_LumpLength(W_GetNumForName ("TEXTURE1"));
    220 	directory = maptex+1;
    221 	if (W_CheckNumForName("TEXTURE2") == -1) {
    222 		maptex2 = NULL;
    223 		numtextures2 = 0;
    224 		maxoff2 = 0;
    225 	} else {
    226 		maptex2 = W_CacheLumpName("TEXTURE2", PU_STATIC);
    227 		numtextures2 = *maptex2;
    228 		maxoff2 = W_LumpLength(W_GetNumForName ("TEXTURE2"));
    229 	}
    230 	numtextures = numtextures1 + numtextures2;
    231 	textures_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    232 	texturecolumnlump_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    233 	texturecolumnofs_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    234 	texturecomposite_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    235 	texturecompositesize_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    236 	texturewidthmask_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    237 	textureheight_g = Z_Malloc(numtextures * sizeof(void*), PU_STATIC, 0);
    238 	totalwidth = 0;
    239 	temp1 = W_GetNumForName ("S_START");
    240 	temp2 = W_GetNumForName ("S_END") - 1;
    241 	temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
    242 	printf("[");
    243 	for (i = 0; i < temp3; ++i)
    244 		printf(" ");
    245 	printf("         ]");
    246 	for (i = 0; i < temp3; ++i)
    247 		printf("\x8");
    248 	printf("\x8\x8\x8\x8\x8\x8\x8\x8\x8\x8");
    249 	for (i = 0; i < numtextures; ++i, ++directory) {
    250 		if (!(i & 63))
    251 			printf(".");
    252 		if (i == numtextures1) {
    253 			maptex = maptex2;
    254 			maxoff = maxoff2;
    255 			directory = maptex+1;
    256 		}
    257 		offset = *directory;
    258 		if (offset > maxoff)
    259 			I_Error("R_InitTextures: bad texture directory");
    260 		mtexture = (maptexture_t*)((byte*)maptex + offset);
    261 		texture = textures_g[i] = Z_Malloc(sizeof(texture_t) + sizeof(texpatch_t)*(mtexture->patchcount-1), PU_STATIC, 0);
    262 		texture->width = mtexture->width;
    263 		texture->height = mtexture->height;
    264 		texture->patchcount = mtexture->patchcount;
    265 		memcpy(texture->name, mtexture->name, sizeof(texture->name));
    266 		mpatch = &mtexture->patches[0];
    267 		patch = &texture->patches[0];
    268 		for (j = 0; j < texture->patchcount; ++j, ++mpatch, ++patch) {
    269 			patch->originx = mpatch->originx;
    270 			patch->originy = mpatch->originy;
    271 			patch->patch = patchlookup[mpatch->patch];
    272 			if (patch->patch == -1)
    273 				I_Error("R_InitTextures: Missing patch in texture %s", texture->name);
    274 		}
    275 		texturecolumnlump_g[i] = Z_Malloc(texture->width * 2, PU_STATIC,0);
    276 		texturecolumnofs_g[i] = Z_Malloc(texture->width * 2, PU_STATIC,0);
    277 		for (j = 1; j * 2 <= texture->width; j <<= 1);
    278 		texturewidthmask_g[i] = j-1;
    279 		textureheight_g[i] = texture->height<<FRACBITS;
    280 		totalwidth += texture->width;
    281 	}
    282 	Z_Free(maptex1);
    283 	if (maptex2)
    284 		Z_Free(maptex2);
    285 	for (i = 0; i < numtextures; ++i)
    286 		R_GenerateLookup(i);
    287 	texturetranslation = Z_Malloc((numtextures+1) * 4, PU_STATIC, 0);
    288 	for (i = 0; i < numtextures; ++i)
    289 		texturetranslation[i] = i;
    290 }
    291 
    292 void
    293 R_InitFlats()
    294 {
    295 	int i;
    296 
    297 	firstflat = W_GetNumForName ("F_START") + 1;
    298 	lastflat = W_GetNumForName ("F_END") - 1;
    299 	numflats = lastflat - firstflat + 1;
    300 	flattranslation = Z_Malloc((numflats+1) * 4, PU_STATIC, 0);
    301 	for (i = 0; i < numflats; ++i)
    302 		flattranslation[i] = i;
    303 }
    304 
    305 void
    306 R_InitSpriteLumps()
    307 {
    308 	patch_t* patch;
    309 	int      i;
    310 
    311 	firstspritelump = W_GetNumForName("S_START") + 1;
    312 	lastspritelump = W_GetNumForName("S_END") - 1;
    313 	numspritelumps = lastspritelump - firstspritelump + 1;
    314 	spritewidth = Z_Malloc(numspritelumps * sizeof(*spritewidth), PU_STATIC, 0);
    315 	spriteoffset = Z_Malloc(numspritelumps * sizeof(*spriteoffset), PU_STATIC, 0);
    316 	spritetopoffset = Z_Malloc(numspritelumps * sizeof(*spritetopoffset), PU_STATIC, 0);
    317 	for (i = 0; i < numspritelumps; ++i) {
    318 		if (!(i & 63))
    319 			printf (".");
    320 		patch = W_CacheLumpNum(firstspritelump+i, PU_CACHE);
    321 		spritewidth[i] = patch->width<<FRACBITS;
    322 		spriteoffset[i] = patch->leftoffset<<FRACBITS;
    323 		spritetopoffset[i] = patch->topoffset<<FRACBITS;
    324 	}
    325 }
    326 
    327 void
    328 R_InitColormaps()
    329 {
    330 	int	lump, length;
    331 
    332 	lump = W_GetNumForName("COLORMAP");
    333 	length = W_LumpLength (lump) + 255;
    334 	colormaps = Z_Malloc (length, PU_STATIC, 0);
    335 	colormaps = (byte*)(((long)colormaps + 255)&~0xff);
    336 	W_ReadLump(lump, colormaps);
    337 }
    338 
    339 void
    340 R_InitData()
    341 {
    342 	R_InitTextures();
    343 	printf("\nInitTextures");
    344 	R_InitFlats();
    345 	printf("\nInitFlats");
    346 	R_InitSpriteLumps();
    347 	printf("\nInitSprites");
    348 	R_InitColormaps();
    349 	printf("\nInitColormaps");
    350 }
    351 
    352 int
    353 R_FlatNumForName(char* name)
    354 {
    355 	char namet[9];
    356 	int  i;
    357 
    358 	i = W_CheckNumForName(name);
    359 	if (i == -1) {
    360 		namet[8] = 0;
    361 		memcpy(namet, name,8);
    362 		I_Error("R_FlatNumForName: %s not found", namet);
    363 	}
    364 	return i - firstflat;
    365 }
    366 
    367 int
    368 R_CheckTextureNumForName(char *name)
    369 {
    370 	int i;
    371 
    372 	if (name[0] == '-')
    373 		return 0;
    374 	for (i = 0; i < numtextures; ++i)
    375 		if (!strncasecmp(textures_g[i]->name, name, 8))
    376 			return i;
    377 	return -1;
    378 }
    379 
    380 int
    381 R_TextureNumForName(char* name)
    382 {
    383 	int i;
    384 
    385 	i = R_CheckTextureNumForName(name);
    386 	if (i == -1)
    387 		I_Error("R_TextureNumForName: %s not found", name);
    388 	return i;
    389 }
    390 
    391 void
    392 R_PrecacheLevel()
    393 {
    394 	texture_t*		texture;
    395 	thinker_t*		th;
    396 	spriteframe_t*	sf;
    397 	char*           flatpresent, *texturepresent, *spritepresent;
    398 	int             i, j, k, lump;
    399 
    400 	if (demoplayback)
    401 		return;
    402 	flatpresent = alloca(numflats);
    403 	memset(flatpresent,0,numflats);
    404 	for (i = 0; i < numsectors; ++i) {
    405 		flatpresent[sectors[i].floorpic] = 1;
    406 		flatpresent[sectors[i].ceilingpic] = 1;
    407 	}
    408 	flatmemory = 0;
    409 	for (i = 0; i < numflats; ++i) {
    410 		if (flatpresent[i]) {
    411 			lump = firstflat + i;
    412 			flatmemory += lumpinfo_g[lump].size;
    413 			W_CacheLumpNum(lump, PU_CACHE);
    414 		}
    415 	}
    416 	texturepresent = alloca(numtextures);
    417 	memset (texturepresent,0, numtextures);
    418 	for (i = 0; i < numsides; ++i) {
    419 		texturepresent[sides[i].toptexture] = 1;
    420 		texturepresent[sides[i].midtexture] = 1;
    421 		texturepresent[sides[i].bottomtexture] = 1;
    422 	}
    423 	texturepresent[skytexture] = 1;
    424 	texturememory = 0;
    425 	for (i = 0; i < numtextures; ++i) {
    426 		if (!texturepresent[i])
    427 			continue;
    428 		texture = textures_g[i];
    429 		for (j = 0; j < texture->patchcount; ++j) {
    430 			lump = texture->patches[j].patch;
    431 			texturememory += lumpinfo_g[lump].size;
    432 			W_CacheLumpNum(lump , PU_CACHE);
    433 		}
    434 	}
    435 	spritepresent = alloca(numsprites);
    436 	memset (spritepresent,0, numsprites);
    437 	for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
    438 		if (th->function.acp1 == (actionf_p1)P_MobjThinker)
    439 			spritepresent[((mobj_t *)th)->sprite] = 1;
    440 	spritememory = 0;
    441 	for (i = 0; i < numsprites; ++i) {
    442 		if (!spritepresent[i])
    443 			continue;
    444 		for (j = 0; j < sprites[i].numframes; ++j) {
    445 			sf = &sprites[i].spriteframes[j];
    446 			for (k = 0; k < 8; ++k) {
    447 				lump = firstspritelump + sf->lump[k];
    448 				spritememory += lumpinfo_g[lump].size;
    449 				W_CacheLumpNum(lump , PU_CACHE);
    450 			}
    451 		}
    452 	}
    453 }