R_DATA.C 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. // R_data.c
  2. #include "DoomDef.h"
  3. #include "R_local.h"
  4. #include "P_local.h"
  5. extern void CheckAbortStartup(void);
  6. typedef struct
  7. {
  8. int originx; // block origin (allways UL), which has allready
  9. int originy; // accounted for the patch's internal origin
  10. int patch;
  11. } texpatch_t;
  12. // a maptexturedef_t describes a rectangular texture, which is composed of one
  13. // or more mappatch_t structures that arrange graphic patches
  14. typedef struct
  15. {
  16. char name[8]; // for switch changing, etc
  17. short width;
  18. short height;
  19. short patchcount;
  20. texpatch_t patches[1]; // [patchcount] drawn back to front
  21. // into the cached texture
  22. } texture_t;
  23. int firstflat, lastflat, numflats;
  24. int firstpatch, lastpatch, numpatches;
  25. int firstspritelump, lastspritelump, numspritelumps;
  26. int numtextures;
  27. texture_t **textures;
  28. int *texturewidthmask;
  29. fixed_t *textureheight; // needed for texture pegging
  30. int *texturecompositesize;
  31. short **texturecolumnlump;
  32. unsigned short **texturecolumnofs;
  33. byte **texturecomposite;
  34. int *flattranslation; // for global animation
  35. int *texturetranslation; // for global animation
  36. fixed_t *spritewidth; // needed for pre rendering
  37. fixed_t *spriteoffset;
  38. fixed_t *spritetopoffset;
  39. lighttable_t *colormaps;
  40. /*
  41. ==============================================================================
  42. MAPTEXTURE_T CACHING
  43. when a texture is first needed, it counts the number of composite columns
  44. required in the texture and allocates space for a column directory and any
  45. new columns. The directory will simply point inside other patches if there
  46. is only one patch in a given column, but any columns with multiple patches
  47. will have new column_ts generated.
  48. ==============================================================================
  49. */
  50. /*
  51. ===================
  52. =
  53. = R_DrawColumnInCache
  54. =
  55. = Clip and draw a column from a patch into a cached post
  56. =
  57. ===================
  58. */
  59. void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight)
  60. {
  61. int count, position;
  62. byte *source, *dest;
  63. dest = (byte *)cache + 3;
  64. while (patch->topdelta != 0xff)
  65. {
  66. source = (byte *)patch + 3;
  67. count = patch->length;
  68. position = originy + patch->topdelta;
  69. if (position < 0)
  70. {
  71. count += position;
  72. position = 0;
  73. }
  74. if (position + count > cacheheight)
  75. count = cacheheight - position;
  76. if (count > 0)
  77. memcpy (cache + position, source, count);
  78. patch = (column_t *)( (byte *)patch + patch->length + 4);
  79. }
  80. }
  81. /*
  82. ===================
  83. =
  84. = R_GenerateComposite
  85. =
  86. ===================
  87. */
  88. void R_GenerateComposite (int texnum)
  89. {
  90. byte *block;
  91. texture_t *texture;
  92. texpatch_t *patch;
  93. patch_t *realpatch;
  94. int x, x1, x2;
  95. int i;
  96. column_t *patchcol;
  97. short *collump;
  98. unsigned short *colofs;
  99. texture = textures[texnum];
  100. block = Z_Malloc (texturecompositesize[texnum], PU_STATIC,
  101. &texturecomposite[texnum]);
  102. collump = texturecolumnlump[texnum];
  103. colofs = texturecolumnofs[texnum];
  104. //
  105. // composite the columns together
  106. //
  107. patch = texture->patches;
  108. for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
  109. {
  110. realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  111. x1 = patch->originx;
  112. x2 = x1 + SHORT(realpatch->width);
  113. if (x1<0)
  114. x = 0;
  115. else
  116. x = x1;
  117. if (x2 > texture->width)
  118. x2 = texture->width;
  119. for ( ; x<x2 ; x++)
  120. {
  121. if (collump[x] >= 0)
  122. continue; // column does not have multiple patches
  123. patchcol = (column_t *)((byte *)realpatch +
  124. LONG(realpatch->columnofs[x-x1]));
  125. R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy,
  126. texture->height);
  127. }
  128. }
  129. // now that the texture has been built, it is purgable
  130. Z_ChangeTag (block, PU_CACHE);
  131. }
  132. /*
  133. ===================
  134. =
  135. = R_GenerateLookup
  136. =
  137. ===================
  138. */
  139. void R_GenerateLookup (int texnum)
  140. {
  141. texture_t *texture;
  142. byte *patchcount; // [texture->width]
  143. texpatch_t *patch;
  144. patch_t *realpatch;
  145. int x, x1, x2;
  146. int i;
  147. short *collump;
  148. unsigned short *colofs;
  149. texture = textures[texnum];
  150. texturecomposite[texnum] = 0; // composited not created yet
  151. texturecompositesize[texnum] = 0;
  152. collump = texturecolumnlump[texnum];
  153. colofs = texturecolumnofs[texnum];
  154. //
  155. // count the number of columns that are covered by more than one patch
  156. // fill in the lump / offset, so columns with only a single patch are
  157. // all done
  158. //
  159. patchcount = (byte *)alloca (texture->width);
  160. memset (patchcount, 0, texture->width);
  161. patch = texture->patches;
  162. for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
  163. {
  164. realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
  165. x1 = patch->originx;
  166. x2 = x1 + SHORT(realpatch->width);
  167. if (x1 < 0)
  168. x = 0;
  169. else
  170. x = x1;
  171. if (x2 > texture->width)
  172. x2 = texture->width;
  173. for ( ; x<x2 ; x++)
  174. {
  175. patchcount[x]++;
  176. collump[x] = patch->patch;
  177. colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
  178. }
  179. }
  180. for (x=0 ; x<texture->width ; x++)
  181. {
  182. if (!patchcount[x])
  183. {
  184. printf ("R_GenerateLookup: column without a patch (%s)\n", texture->name);
  185. return;
  186. }
  187. // I_Error ("R_GenerateLookup: column without a patch");
  188. if (patchcount[x] > 1)
  189. {
  190. collump[x] = -1; // use the cached block
  191. colofs[x] = texturecompositesize[texnum];
  192. if (texturecompositesize[texnum] > 0x10000-texture->height)
  193. I_Error ("R_GenerateLookup: texture %i is >64k",texnum);
  194. texturecompositesize[texnum] += texture->height;
  195. }
  196. }
  197. }
  198. /*
  199. ================
  200. =
  201. = R_GetColumn
  202. =
  203. ================
  204. */
  205. byte *R_GetColumn (int tex, int col)
  206. {
  207. int lump, ofs;
  208. col &= texturewidthmask[tex];
  209. lump = texturecolumnlump[tex][col];
  210. ofs = texturecolumnofs[tex][col];
  211. if (lump > 0)
  212. return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
  213. if (!texturecomposite[tex])
  214. R_GenerateComposite (tex);
  215. return texturecomposite[tex] + ofs;
  216. }
  217. /*
  218. ==================
  219. =
  220. = R_InitTextures
  221. =
  222. = Initializes the texture list with the textures from the world map
  223. =
  224. ==================
  225. */
  226. void R_InitTextures (void)
  227. {
  228. maptexture_t *mtexture;
  229. texture_t *texture;
  230. mappatch_t *mpatch;
  231. texpatch_t *patch;
  232. int i,j;
  233. int *maptex, *maptex2, *maptex1;
  234. char name[9], *names, *name_p;
  235. int *patchlookup;
  236. int totalwidth;
  237. int nummappatches;
  238. int offset, maxoff, maxoff2;
  239. int numtextures1, numtextures2;
  240. int *directory;
  241. //
  242. // load the patch names from pnames.lmp
  243. //
  244. name[8] = 0;
  245. names = W_CacheLumpName ("PNAMES", PU_STATIC);
  246. nummappatches = LONG ( *((int *)names) );
  247. name_p = names+4;
  248. patchlookup = alloca (nummappatches*sizeof(*patchlookup));
  249. for (i=0 ; i<nummappatches ; i++)
  250. {
  251. strncpy (name,name_p+i*8, 8);
  252. patchlookup[i] = W_CheckNumForName (name);
  253. }
  254. Z_Free (names);
  255. //
  256. // load the map texture definitions from textures.lmp
  257. //
  258. maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
  259. numtextures1 = LONG(*maptex);
  260. maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
  261. directory = maptex+1;
  262. if (W_CheckNumForName ("TEXTURE2") != -1)
  263. {
  264. maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
  265. numtextures2 = LONG(*maptex2);
  266. maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
  267. }
  268. else
  269. {
  270. maptex2 = NULL;
  271. numtextures2 = 0;
  272. maxoff2 = 0;
  273. }
  274. numtextures = numtextures1 + numtextures2;
  275. //
  276. // Init the startup thermometer at this point...
  277. //
  278. {
  279. int spramount;
  280. spramount = W_GetNumForName("S_END") - W_GetNumForName("S_START") + 1;
  281. InitThermo(spramount + numtextures + 6);
  282. }
  283. textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
  284. texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
  285. texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
  286. texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
  287. texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
  288. texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
  289. textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
  290. totalwidth = 0;
  291. for (i=0 ; i<numtextures ; i++, directory++)
  292. {
  293. #ifdef __NEXT__
  294. if(!(i&63))
  295. printf (".");
  296. #else
  297. IncThermo();
  298. #endif
  299. if (i == numtextures1)
  300. { // start looking in second texture file
  301. maptex = maptex2;
  302. maxoff = maxoff2;
  303. directory = maptex+1;
  304. }
  305. offset = LONG(*directory);
  306. if (offset > maxoff)
  307. I_Error ("R_InitTextures: bad texture directory");
  308. mtexture = (maptexture_t *) ( (byte *)maptex + offset);
  309. texture = textures[i] = Z_Malloc (sizeof(texture_t)
  310. + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), PU_STATIC,
  311. 0);
  312. texture->width = SHORT(mtexture->width);
  313. texture->height = SHORT(mtexture->height);
  314. texture->patchcount = SHORT(mtexture->patchcount);
  315. memcpy (texture->name, mtexture->name, sizeof(texture->name));
  316. mpatch = &mtexture->patches[0];
  317. patch = &texture->patches[0];
  318. for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
  319. {
  320. patch->originx = SHORT(mpatch->originx);
  321. patch->originy = SHORT(mpatch->originy);
  322. patch->patch = patchlookup[SHORT(mpatch->patch)];
  323. if (patch->patch == -1)
  324. I_Error (
  325. "R_InitTextures: Missing patch in texture %s",texture->name);
  326. }
  327. texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  328. texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
  329. j = 1;
  330. while (j*2 <= texture->width)
  331. j<<=1;
  332. texturewidthmask[i] = j-1;
  333. textureheight[i] = texture->height<<FRACBITS;
  334. totalwidth += texture->width;
  335. }
  336. Z_Free (maptex1);
  337. if (maptex2)
  338. Z_Free (maptex2);
  339. //
  340. // precalculate whatever possible
  341. //
  342. for(i = 0; i < numtextures; i++)
  343. {
  344. R_GenerateLookup(i);
  345. CheckAbortStartup();
  346. }
  347. //
  348. // translation table for global animation
  349. //
  350. texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
  351. for (i=0 ; i<numtextures ; i++)
  352. texturetranslation[i] = i;
  353. }
  354. /*
  355. ================
  356. =
  357. = R_InitFlats
  358. =
  359. =================
  360. */
  361. void R_InitFlats (void)
  362. {
  363. int i;
  364. firstflat = W_GetNumForName ("F_START") + 1;
  365. lastflat = W_GetNumForName ("F_END") - 1;
  366. numflats = lastflat - firstflat + 1;
  367. // translation table for global animation
  368. flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
  369. for (i=0 ; i<numflats ; i++)
  370. flattranslation[i] = i;
  371. }
  372. /*
  373. ================
  374. =
  375. = R_InitSpriteLumps
  376. =
  377. = Finds the width and hoffset of all sprites in the wad, so the sprite doesn't
  378. = need to be cached just for the header during rendering
  379. =================
  380. */
  381. void R_InitSpriteLumps (void)
  382. {
  383. int i;
  384. patch_t *patch;
  385. firstspritelump = W_GetNumForName ("S_START") + 1;
  386. lastspritelump = W_GetNumForName ("S_END") - 1;
  387. numspritelumps = lastspritelump - firstspritelump + 1;
  388. spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  389. spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  390. spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
  391. for (i=0 ; i< numspritelumps ; i++)
  392. {
  393. #ifdef __NEXT__
  394. if (!(i&63))
  395. printf (".");
  396. #else
  397. IncThermo();
  398. #endif
  399. patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
  400. spritewidth[i] = SHORT(patch->width)<<FRACBITS;
  401. spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
  402. spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
  403. }
  404. }
  405. /*
  406. ================
  407. =
  408. = R_InitColormaps
  409. =
  410. =================
  411. */
  412. void R_InitColormaps (void)
  413. {
  414. int lump, length;
  415. //
  416. // load in the light tables
  417. // 256 byte align tables
  418. //
  419. lump = W_GetNumForName("COLORMAP");
  420. length = W_LumpLength (lump) + 255;
  421. colormaps = Z_Malloc (length, PU_STATIC, 0);
  422. colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
  423. W_ReadLump (lump,colormaps);
  424. }
  425. /*
  426. ================
  427. =
  428. = R_InitData
  429. =
  430. = Locates all the lumps that will be used by all views
  431. = Must be called after W_Init
  432. =================
  433. */
  434. void R_InitData (void)
  435. {
  436. tprintf("\nR_InitTextures ",0);
  437. R_InitTextures ();
  438. //printf (".");
  439. tprintf("R_InitFlats\n",0);
  440. R_InitFlats ();
  441. IncThermo();
  442. //printf (".");
  443. tprintf("R_InitSpriteLumps ",0);
  444. R_InitSpriteLumps ();
  445. IncThermo();
  446. //printf (".");
  447. R_InitColormaps ();
  448. }
  449. //=============================================================================
  450. /*
  451. ================
  452. =
  453. = R_FlatNumForName
  454. =
  455. ================
  456. */
  457. int R_FlatNumForName (char *name)
  458. {
  459. int i;
  460. char namet[9];
  461. i = W_CheckNumForName (name);
  462. if (i == -1)
  463. {
  464. namet[8] = 0;
  465. memcpy (namet, name,8);
  466. I_Error ("R_FlatNumForName: %s not found",namet);
  467. }
  468. return i - firstflat;
  469. }
  470. /*
  471. ================
  472. =
  473. = R_CheckTextureNumForName
  474. =
  475. ================
  476. */
  477. int R_CheckTextureNumForName (char *name)
  478. {
  479. int i;
  480. if (name[0] == '-') // no texture marker
  481. return 0;
  482. for (i=0 ; i<numtextures ; i++)
  483. if (!strncasecmp (textures[i]->name, name, 8) )
  484. return i;
  485. return -1;
  486. }
  487. /*
  488. ================
  489. =
  490. = R_TextureNumForName
  491. =
  492. ================
  493. */
  494. int R_TextureNumForName (char *name)
  495. {
  496. int i;
  497. //char namet[9];
  498. i = R_CheckTextureNumForName (name);
  499. if (i==-1)
  500. I_Error ("R_TextureNumForName: %s not found",name);
  501. return i;
  502. }
  503. /*
  504. =================
  505. =
  506. = R_PrecacheLevel
  507. =
  508. = Preloads all relevent graphics for the level
  509. =================
  510. */
  511. int flatmemory, texturememory, spritememory;
  512. void R_PrecacheLevel (void)
  513. {
  514. char *flatpresent;
  515. char *texturepresent;
  516. char *spritepresent;
  517. int i,j,k, lump;
  518. texture_t *texture;
  519. thinker_t *th;
  520. spriteframe_t *sf;
  521. if (demoplayback)
  522. return;
  523. //
  524. // precache flats
  525. //
  526. flatpresent = alloca(numflats);
  527. memset (flatpresent,0,numflats);
  528. for (i=0 ; i<numsectors ; i++)
  529. {
  530. flatpresent[sectors[i].floorpic] = 1;
  531. flatpresent[sectors[i].ceilingpic] = 1;
  532. }
  533. flatmemory = 0;
  534. for (i=0 ; i<numflats ; i++)
  535. if (flatpresent[i])
  536. {
  537. lump = firstflat + i;
  538. flatmemory += lumpinfo[lump].size;
  539. W_CacheLumpNum(lump, PU_CACHE);
  540. }
  541. //
  542. // precache textures
  543. //
  544. texturepresent = alloca(numtextures);
  545. memset (texturepresent,0, numtextures);
  546. for (i=0 ; i<numsides ; i++)
  547. {
  548. texturepresent[sides[i].toptexture] = 1;
  549. texturepresent[sides[i].midtexture] = 1;
  550. texturepresent[sides[i].bottomtexture] = 1;
  551. }
  552. texturepresent[skytexture] = 1;
  553. texturememory = 0;
  554. for (i=0 ; i<numtextures ; i++)
  555. {
  556. if (!texturepresent[i])
  557. continue;
  558. texture = textures[i];
  559. for (j=0 ; j<texture->patchcount ; j++)
  560. {
  561. lump = texture->patches[j].patch;
  562. texturememory += lumpinfo[lump].size;
  563. W_CacheLumpNum(lump , PU_CACHE);
  564. }
  565. }
  566. //
  567. // precache sprites
  568. //
  569. spritepresent = alloca(numsprites);
  570. memset (spritepresent,0, numsprites);
  571. for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  572. {
  573. if (th->function == P_MobjThinker)
  574. spritepresent[((mobj_t *)th)->sprite] = 1;
  575. }
  576. spritememory = 0;
  577. for (i=0 ; i<numsprites ; i++)
  578. {
  579. if (!spritepresent[i])
  580. continue;
  581. for (j=0 ; j<sprites[i].numframes ; j++)
  582. {
  583. sf = &sprites[i].spriteframes[j];
  584. for (k=0 ; k<8 ; k++)
  585. {
  586. lump = firstspritelump + sf->lump[k];
  587. spritememory += lumpinfo[lump].size;
  588. W_CacheLumpNum(lump , PU_CACHE);
  589. }
  590. }
  591. }
  592. }