Subversion Repositories Kolibri OS

Rev

Rev 298 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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. #include "doomtype.h"
  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. {
  107.     int                 count;
  108.     byte*               dest;
  109.     fixed_t             frac;
  110.     fixed_t             fracstep;        
  111.  
  112.     count = dc_yh - dc_yl;
  113.  
  114.     // Zero length, column does not exceed a pixel.
  115.     if (count < 0)
  116.         return;
  117.                                  
  118. #ifdef RANGECHECK
  119.     if ((unsigned)dc_x >= SCREENWIDTH
  120.         || dc_yl < 0
  121.         || dc_yh >= SCREENHEIGHT)
  122.         I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
  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.     {
  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.        
  147.     } while (count--);
  148. }
  149.  
  150.  
  151.  
  152. // UNUSED.
  153. // Loop unrolled.
  154. #if 0
  155. void R_DrawColumn (void)
  156. {
  157.     int                 count;
  158.     byte*               source;
  159.     byte*               dest;
  160.     byte*               colormap;
  161.    
  162.     unsigned            frac;
  163.     unsigned            fracstep;
  164.     unsigned            fracstep2;
  165.     unsigned            fracstep3;
  166.     unsigned            fracstep4;      
  167.  
  168.     count = dc_yh - dc_yl + 1;
  169.  
  170.     source = dc_source;
  171.     colormap = dc_colormap;              
  172.     dest = ylookup[dc_yl] + columnofs[dc_x];  
  173.          
  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;
  180.        
  181.     while (count >= 8)
  182.     {
  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;
  189.  
  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]];
  194.  
  195.         frac += fracstep4;
  196.         dest += SCREENWIDTH*8;
  197.         count -= 8;
  198.     }
  199.        
  200.     while (count > 0)
  201.     {
  202.         *dest = colormap[source[frac>>25]];
  203.         dest += SCREENWIDTH;
  204.         frac += fracstep;
  205.         count--;
  206.     }
  207. }
  208. #endif
  209.  
  210.  
  211. void R_DrawColumnLow (void)
  212. {
  213.     int                 count;
  214.     byte*               dest;
  215.     byte*               dest2;
  216.     fixed_t             frac;
  217.     fixed_t             fracstep;        
  218.  
  219.     count = dc_yh - dc_yl;
  220.  
  221.     // Zero length.
  222.     if (count < 0)
  223.         return;
  224.                                  
  225. #ifdef RANGECHECK
  226.     if ((unsigned)dc_x >= SCREENWIDTH
  227.         || dc_yl < 0
  228.         || dc_yh >= SCREENHEIGHT)
  229.     {
  230.        
  231.         I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
  232.     }
  233.     //  dccount++;
  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.     {
  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;
  251.  
  252.     } while (count--);
  253. }
  254.  
  255.  
  256. //
  257. // Spectre/Invisibility.
  258. //
  259. #define FUZZTABLE               50
  260. #define FUZZOFF (SCREENWIDTH)
  261.  
  262.  
  263. int     fuzzoffset[FUZZTABLE] =
  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.  
  274. int     fuzzpos = 0;
  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. {
  287.     int                 count;
  288.     byte*               dest;
  289.     fixed_t             frac;
  290.     fixed_t             fracstep;        
  291.  
  292.     // Adjust borders. Low...
  293.     if (!dc_yl)
  294.         dc_yl = 1;
  295.  
  296.     // .. and high.
  297.     if (dc_yh == viewheight-1)
  298.         dc_yh = viewheight - 2;
  299.                  
  300.     count = dc_yh - dc_yl;
  301.  
  302.     // Zero length.
  303.     if (count < 0)
  304.         return;
  305.  
  306.    
  307. #ifdef RANGECHECK
  308.     if ((unsigned)dc_x >= SCREENWIDTH
  309.         || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  310.     {
  311.         I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  312.                  dc_yl, dc_yh, dc_x);
  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.     {
  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);
  333.     }
  334.     else
  335.     {
  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);
  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.     {
  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]]];
  359.  
  360.         // Clamp table lookup index.
  361.         if (++fuzzpos == FUZZTABLE)
  362.             fuzzpos = 0;
  363.        
  364.         dest += SCREENWIDTH;
  365.  
  366.         frac += fracstep;
  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. //
  382. byte*   dc_translation;
  383. byte*   translationtables;
  384.  
  385. void R_DrawTranslatedColumn (void)
  386. {
  387.     int                 count;
  388.     byte*               dest;
  389.     fixed_t             frac;
  390.     fixed_t             fracstep;        
  391.  
  392.     count = dc_yh - dc_yl;
  393.     if (count < 0)
  394.         return;
  395.                                  
  396. #ifdef RANGECHECK
  397.     if ((unsigned)dc_x >= SCREENWIDTH
  398.         || dc_yl < 0
  399.         || dc_yh >= SCREENHEIGHT)
  400.     {
  401.         I_Error ( "R_DrawColumn: %i to %i at %i",
  402.                   dc_yl, dc_yh, dc_x);
  403.     }
  404.    
  405. #endif
  406.  
  407.  
  408.     // WATCOM VGA specific.
  409.     /* Keep for fixing.
  410.     if (detailshift)
  411.     {
  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);
  418.     }
  419.     else
  420.     {
  421.         outp (SC_INDEX+1,1<<(dc_x&3));
  422.  
  423.         dest = destview + dc_yl*80 + (dc_x>>2);
  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.     {
  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;
  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. {
  461.     int         i;
  462.        
  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.     {
  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.         }
  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. //
  500. int                     ds_y;
  501. int                     ds_x1;
  502. int                     ds_x2;
  503.  
  504. lighttable_t*           ds_colormap;
  505.  
  506. fixed_t                 ds_xfrac;
  507. fixed_t                 ds_yfrac;
  508. fixed_t                 ds_xstep;
  509. fixed_t                 ds_ystep;
  510.  
  511. // start of a 64*64 tile image
  512. byte*                   ds_source;      
  513.  
  514. // just for profiling
  515. int                     dscount;
  516.  
  517.  
  518. //
  519. // Draws the actual span.
  520. void R_DrawSpan (void)
  521. {
  522.     fixed_t             xfrac;
  523.     fixed_t             yfrac;
  524.     byte*               dest;
  525.     int                 count;
  526.     int                 spot;
  527.          
  528. #ifdef RANGECHECK
  529.     if (ds_x2 < ds_x1
  530.         || ds_x1<0
  531.         || ds_x2>=SCREENWIDTH  
  532.         || (unsigned)ds_y>SCREENHEIGHT)
  533.     {
  534.         I_Error( "R_DrawSpan: %i to %i at %i",
  535.                  ds_x1,ds_x2,ds_y);
  536.     }
  537. //      dscount++;
  538. #endif
  539.  
  540.    
  541.     xfrac = ds_xfrac;
  542.     yfrac = ds_yfrac;
  543.          
  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.     {
  551.         // Current texture index in u,v.
  552.         spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  553.  
  554.         // Lookup pixel from flat texture tile,
  555.         //  re-index using light/colormap.
  556.         *dest++ = ds_colormap[ds_source[spot]];
  557.  
  558.         // Next step in u,v.
  559.         xfrac += ds_xstep;
  560.         yfrac += ds_ystep;
  561.        
  562.     } while (count--);
  563. }
  564.  
  565.  
  566.  
  567. // UNUSED.
  568. // Loop unrolled by 4.
  569. #if 0
  570. void R_DrawSpan (void)
  571. {
  572.     unsigned    position, step;
  573.  
  574.     byte*       source;
  575.     byte*       colormap;
  576.     byte*       dest;
  577.    
  578.     unsigned    count;
  579.     usingned    spot;
  580.     unsigned    value;
  581.     unsigned    temp;
  582.     unsigned    xtemp;
  583.     unsigned    ytemp;
  584.                
  585.     position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
  586.     step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
  587.                
  588.     source = ds_source;
  589.     colormap = ds_colormap;
  590.     dest = ylookup[ds_y] + columnofs[ds_x1];    
  591.     count = ds_x2 - ds_x1 + 1;
  592.        
  593.     while (count >= 4)
  594.     {
  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]];
  601.  
  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;
  625.     }
  626.     while (count > 0)
  627.     {
  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--;
  635.     }
  636. }
  637. #endif
  638.  
  639.  
  640. //
  641. // Again..
  642. //
  643. void R_DrawSpanLow (void)
  644. {
  645.     fixed_t             xfrac;
  646.     fixed_t             yfrac;
  647.     byte*               dest;
  648.     int                 count;
  649.     int                 spot;
  650.          
  651. #ifdef RANGECHECK
  652.     if (ds_x2 < ds_x1
  653.         || ds_x1<0
  654.         || ds_x2>=SCREENWIDTH  
  655.         || (unsigned)ds_y>SCREENHEIGHT)
  656.     {
  657.         I_Error( "R_DrawSpan: %i to %i at %i",
  658.                  ds_x1,ds_x2,ds_y);
  659.     }
  660. //      dscount++;
  661. #endif
  662.          
  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.     {
  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;
  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
  697. ( int           width,
  698.   int           height )
  699. {
  700.     int         i;
  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<width ; i++)
  709.         columnofs[i] = viewwindowx + i;
  710.  
  711.     // Samw with base row offset.
  712.     if (width == SCREENWIDTH)
  713.         viewwindowy = 0;
  714.     else
  715.         viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
  716.  
  717.     // Preclaculate all row offsets.
  718.     for (i=0 ; i<height ; i++)
  719.         ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
  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. {
  733.     byte*       src;
  734.     byte*       dest;
  735.     int         x;
  736.     int         y;
  737.     patch_t*    patch;
  738.  
  739.     // DOOM border patch.
  740.     char        name1[] = "FLOOR7_2";
  741.  
  742.     // DOOM II border patch.
  743.     char        name2[] = "GRNROCK";    
  744.  
  745.     char*       name;
  746.        
  747.     if (scaledviewwidth == 320)
  748.         return;
  749.        
  750.     if ( gamemode == commercial)
  751.         name = name2;
  752.     else
  753.         name = name1;
  754.    
  755.     src = W_CacheLumpName (name, PU_CACHE);
  756.     dest = screens[1];
  757.          
  758.     for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++)
  759.     {
  760.         for (x=0 ; x<SCREENWIDTH/64 ; x++)
  761.         {
  762.             memcpy (dest, src+((y&63)<<6), 64);
  763.             dest += 64;
  764.         }
  765.  
  766.         if (SCREENWIDTH&63)
  767.         {
  768.             memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
  769.             dest += (SCREENWIDTH&63);
  770.         }
  771.     }
  772.        
  773.     patch = W_CacheLumpName ("brdr_t",PU_CACHE);
  774.  
  775.     for (x=0 ; x<scaledviewwidth ; x+=8)
  776.         V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
  777.     patch = W_CacheLumpName ("brdr_b",PU_CACHE);
  778.  
  779.     for (x=0 ; x<scaledviewwidth ; x+=8)
  780.         V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
  781.     patch = W_CacheLumpName ("brdr_l",PU_CACHE);
  782.  
  783.     for (y=0 ; y<viewheight ; y+=8)
  784.         V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
  785.     patch = W_CacheLumpName ("brdr_r",PU_CACHE);
  786.  
  787.     for (y=0 ; y<viewheight ; y+=8)
  788.         V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
  789.  
  790.  
  791.     // Draw beveled edge.
  792.     V_DrawPatch (viewwindowx-8,
  793.                  viewwindowy-8,
  794.                  1,
  795.                  W_CacheLumpName ("brdr_tl",PU_CACHE));
  796.    
  797.     V_DrawPatch (viewwindowx+scaledviewwidth,
  798.                  viewwindowy-8,
  799.                  1,
  800.                  W_CacheLumpName ("brdr_tr",PU_CACHE));
  801.    
  802.     V_DrawPatch (viewwindowx-8,
  803.                  viewwindowy+viewheight,
  804.                  1,
  805.                  W_CacheLumpName ("brdr_bl",PU_CACHE));
  806.    
  807.     V_DrawPatch (viewwindowx+scaledviewwidth,
  808.                  viewwindowy+viewheight,
  809.                  1,
  810.                  W_CacheLumpName ("brdr_br",PU_CACHE));
  811. }
  812.  
  813.  
  814. //
  815. // Copy a screen buffer.
  816. //
  817. void
  818. R_VideoErase
  819. ( unsigned      ofs,
  820.   int           count )
  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
  838. ( int           x,
  839.   int           y,
  840.   int           width,
  841.   int           height );
  842.  
  843. void R_DrawViewBorder (void)
  844. {
  845.     int         top;
  846.     int         side;
  847.     int         ofs;
  848.     int         i;
  849.  
  850.     if (scaledviewwidth == SCREENWIDTH)
  851.         return;
  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<viewheight ; i++)
  868.     {
  869.         R_VideoErase (ofs, side);
  870.         ofs += SCREENWIDTH;
  871.     }
  872.  
  873.     // ?
  874.     V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT);
  875. }
  876.  
  877.  
  878.