A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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}