r_draw.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include "doomdef.h"
  23. #include "i_system.h"
  24. #include "z_zone.h"
  25. #include "w_wad.h"
  26. #include "r_local.h"
  27. // Needs access to LFB (guess what).
  28. #include "v_video.h"
  29. // State.
  30. #include "doomstat.h"
  31. // ?
  32. // status bar height at bottom of screen
  33. //
  34. // All drawing to the view buffer is accomplished in this file.
  35. // The other refresh files only know about ccordinates,
  36. // not the architecture of the frame buffer.
  37. // Conveniently, the frame buffer is a linear one,
  38. // and we need only the base address,
  39. // and the total size == width*height*depth/8.,
  40. //
  41. // Color tables for different ::g->players,
  42. // translate a limited part to another
  43. // (color ramps used for suit colors).
  44. //
  45. //
  46. // R_DrawColumn
  47. // Source is the top of the column to scale.
  48. //
  49. // first pixel in a column (possibly virtual)
  50. // just for profiling
  51. //
  52. // A column is a vertical slice/span from a wall texture that,
  53. // given the DOOM style restrictions on the view orientation,
  54. // will always have constant z depth.
  55. // Thus a special case loop for very fast rendering can
  56. // be used. It has also been used with Wolfenstein 3D.
  57. //
  58. void R_DrawColumn ( lighttable_t * dc_colormap,
  59. byte * dc_source )
  60. {
  61. int count;
  62. byte* dest;
  63. fixed_t frac;
  64. fixed_t fracstep;
  65. count = ::g->dc_yh - ::g->dc_yl;
  66. // Zero length, column does not exceed a pixel.
  67. if (count >= 0) {
  68. //return;
  69. #ifdef RANGECHECK
  70. if ((unsigned)::g->dc_x >= SCREENWIDTH
  71. || ::g->dc_yl < 0
  72. || ::g->dc_yh >= SCREENHEIGHT)
  73. I_Error ("R_DrawColumn: %i to %i at %i", ::g->dc_yl, ::g->dc_yh, ::g->dc_x);
  74. #endif
  75. // Framebuffer destination address.
  76. // Use ::g->ylookup LUT to avoid multiply with ScreenWidth.
  77. // Use ::g->columnofs LUT for subwindows?
  78. dest = ::g->ylookup[::g->dc_yl] + ::g->columnofs[::g->dc_x];
  79. // Determine scaling,
  80. // which is the only mapping to be done.
  81. fracstep = ::g->dc_iscale;
  82. frac = ::g->dc_texturemid + (::g->dc_yl-::g->centery)*fracstep;
  83. // Inner loop that does the actual texture mapping,
  84. // e.g. a DDA-lile scaling.
  85. // This is as fast as it gets.
  86. do
  87. {
  88. // Re-map color indices from wall texture column
  89. // using a lighting/special effects LUT.
  90. const int truncated1 = frac >> FRACBITS;
  91. const int wrapped1 = truncated1 & 127;
  92. *dest = dc_colormap[dc_source[wrapped1]];
  93. frac += fracstep;
  94. dest += SCREENWIDTH;
  95. } while (count--);
  96. }
  97. }
  98. // UNUSED.
  99. // Loop unrolled.
  100. #if 0
  101. void R_DrawColumn (void)
  102. {
  103. int count;
  104. byte* source;
  105. byte* dest;
  106. byte* colormap;
  107. unsigned frac;
  108. unsigned fracstep;
  109. unsigned fracstep2;
  110. unsigned fracstep3;
  111. unsigned fracstep4;
  112. count = ::g->dc_yh - ::g->dc_yl + 1;
  113. source = ::g->dc_source;
  114. colormap = ::g->dc_colormap;
  115. dest = ::g->ylookup[::g->dc_yl] + ::g->columnofs[::g->dc_x];
  116. fracstep = ::g->dc_iscale<<9;
  117. frac = (::g->dc_texturemid + (::g->dc_yl-::g->centery)*::g->dc_iscale)<<9;
  118. fracstep2 = fracstep+fracstep;
  119. fracstep3 = fracstep2+fracstep;
  120. fracstep4 = fracstep3+fracstep;
  121. while (count >= 8)
  122. {
  123. dest[0] = colormap[source[frac>>25]];
  124. dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]];
  125. dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]];
  126. dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
  127. frac += fracstep4;
  128. dest[SCREENWIDTH*4] = colormap[source[frac>>25]];
  129. dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]];
  130. dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]];
  131. dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]];
  132. frac += fracstep4;
  133. dest += SCREENWIDTH*8;
  134. count -= 8;
  135. }
  136. while (count > 0)
  137. {
  138. *dest = colormap[source[frac>>25]];
  139. dest += SCREENWIDTH;
  140. frac += fracstep;
  141. count--;
  142. }
  143. }
  144. #endif
  145. void R_DrawColumnLow ( lighttable_t * dc_colormap,
  146. byte * dc_source )
  147. {
  148. int count;
  149. byte* dest;
  150. byte* dest2;
  151. fixed_t frac;
  152. fixed_t fracstep;
  153. count = ::g->dc_yh - ::g->dc_yl;
  154. // Zero length.
  155. if (count < 0)
  156. return;
  157. #ifdef RANGECHECK
  158. if ((unsigned)::g->dc_x >= SCREENWIDTH
  159. || ::g->dc_yl < 0
  160. || ::g->dc_yh >= SCREENHEIGHT)
  161. {
  162. I_Error ("R_DrawColumn: %i to %i at %i", ::g->dc_yl, ::g->dc_yh, ::g->dc_x);
  163. }
  164. // ::g->dccount++;
  165. #endif
  166. // Blocky mode, need to multiply by 2.
  167. ::g->dc_x <<= 1;
  168. dest = ::g->ylookup[::g->dc_yl] + ::g->columnofs[::g->dc_x];
  169. dest2 = ::g->ylookup[::g->dc_yl] + ::g->columnofs[::g->dc_x+1];
  170. fracstep = ::g->dc_iscale;
  171. frac = ::g->dc_texturemid + (::g->dc_yl-::g->centery)*fracstep;
  172. do
  173. {
  174. // Hack. Does not work corretly.
  175. *dest2 = *dest = ::g->dc_colormap[::g->dc_source[(frac>>FRACBITS)&127]];
  176. dest += SCREENWIDTH;
  177. dest2 += SCREENWIDTH;
  178. frac += fracstep;
  179. } while (count--);
  180. }
  181. //
  182. // Spectre/Invisibility.
  183. //
  184. //
  185. // Framebuffer postprocessing.
  186. // Creates a fuzzy image by copying pixels
  187. // from adjacent ones to left and right.
  188. // Used with an all black colormap, this
  189. // could create the SHADOW effect,
  190. // i.e. spectres and invisible ::g->players.
  191. //
  192. void R_DrawFuzzColumn ( lighttable_t * dc_colormap,
  193. byte * dc_source )
  194. {
  195. int count;
  196. byte* dest;
  197. fixed_t frac;
  198. fixed_t fracstep;
  199. // Adjust borders. Low...
  200. if (!::g->dc_yl)
  201. ::g->dc_yl = 1;
  202. // .. and high.
  203. if (::g->dc_yh == ::g->viewheight-1)
  204. ::g->dc_yh = ::g->viewheight - 2;
  205. count = ::g->dc_yh - ::g->dc_yl;
  206. // Zero length.
  207. if (count < 0)
  208. return;
  209. #ifdef RANGECHECK
  210. if ((unsigned)::g->dc_x >= SCREENWIDTH
  211. || ::g->dc_yl < 0 || ::g->dc_yh >= SCREENHEIGHT)
  212. {
  213. I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  214. ::g->dc_yl, ::g->dc_yh, ::g->dc_x);
  215. }
  216. #endif
  217. // Keep till ::g->detailshift bug in blocky mode fixed,
  218. // or blocky mode removed.
  219. /* WATCOM code
  220. if (::g->detailshift)
  221. {
  222. if (::g->dc_x & 1)
  223. {
  224. outpw (GC_INDEX,GC_READMAP+(2<<8) );
  225. outp (SC_INDEX+1,12);
  226. }
  227. else
  228. {
  229. outpw (GC_INDEX,GC_READMAP);
  230. outp (SC_INDEX+1,3);
  231. }
  232. dest = destview + ::g->dc_yl*80 + (::g->dc_x>>1);
  233. }
  234. else
  235. {
  236. outpw (GC_INDEX,GC_READMAP+((::g->dc_x&3)<<8) );
  237. outp (SC_INDEX+1,1<<(::g->dc_x&3));
  238. dest = destview + ::g->dc_yl*80 + (::g->dc_x>>2);
  239. }*/
  240. // Does not work with blocky mode.
  241. dest = ::g->ylookup[::g->dc_yl] + ::g->columnofs[::g->dc_x];
  242. // Looks familiar.
  243. fracstep = ::g->dc_iscale;
  244. frac = ::g->dc_texturemid + (::g->dc_yl-::g->centery)*fracstep;
  245. // Looks like an attempt at dithering,
  246. // using the colormap #6 (of 0-31, a bit
  247. // brighter than average).
  248. do
  249. {
  250. // Lookup framebuffer, and retrieve
  251. // a pixel that is either one column
  252. // left or right of the current one.
  253. // Add index from colormap to index.
  254. *dest = ::g->colormaps[6*256+dest[::g->fuzzoffset[::g->fuzzpos]]];
  255. // Clamp table lookup index.
  256. if (++::g->fuzzpos == FUZZTABLE)
  257. ::g->fuzzpos = 0;
  258. dest += SCREENWIDTH;
  259. frac += fracstep;
  260. } while (count--);
  261. }
  262. //
  263. // R_DrawTranslatedColumn
  264. // Used to draw player ::g->sprites
  265. // with the green colorramp mapped to others.
  266. // Could be used with different translation
  267. // tables, e.g. the lighter colored version
  268. // of the BaronOfHell, the HellKnight, uses
  269. // identical ::g->sprites, kinda brightened up.
  270. //
  271. void R_DrawTranslatedColumn ( lighttable_t * dc_colormap,
  272. byte * dc_source )
  273. {
  274. int count;
  275. byte* dest;
  276. fixed_t frac;
  277. fixed_t fracstep;
  278. count = ::g->dc_yh - ::g->dc_yl;
  279. if (count < 0)
  280. return;
  281. #ifdef RANGECHECK
  282. if ((unsigned)::g->dc_x >= SCREENWIDTH
  283. || ::g->dc_yl < 0
  284. || ::g->dc_yh >= SCREENHEIGHT)
  285. {
  286. I_Error ( "R_DrawColumn: %i to %i at %i",
  287. ::g->dc_yl, ::g->dc_yh, ::g->dc_x);
  288. }
  289. #endif
  290. // WATCOM VGA specific.
  291. /* Keep for fixing.
  292. if (::g->detailshift)
  293. {
  294. if (::g->dc_x & 1)
  295. outp (SC_INDEX+1,12);
  296. else
  297. outp (SC_INDEX+1,3);
  298. dest = destview + ::g->dc_yl*80 + (::g->dc_x>>1);
  299. }
  300. else
  301. {
  302. outp (SC_INDEX+1,1<<(::g->dc_x&3));
  303. dest = destview + ::g->dc_yl*80 + (::g->dc_x>>2);
  304. }*/
  305. // FIXME. As above.
  306. dest = ::g->ylookup[::g->dc_yl] + ::g->columnofs[::g->dc_x];
  307. // Looks familiar.
  308. fracstep = ::g->dc_iscale;
  309. frac = ::g->dc_texturemid + (::g->dc_yl-::g->centery)*fracstep;
  310. // Here we do an additional index re-mapping.
  311. do
  312. {
  313. // Translation tables are used
  314. // to map certain colorramps to other ones,
  315. // used with PLAY ::g->sprites.
  316. // Thus the "green" ramp of the player 0 sprite
  317. // is mapped to gray, red, black/indigo.
  318. *dest = dc_colormap[::g->dc_translation[dc_source[frac>>FRACBITS]]];
  319. dest += SCREENWIDTH;
  320. frac += fracstep;
  321. } while (count--);
  322. }
  323. //
  324. // R_InitTranslationTables
  325. // Creates the translation tables to map
  326. // the green color ramp to gray, brown, red.
  327. // Assumes a given structure of the PLAYPAL.
  328. // Could be read from a lump instead.
  329. //
  330. void R_InitTranslationTables (void)
  331. {
  332. int i;
  333. ::g->translationtables = (byte*)DoomLib::Z_Malloc (256*3+255, PU_STATIC, 0);
  334. ::g->translationtables = (byte *)(( (int)::g->translationtables + 255 )& ~255);
  335. // translate just the 16 green colors
  336. for (i=0 ; i<256 ; i++)
  337. {
  338. if (i >= 0x70 && i<= 0x7f)
  339. {
  340. // map green ramp to gray, brown, red
  341. ::g->translationtables[i] = 0x60 + (i&0xf);
  342. ::g->translationtables [i+256] = 0x40 + (i&0xf);
  343. ::g->translationtables [i+512] = 0x20 + (i&0xf);
  344. }
  345. else
  346. {
  347. // Keep all other colors as is.
  348. ::g->translationtables[i] = ::g->translationtables[i+256]
  349. = ::g->translationtables[i+512] = i;
  350. }
  351. }
  352. }
  353. //
  354. // R_DrawSpan
  355. // With DOOM style restrictions on view orientation,
  356. // the floors and ceilings consist of horizontal slices
  357. // or spans with constant z depth.
  358. // However, rotation around the world z axis is possible,
  359. // thus this mapping, while simpler and faster than
  360. // perspective correct texture mapping, has to traverse
  361. // the texture at an angle in all but a few cases.
  362. // In consequence, flats are not stored by column (like walls),
  363. // and the inner loop has to step in texture space u and v.
  364. //
  365. // start of a 64*64 tile image
  366. // just for profiling
  367. //
  368. // Draws the actual span.
  369. void R_DrawSpan ( fixed_t xfrac,
  370. fixed_t yfrac,
  371. fixed_t ds_y,
  372. int ds_x1,
  373. int ds_x2,
  374. fixed_t ds_xstep,
  375. fixed_t ds_ystep,
  376. lighttable_t * ds_colormap,
  377. byte * ds_source )
  378. {
  379. byte* dest;
  380. int count;
  381. int spot;
  382. #ifdef RANGECHECK
  383. if (::g->ds_x2 < ::g->ds_x1
  384. || ::g->ds_x1<0
  385. || ::g->ds_x2>=SCREENWIDTH
  386. || (unsigned)::g->ds_y>SCREENHEIGHT)
  387. {
  388. I_Error( "R_DrawSpan: %i to %i at %i",
  389. ::g->ds_x1,::g->ds_x2,::g->ds_y);
  390. }
  391. // ::g->dscount++;
  392. #endif
  393. dest = ::g->ylookup[::g->ds_y] + ::g->columnofs[::g->ds_x1];
  394. // We do not check for zero spans here?
  395. count = ds_x2 - g->ds_x1;
  396. if ( ds_x2 < ds_x1 ) {
  397. return; // SMF - think this is the sky
  398. }
  399. do
  400. {
  401. // Current texture index in u,v.
  402. spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  403. // Lookup pixel from flat texture tile,
  404. // re-index using light/colormap.
  405. *dest++ = ds_colormap[ds_source[spot]];
  406. // Next step in u,v.
  407. xfrac += ds_xstep;
  408. yfrac += ds_ystep;
  409. } while (count--);
  410. }
  411. // UNUSED.
  412. // Loop unrolled by 4.
  413. #if 0
  414. void R_DrawSpan (void)
  415. {
  416. unsigned position, step;
  417. byte* source;
  418. byte* colormap;
  419. byte* dest;
  420. unsigned count;
  421. usingned spot;
  422. unsigned value;
  423. unsigned temp;
  424. unsigned xtemp;
  425. unsigned ytemp;
  426. position = ((::g->ds_xfrac<<10)&0xffff0000) | ((::g->ds_yfrac>>6)&0xffff);
  427. step = ((::g->ds_xstep<<10)&0xffff0000) | ((::g->ds_ystep>>6)&0xffff);
  428. source = ::g->ds_source;
  429. colormap = ::g->ds_colormap;
  430. dest = ::g->ylookup[::g->ds_y] + ::g->columnofs[::g->ds_x1];
  431. count = ::g->ds_x2 - ::g->ds_x1 + 1;
  432. while (count >= 4)
  433. {
  434. ytemp = position>>4;
  435. ytemp = ytemp & 4032;
  436. xtemp = position>>26;
  437. spot = xtemp | ytemp;
  438. position += step;
  439. dest[0] = colormap[source[spot]];
  440. ytemp = position>>4;
  441. ytemp = ytemp & 4032;
  442. xtemp = position>>26;
  443. spot = xtemp | ytemp;
  444. position += step;
  445. dest[1] = colormap[source[spot]];
  446. ytemp = position>>4;
  447. ytemp = ytemp & 4032;
  448. xtemp = position>>26;
  449. spot = xtemp | ytemp;
  450. position += step;
  451. dest[2] = colormap[source[spot]];
  452. ytemp = position>>4;
  453. ytemp = ytemp & 4032;
  454. xtemp = position>>26;
  455. spot = xtemp | ytemp;
  456. position += step;
  457. dest[3] = colormap[source[spot]];
  458. count -= 4;
  459. dest += 4;
  460. }
  461. while (count > 0)
  462. {
  463. ytemp = position>>4;
  464. ytemp = ytemp & 4032;
  465. xtemp = position>>26;
  466. spot = xtemp | ytemp;
  467. position += step;
  468. *dest++ = colormap[source[spot]];
  469. count--;
  470. }
  471. }
  472. #endif
  473. //
  474. // Again..
  475. //
  476. void R_DrawSpanLow ( fixed_t xfrac,
  477. fixed_t yfrac,
  478. fixed_t ds_y,
  479. int ds_x1,
  480. int ds_x2,
  481. fixed_t ds_xstep,
  482. fixed_t ds_ystep,
  483. lighttable_t * ds_colormap,
  484. byte * ds_source )
  485. {
  486. byte* dest;
  487. int count;
  488. int spot;
  489. #ifdef RANGECHECK
  490. if (::g->ds_x2 < ::g->ds_x1
  491. || ::g->ds_x1<0
  492. || ::g->ds_x2>=SCREENWIDTH
  493. || (unsigned)::g->ds_y>SCREENHEIGHT)
  494. {
  495. I_Error( "R_DrawSpan: %i to %i at %i",
  496. ::g->ds_x1,::g->ds_x2,::g->ds_y);
  497. }
  498. // ::g->dscount++;
  499. #endif
  500. // Blocky mode, need to multiply by 2.
  501. ::g->ds_x1 <<= 1;
  502. ::g->ds_x2 <<= 1;
  503. dest = ::g->ylookup[::g->ds_y] + ::g->columnofs[::g->ds_x1];
  504. count = ::g->ds_x2 - ::g->ds_x1;
  505. do
  506. {
  507. spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  508. // Lowres/blocky mode does it twice,
  509. // while scale is adjusted appropriately.
  510. *dest++ = ::g->ds_colormap[::g->ds_source[spot]];
  511. *dest++ = ::g->ds_colormap[::g->ds_source[spot]];
  512. xfrac += ::g->ds_xstep;
  513. yfrac += ::g->ds_ystep;
  514. } while (count--);
  515. }
  516. //
  517. // R_InitBuffer
  518. // Creats lookup tables that avoid
  519. // multiplies and other hazzles
  520. // for getting the framebuffer address
  521. // of a pixel to draw.
  522. //
  523. void
  524. R_InitBuffer
  525. ( int width,
  526. int height )
  527. {
  528. int i;
  529. // Handle resize,
  530. // e.g. smaller view windows
  531. // with border and/or status bar.
  532. ::g->viewwindowx = (SCREENWIDTH-width) >> 1;
  533. // Column offset. For windows.
  534. for (i=0 ; i<width ; i++)
  535. ::g->columnofs[i] = ::g->viewwindowx + i;
  536. // Samw with base row offset.
  537. if (width == SCREENWIDTH)
  538. ::g->viewwindowy = 0;
  539. else
  540. ::g->viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
  541. // Preclaculate all row offsets.
  542. for (i=0 ; i<height ; i++)
  543. ::g->ylookup[i] = ::g->screens[0] + (i+::g->viewwindowy)*SCREENWIDTH;
  544. }
  545. //
  546. // R_FillBackScreen
  547. // Fills the back screen with a pattern
  548. // for variable screen sizes
  549. // Also draws a beveled edge.
  550. //
  551. void R_FillBackScreen (void)
  552. {
  553. byte* src;
  554. byte* dest;
  555. int x;
  556. int y;
  557. int width, height, windowx, windowy;
  558. patch_t* patch;
  559. // DOOM border patch.
  560. char name1[] = "FLOOR7_2";
  561. // DOOM II border patch.
  562. char name2[] = "GRNROCK";
  563. char* name;
  564. if (::g->scaledviewwidth == SCREENWIDTH)
  565. return;
  566. if ( ::g->gamemode == commercial)
  567. name = name2;
  568. else
  569. name = name1;
  570. src = (byte*)W_CacheLumpName (name, PU_CACHE_SHARED);
  571. dest = ::g->screens[1];
  572. for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++) {
  573. for (x=0 ; x<SCREENWIDTH/64 ; x++) {
  574. memcpy(dest, src+((y&63)<<6), 64);
  575. dest += 64;
  576. }
  577. if (SCREENWIDTH&63)
  578. {
  579. memcpy(dest, src+((y&63)<<6), SCREENWIDTH&63);
  580. dest += (SCREENWIDTH&63);
  581. }
  582. }
  583. width = ::g->scaledviewwidth / GLOBAL_IMAGE_SCALER;
  584. height = ::g->viewheight / GLOBAL_IMAGE_SCALER;
  585. windowx = ::g->viewwindowx / GLOBAL_IMAGE_SCALER;
  586. windowy = ::g->viewwindowy / GLOBAL_IMAGE_SCALER;
  587. patch = (patch_t*)W_CacheLumpName ("brdr_t",PU_CACHE_SHARED);
  588. for (x=0 ; x<width ; x+=8) {
  589. V_DrawPatch (windowx+x,windowy-8,1,patch);
  590. }
  591. patch = (patch_t*)W_CacheLumpName ("brdr_b",PU_CACHE_SHARED);
  592. for (x=0 ; x<width ; x+=8) {
  593. V_DrawPatch (windowx+x,windowy+height,1,patch);
  594. }
  595. patch = (patch_t*)W_CacheLumpName ("brdr_l",PU_CACHE_SHARED);
  596. for (y=0 ; y<height ; y+=8) {
  597. V_DrawPatch (windowx-8,windowy+y,1,patch);
  598. }
  599. patch = (patch_t*)W_CacheLumpName ("brdr_r",PU_CACHE_SHARED);
  600. for (y=0 ; y<height ; y+=8) {
  601. V_DrawPatch (windowx+width,windowy+y,1,patch);
  602. }
  603. // Draw beveled edge.
  604. V_DrawPatch(windowx-8, windowy-8, 1, (patch_t*)W_CacheLumpName ("brdr_tl",PU_CACHE_SHARED));
  605. V_DrawPatch(windowx+width, windowy-8, 1, (patch_t*)W_CacheLumpName ("brdr_tr",PU_CACHE_SHARED));
  606. V_DrawPatch(windowx-8, windowy+height, 1, (patch_t*)W_CacheLumpName ("brdr_bl",PU_CACHE_SHARED));
  607. V_DrawPatch (windowx+width, windowy+height, 1, (patch_t*)W_CacheLumpName ("brdr_br",PU_CACHE_SHARED));
  608. }
  609. //
  610. // Copy a screen buffer.
  611. //
  612. void
  613. R_VideoErase
  614. ( unsigned ofs,
  615. int count )
  616. {
  617. // LFB copy.
  618. // This might not be a good idea if memcpy
  619. // is not optiomal, e.g. byte by byte on
  620. // a 32bit CPU, as GNU GCC/Linux libc did
  621. // at one point.
  622. memcpy(::g->screens[0]+ofs, ::g->screens[1]+ofs, count);
  623. }
  624. //
  625. // R_DrawViewBorder
  626. // Draws the border around the view
  627. // for different size windows?
  628. //
  629. void
  630. V_MarkRect
  631. ( int x,
  632. int y,
  633. int width,
  634. int height );
  635. void R_DrawViewBorder (void)
  636. {
  637. int top;
  638. int side;
  639. int ofs;
  640. int i;
  641. if (::g->scaledviewwidth == SCREENWIDTH)
  642. return;
  643. top = ((SCREENHEIGHT-SBARHEIGHT)-::g->viewheight)/2;
  644. side = (SCREENWIDTH-::g->scaledviewwidth)/2;
  645. // copy top and one line of left side
  646. R_VideoErase (0, top*SCREENWIDTH+side);
  647. // copy one line of right side and bottom
  648. ofs = (::g->viewheight+top)*SCREENWIDTH-side;
  649. R_VideoErase (ofs, top*SCREENWIDTH+side);
  650. // copy ::g->sides using wraparound
  651. ofs = top*SCREENWIDTH + SCREENWIDTH-side;
  652. side <<= 1;
  653. for (i=1 ; i < ::g->viewheight ; i++)
  654. {
  655. R_VideoErase (ofs, side);
  656. ofs += SCREENWIDTH;
  657. }
  658. // ?
  659. V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT);
  660. }