home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #2 / amigaacscoverdisc1998-021998.iso / games / doom / source / linuxdoom-1.10 / r_draw.c < prev    next >
C/C++ Source or Header  |  1997-12-22  |  19KB  |  878 lines

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