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