A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 723 lines 21 kB view raw
1/* Emacs style mode select -*- C++ -*- 2 *----------------------------------------------------------------------------- 3 * 4 * 5 * PrBoom a Doom port merged with LxDoom and LSDLDoom 6 * based on BOOM, a modified and improved DOOM engine 7 * Copyright (C) 1999 by 8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman 9 * Copyright (C) 1999-2000 by 10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 25 * 02111-1307, USA. 26 * 27 * DESCRIPTION: 28 * The actual span/column drawing functions. 29 * Here find the main potential for optimization, 30 * e.g. inline assembly, different algorithms. 31 * 32 *-----------------------------------------------------------------------------*/ 33 34#include "doomstat.h" 35#include "w_wad.h" 36#include "r_main.h" 37#include "v_video.h" 38#include "st_stuff.h" 39#include "g_game.h" 40#include "am_map.h" 41//#include "lprintf.h" 42#include "rockmacros.h" 43 44// 45// All drawing to the view buffer is accomplished in this file. 46// The other refresh files only know about ccordinates, 47// not the architecture of the frame buffer. 48// Conveniently, the frame buffer is a linear one, 49// and we need only the base address, 50// and the total size == width*height*depth/8., 51// 52 53//byte* viewimage; 54int viewwidth; 55int scaledviewwidth; 56int viewheight; 57int viewwindowx; 58int viewwindowy; 59 60byte *topleft IBSS_ATTR; 61 62// Color tables for different players, 63// translate a limited part to another 64// (color ramps used for suit colors). 65// 66 67// CPhipps - made const*'s 68const byte *tranmap IBSS_ATTR; // translucency filter maps 256x256 // phares 69const byte *main_tranmap IBSS_ATTR; // killough 4/11/98 70 71// 72// R_DrawColumn 73// Source is the top of the column to scale. 74// 75 76lighttable_t *dc_colormap IBSS_ATTR; 77int dc_x IBSS_ATTR; 78int dc_yl IBSS_ATTR; 79int dc_yh IBSS_ATTR; 80fixed_t dc_iscale IBSS_ATTR; 81fixed_t dc_texturemid IBSS_ATTR; 82int dc_texheight IBSS_ATTR; // killough 83const byte *dc_source IBSS_ATTR; // first pixel in a column (possibly virtual) 84 85 86// 87// A column is a vertical slice/span from a wall texture that, 88// given the DOOM style restrictions on the view orientation, 89// will always have constant z depth. 90// Thus a special case loop for very fast rendering can 91// be used. It has also been used with Wolfenstein 3D. 92// 93void R_DrawColumn (void) 94{ 95 int count; 96 register byte *dest; // killough 97 register fixed_t frac; // killough 98 99 // leban 1/17/99: 100 // removed the + 1 here, adjusted the if test, and added an increment 101 // later. this helps a compiler pipeline a bit better. the x86 102 // assembler also does this. 103 count = dc_yh - dc_yl; 104 105 // Zero length, column does not exceed a pixel. 106 if (count < 0) 107 return; 108 109#ifdef RANGECHECK 110 111 if ((unsigned)dc_x >= SCREENWIDTH 112 || dc_yl < 0 113 || dc_yh >= SCREENHEIGHT) 114 I_Error ("R_DrawColumn: %d to %d at %d", dc_yl, dc_yh, dc_x); 115#endif 116 117 count++; 118 119 // Framebuffer destination address. 120 dest = topleft + dc_yl*SCREENWIDTH + dc_x; 121 122 // Determine scaling, 123 // which is the only mapping to be done. 124#define fracstep dc_iscale 125 126 frac = dc_texturemid + (dc_yl-centery)*fracstep; 127 128 // Inner loop that does the actual texture mapping, 129 // e.g. a DDA-lile scaling. 130 // This is as fast as it gets. (Yeah, right!!! -- killough) 131 // 132 // killough 2/1/98: more performance tuning 133 134 if (dc_texheight == 128) 135 { 136 while(count--) 137 { 138 *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; 139 frac += fracstep; 140 dest += SCREENWIDTH; 141 } 142 } 143 else if (dc_texheight == 0) 144 { 145 /* cph - another special case */ 146 while (count--) 147 { 148 *dest = dc_colormap[dc_source[frac>>FRACBITS]]; 149 frac += fracstep; 150 dest += SCREENWIDTH; 151 } 152 } 153 else 154 { 155 register unsigned heightmask = dc_texheight-1; // CPhipps - specify type 156 if (! (dc_texheight & heightmask) ) // power of 2 -- killough 157 { 158 while (count>0) // texture height is a power of 2 -- killough 159 { 160 *dest = dc_colormap[dc_source[(frac>>FRACBITS) & heightmask]]; 161 dest += SCREENWIDTH; 162 frac += fracstep; 163 count--; 164 } 165 } 166 else 167 { 168 heightmask++; 169 heightmask <<= FRACBITS; 170 171 if (frac < 0) 172 while ((frac += heightmask) < 0) 173 ; 174 else 175 while (frac >= (int)heightmask) 176 frac -= heightmask; 177 178 while(count>0) 179 { 180 // Re-map color indices from wall texture column 181 // using a lighting/special effects LUT. 182 183 // heightmask is the Tutti-Frutti fix -- killough 184 185 *dest = dc_colormap[dc_source[frac>>FRACBITS]]; 186 dest += SCREENWIDTH; 187 if ((frac += fracstep) >= (int)heightmask) 188 frac -= heightmask; 189 count--; 190 } 191 } 192 } 193} 194#undef fracstep 195 196// Here is the version of R_DrawColumn that deals with translucent // phares 197// textures and sprites. It's identical to R_DrawColumn except // | 198// for the spot where the color index is stuffed into *dest. At // V 199// that point, the existing color index and the new color index 200// are mapped through the TRANMAP lump filters to get a new color 201// index whose RGB values are the average of the existing and new 202// colors. 203// 204// Since we're concerned about performance, the 'translucent or 205// opaque' decision is made outside this routine, not down where the 206// actual code differences are. 207 208void R_DrawTLColumn (void) 209{ 210 int count; 211 register byte *dest; // killough 212 register fixed_t frac; // killough 213 214 count = dc_yh - dc_yl + 1; 215 216 // Zero length, column does not exceed a pixel. 217 if (count <= 0) 218 return; 219 220#ifdef RANGECHECK 221 222 if ((unsigned)dc_x >= (unsigned)SCREENWIDTH 223 || dc_yl < 0 224 || dc_yh >= SCREENHEIGHT) 225 I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); 226#endif 227 228 // Framebuffer destination address. 229 dest = topleft + dc_yl*SCREENWIDTH + dc_x; 230 231 // Determine scaling, 232 // which is the only mapping to be done. 233#define fracstep dc_iscale 234 235 frac = dc_texturemid + (dc_yl-centery)*fracstep; 236 237 // Inner loop that does the actual texture mapping, 238 // e.g. a DDA-lile scaling. 239 // This is as fast as it gets. (Yeah, right!!! -- killough) 240 // 241 // killough 2/1/98, 2/21/98: more performance tuning 242 243 { 244 register const byte *source = dc_source; 245 register const lighttable_t *colormap = dc_colormap; 246 register unsigned heightmask = dc_texheight-1; // CPhipps - specify type 247 if (dc_texheight & heightmask) // not a power of 2 -- killough 248 { 249 heightmask++; 250 heightmask <<= FRACBITS; 251 252 if (frac < 0) 253 while ((frac += heightmask) < 0) 254 ; 255 else 256 while (frac >= (int)heightmask) 257 frac -= heightmask; 258 259 do 260 { 261 // Re-map color indices from wall texture column 262 // using a lighting/special effects LUT. 263 264 // heightmask is the Tutti-Frutti fix -- killough 265 266 *dest = tranmap[(*dest<<8)+colormap[source[frac>>FRACBITS]]]; // phares 267 dest += SCREENWIDTH; 268 if ((frac += fracstep) >= (int)heightmask) 269 frac -= heightmask; 270 } 271 while (--count); 272 } 273 else 274 { 275 while ((count-=2)>=0) // texture height is a power of 2 -- killough 276 { 277 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares 278 dest += SCREENWIDTH; 279 frac += fracstep; 280 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares 281 dest += SCREENWIDTH; 282 frac += fracstep; 283 } 284 if (count & 1) 285 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares 286 } 287 } 288} 289#undef fracstep 290 291// 292// Spectre/Invisibility. 293// 294 295#define FUZZTABLE 50 296// proff 08/17/98: Changed for high-res 297//#define FUZZOFF (SCREENWIDTH) 298#define FUZZOFF 1 299 300static const int fuzzoffset_org[FUZZTABLE] ICONST_ATTR = { 301 FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, 302 FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, 303 FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF, 304 FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, 305 FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF, 306 FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF, 307 FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF 308 } ; 309 310static int fuzzoffset[FUZZTABLE] IBSS_ATTR; 311 312static int fuzzpos IBSS_ATTR = 0; 313 314// 315// Framebuffer postprocessing. 316// Creates a fuzzy image by copying pixels 317// from adjacent ones to left and right. 318// Used with an all black colormap, this 319// could create the SHADOW effect, 320// i.e. spectres and invisible players. 321// 322 323void R_DrawFuzzColumn(void) 324{ 325 int count; 326 byte *dest; 327 fixed_t frac; 328 fixed_t fracstep; 329 330 // Adjust borders. Low... 331 if (!dc_yl) 332 dc_yl = 1; 333 334 // .. and high. 335 if (dc_yh == viewheight-1) 336 dc_yh = viewheight - 2; 337 338 count = dc_yh - dc_yl; 339 340 // Zero length. 341 if (count < 0) 342 return; 343 344#ifdef RANGECHECK 345 346 if ((unsigned) dc_x >= (unsigned)SCREENWIDTH 347 || dc_yl < 0 348 || (unsigned)dc_yh >= (unsigned)SCREENHEIGHT) 349 I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); 350#endif 351 352 // Keep till detailshift bug in blocky mode fixed, 353 // or blocky mode removed. 354 355 // Does not work with blocky mode. 356 dest = topleft + dc_yl*SCREENWIDTH + dc_x; 357 358 // Looks familiar. 359 fracstep = dc_iscale; 360 frac = dc_texturemid + (dc_yl-centery)*fracstep; 361 362 // Looks like an attempt at dithering, 363 // using the colormap #6 (of 0-31, a bit brighter than average). 364 365 do 366 { 367 // Lookup framebuffer, and retrieve 368 // a pixel that is either one column 369 // left or right of the current one. 370 // Add index from colormap to index. 371 // killough 3/20/98: use fullcolormap instead of colormaps 372 373 *dest = fullcolormap[6*256+dest[fuzzoffset[fuzzpos]]]; 374 375 // Some varying invisibility effects can be gotten by playing // phares 376 // with this logic. For example, try // phares 377 // // phares 378 // *dest = fullcolormap[0*256+dest[FUZZOFF]]; // phares 379 380 // Clamp table lookup index. 381 if (++fuzzpos == FUZZTABLE) 382 fuzzpos = 0; 383 384 dest += SCREENWIDTH; 385 386 frac += fracstep; 387 } 388 while (count--); 389} 390 391// 392// R_DrawTranslatedColumn 393// Used to draw player sprites 394// with the green colorramp mapped to others. 395// Could be used with different translation 396// tables, e.g. the lighter colored version 397// of the BaronOfHell, the HellKnight, uses 398// identical sprites, kinda brightened up. 399// 400 401byte *dc_translation, *translationtables; 402 403void R_DrawTranslatedColumn (void) 404{ 405 int count; 406 byte *dest; 407 fixed_t frac; 408 fixed_t fracstep; 409 410 count = dc_yh - dc_yl; 411 if (count < 0) 412 return; 413 414#ifdef RANGECHECK 415 416 if ((unsigned)dc_x >= (unsigned)SCREENWIDTH 417 || dc_yl < 0 418 || (unsigned)dc_yh >= (unsigned)SCREENHEIGHT) 419 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); 420#endif 421 422 // FIXME. As above. 423 dest = topleft + dc_yl*SCREENWIDTH + dc_x; 424 425 // Looks familiar. 426 fracstep = dc_iscale; 427 frac = dc_texturemid + (dc_yl-centery)*fracstep; 428 429 // Here we do an additional index re-mapping. 430 do 431 { 432 // Translation tables are used 433 // to map certain colorramps to other ones, 434 // used with PLAY sprites. 435 // Thus the "green" ramp of the player 0 sprite 436 // is mapped to gray, red, black/indigo. 437 438 *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; 439 dest += SCREENWIDTH; 440 441 frac += fracstep; 442 } 443 while (count--); 444} 445 446// 447// R_InitTranslationTables 448// Creates the translation tables to map 449// the green color ramp to gray, brown, red. 450// Assumes a given structure of the PLAYPAL. 451// Could be read from a lump instead. 452// 453 454byte playernumtotrans[MAXPLAYERS]; 455extern lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ]; 456 457void R_InitTranslationTables (void) 458{ 459 int i, j; 460#define MAXTRANS 3 461 462 byte transtocolour[MAXTRANS]; 463 464 // killough 5/2/98: 465 // Remove dependency of colormaps aligned on 256-byte boundary 466 467 if (translationtables == NULL) // CPhipps - allow multiple calls 468 translationtables = Z_Malloc(256*MAXTRANS, PU_STATIC, 0); 469 470 for (i=0; i<MAXTRANS; i++) 471 transtocolour[i] = 255; 472 473 for (i=0; i<MAXPLAYERS; i++) 474 { 475 byte wantcolour = mapcolor_plyr[i]; 476 playernumtotrans[i] = 0; 477 if (wantcolour != 0x70) // Not green, would like translation 478 for (j=0; j<MAXTRANS; j++) 479 if (transtocolour[j] == 255) 480 { 481 transtocolour[j] = wantcolour; 482 playernumtotrans[i] = j+1; 483 break; 484 } 485 } 486 487 // translate just the 16 green colors 488 for (i=0; i<256; i++) 489 if (i >= 0x70 && i<= 0x7f) 490 { 491 // CPhipps - configurable player colours 492 translationtables[i] = colormaps[0][((i&0xf)<<9) + transtocolour[0]]; 493 translationtables[i+256] = colormaps[0][((i&0xf)<<9) + transtocolour[1]]; 494 translationtables[i+512] = colormaps[0][((i&0xf)<<9) + transtocolour[2]]; 495 } 496 else // Keep all other colors as is. 497 translationtables[i]=translationtables[i+256]=translationtables[i+512]=i; 498} 499 500// 501// R_DrawSpan 502// With DOOM style restrictions on view orientation, 503// the floors and ceilings consist of horizontal slices 504// or spans with constant z depth. 505// However, rotation around the world z axis is possible, 506// thus this mapping, while simpler and faster than 507// perspective correct texture mapping, has to traverse 508// the texture at an angle in all but a few cases. 509// In consequence, flats are not stored by column (like walls), 510// and the inner loop has to step in texture space u and v. 511// 512 513int ds_y IBSS_ATTR; 514int ds_x1 IBSS_ATTR; 515int ds_x2 IBSS_ATTR; 516 517lighttable_t *ds_colormap IBSS_ATTR; 518 519fixed_t ds_xfrac IBSS_ATTR; 520fixed_t ds_yfrac IBSS_ATTR; 521fixed_t ds_xstep IBSS_ATTR; 522fixed_t ds_ystep IBSS_ATTR; 523 524// start of a 64*64 tile image 525byte *ds_source IBSS_ATTR; 526 527void R_DrawSpan (void) 528{ 529#ifdef CPU_COLDFIRE 530 // only slightly faster 531 asm volatile ( 532 "tst %[count] \n" 533 "beq endspanloop \n" 534 "clr.l %%d4 \n" 535 "spanloop: \n" 536 "move.l %[xfrac], %%d1 \n" 537 "swap %%d1 \n" 538 "and.l #63,%%d1 \n" 539 "move.l %[yfrac], %%d2 \n" 540 "lsr.l %[ten],%%d2 \n" 541 "and.l #4032,%%d2 \n" 542 "or.l %%d2, %%d1 \n" 543 "move.b (%[source], %%d1), %%d4 \n" 544 "add.l %[ds_xstep], %[xfrac] \n" 545 "add.l %[ds_ystep], %[yfrac] \n" 546 "move.b (%[colormap],%%d4.l), (%[dest])+ \n" 547 "subq.l #1, %[count] \n" 548 "bne spanloop \n" 549 "endspanloop: \n" 550 : /* outputs */ 551 : /* inputs */ 552 [ten] "d"(10), 553 [count] "d" (ds_x2-ds_x1+1), 554 [xfrac] "a" (ds_xfrac), 555 [yfrac] "a" (ds_yfrac), 556 [source] "a" (ds_source), 557 [colormap] "a" (ds_colormap), 558 [dest] "a" (topleft+ds_y*SCREENWIDTH +ds_x1), 559 [ds_xstep] "d" (ds_xstep), 560 [ds_ystep] "d" (ds_ystep) 561 : /* clobbers */ 562 "d1", "d2", "d4" 563 ); 564#else 565 register unsigned count = ds_x2 - ds_x1 + 1,xfrac = ds_xfrac,yfrac = ds_yfrac; 566 567 register byte *source = ds_source; 568 register byte *colormap = ds_colormap; 569 register byte *dest = topleft + ds_y*SCREENWIDTH + ds_x1; 570 571 while (count) 572 { 573 register unsigned xtemp = xfrac >> 16; 574 register unsigned ytemp = yfrac >> 10; 575 register unsigned spot; 576 ytemp &= 4032; 577 xtemp &= 63; 578 spot = xtemp | ytemp; 579 xfrac += ds_xstep; 580 yfrac += ds_ystep; 581 *dest++ = colormap[source[spot]]; 582 count--; 583 } 584#endif 585} 586 587// 588// R_InitBuffer 589// Creats lookup tables that avoid 590// multiplies and other hazzles 591// for getting the framebuffer address 592// of a pixel to draw. 593// 594 595void R_InitBuffer(int width, int height) 596{ 597 int i=0; 598 // Handle resize, 599 // e.g. smaller view windows 600 // with border and/or status bar. 601 602 viewwindowx = (SCREENWIDTH-width) >> 1; 603 604 // Same with base row offset. 605 606 viewwindowy = width==SCREENWIDTH ? 0 : (SCREENHEIGHT-(ST_SCALED_HEIGHT-1)-height)>>1; 607 608 topleft = d_screens[0] + viewwindowy*SCREENWIDTH + viewwindowx; 609 610 // Preclaculate all row offsets. 611 // CPhipps - merge viewwindowx into here 612 for (i=0; i<FUZZTABLE; i++) 613 fuzzoffset[i] = fuzzoffset_org[i]*SCREENWIDTH; 614} 615 616 617// 618// R_FillBackScreen 619// Fills the back screen with a pattern 620// for variable screen sizes 621// Also draws a beveled edge. 622// 623// CPhipps - patch drawing updated 624 625void R_FillBackScreen (void) 626{ 627 int x,y; 628 629 if (scaledviewwidth == SCREENWIDTH) 630 return; 631 632 V_DrawBackground(gamemode == commercial ? "GRNROCK" : "FLOOR7_2", 1); 633 634 for (x=0 ; x<scaledviewwidth ; x+=8) 635 V_DrawNamePatch(viewwindowx+x,viewwindowy-8,1,"brdr_t", CR_DEFAULT, VPT_NONE); 636 637 for (x=0 ; x<scaledviewwidth ; x+=8) 638 V_DrawNamePatch(viewwindowx+x,viewwindowy+viewheight,1,"brdr_b", CR_DEFAULT, VPT_NONE); 639 640 for (y=0 ; y<viewheight ; y+=8) 641 V_DrawNamePatch(viewwindowx-8,viewwindowy+y,1,"brdr_l", CR_DEFAULT, VPT_NONE); 642 643 for (y=0 ; y<viewheight ; y+=8) 644 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+y,1,"brdr_r", CR_DEFAULT, VPT_NONE); 645 646 // Draw beveled edge. 647 V_DrawNamePatch(viewwindowx-8,viewwindowy-8,1,"brdr_tl", CR_DEFAULT, VPT_NONE); 648 649 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy-8,1,"brdr_tr", CR_DEFAULT, VPT_NONE); 650 651 V_DrawNamePatch(viewwindowx-8,viewwindowy+viewheight,1,"brdr_bl", CR_DEFAULT, VPT_NONE); 652 653 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+viewheight,1,"brdr_br", CR_DEFAULT, VPT_NONE); 654} 655 656// 657// Copy a screen buffer. 658// 659 660void R_VideoErase(unsigned ofs, int count) 661{ 662 memcpy(d_screens[0]+ofs, d_screens[1]+ofs, count); // LFB copy. 663} 664 665// 666// R_DrawViewBorder 667// Draws the border around the view 668// for different size windows? 669// 670 671void R_DrawViewBorder(void) 672{ 673 int top, side, ofs, i; 674 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM) 675 int side2; 676 677 // proff/nicolas 09/20/98: Removed for high-res 678 // if (scaledviewwidth == SCREENWIDTH) 679 // return; 680 681 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM) 682 if ((SCREENHEIGHT != viewheight) || 683 ((automapmode & am_active) && ! (automapmode & am_overlay))) 684 { 685 ofs = ( SCREENHEIGHT - ST_SCALED_HEIGHT ) * SCREENWIDTH; 686 side= ( SCREENWIDTH - ST_SCALED_WIDTH ) / 2; 687 side2 = side * 2; 688 689 R_VideoErase ( ofs, side ); 690 691 ofs += ( SCREENWIDTH - side ); 692 for ( i = 1; i < ST_SCALED_HEIGHT; i++ ) 693 { 694 R_VideoErase ( ofs, side2 ); 695 ofs += SCREENWIDTH; 696 } 697 698 R_VideoErase ( ofs, side ); 699 } 700 701 if ( viewheight >= ( SCREENHEIGHT - ST_SCALED_HEIGHT )) 702 return; // if high-res, don't go any further! 703 704 top = ((SCREENHEIGHT-ST_SCALED_HEIGHT)-viewheight)/2; 705 side = (SCREENWIDTH-scaledviewwidth)/2; 706 707 // copy top and one line of left side 708 R_VideoErase (0, top*SCREENWIDTH+side); 709 710 // copy one line of right side and bottom 711 ofs = (viewheight+top)*SCREENWIDTH-side; 712 R_VideoErase (ofs, top*SCREENWIDTH+side); 713 714 // copy sides using wraparound 715 ofs = top*SCREENWIDTH + SCREENWIDTH-side; 716 side <<= 1; 717 718 for (i=1 ; i<viewheight ; i++) 719 { 720 R_VideoErase (ofs, side); 721 ofs += SCREENWIDTH; 722 } 723}