r_draw.c 18 KB

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