Subversion Repositories Kolibri OS

Rev

Rev 298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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