Subversion Repositories Kolibri OS

Rev

Rev 9097 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. // WL_DRAW.C
  2.  
  3. #include "wl_def.h"
  4. #include <cstdio>
  5. #pragma hdrstop
  6.  
  7. #include "wl_cloudsky.h"
  8. #include "wl_atmos.h"
  9. #include "wl_shade.h"
  10.  
  11. /*
  12. =============================================================================
  13.  
  14.                                LOCAL CONSTANTS
  15.  
  16. =============================================================================
  17. */
  18.  
  19. // the door is the last picture before the sprites
  20. #define DOORWALL        (PMSpriteStart-8)
  21.  
  22. #define ACTORSIZE       0x4000
  23.  
  24. /*
  25. =============================================================================
  26.  
  27.                               GLOBAL VARIABLES
  28.  
  29. =============================================================================
  30. */
  31.  
  32. static byte *vbuf = NULL;
  33. unsigned vbufPitch = 0;
  34.  
  35. int32_t    lasttimecount;
  36. int32_t    frameon;
  37. boolean fpscounter;
  38.  
  39. int fps_frames=0, fps_time=0, fps=0;
  40.  
  41. int *wallheight;
  42. int min_wallheight;
  43.  
  44. //
  45. // math tables
  46. //
  47. short *pixelangle;
  48. int32_t finetangent[FINEANGLES/4];
  49. fixed sintable[ANGLES+ANGLES/4];
  50. fixed *costable = sintable+(ANGLES/4);
  51.  
  52. //
  53. // refresh variables
  54. //
  55. fixed   viewx,viewy;                    // the focal point
  56. short   viewangle;
  57. fixed   viewsin,viewcos;
  58.  
  59. void    TransformActor (objtype *ob);
  60. void    BuildTables (void);
  61. void    ClearScreen (void);
  62. int     CalcRotate (objtype *ob);
  63. void    DrawScaleds (void);
  64. void    CalcTics (void);
  65. void    ThreeDRefresh (void);
  66.  
  67.  
  68.  
  69. //
  70. // wall optimization variables
  71. //
  72. int     lastside;               // true for vertical
  73. int32_t    lastintercept;
  74. int     lasttilehit;
  75. int     lasttexture;
  76.  
  77. //
  78. // ray tracing variables
  79. //
  80. short    focaltx,focalty,viewtx,viewty;
  81. longword xpartialup,xpartialdown,ypartialup,ypartialdown;
  82.  
  83. short   midangle,angle;
  84.  
  85. word    tilehit;
  86. int     pixx;
  87.  
  88. short   xtile,ytile;
  89. short   xtilestep,ytilestep;
  90. int32_t    xintercept,yintercept;
  91. word    xstep,ystep;
  92. word    xspot,yspot;
  93. int     texdelta;
  94.  
  95. word horizwall[MAXWALLTILES],vertwall[MAXWALLTILES];
  96.  
  97.  
  98. /*
  99. ============================================================================
  100.  
  101.                            3 - D  DEFINITIONS
  102.  
  103. ============================================================================
  104. */
  105.  
  106. /*
  107. ========================
  108. =
  109. = TransformActor
  110. =
  111. = Takes paramaters:
  112. =   gx,gy               : globalx/globaly of point
  113. =
  114. = globals:
  115. =   viewx,viewy         : point of view
  116. =   viewcos,viewsin     : sin/cos of viewangle
  117. =   scale               : conversion from global value to screen value
  118. =
  119. = sets:
  120. =   screenx,transx,transy,screenheight: projected edge location and size
  121. =
  122. ========================
  123. */
  124.  
  125.  
  126. //
  127. // transform actor
  128. //
  129. void TransformActor (objtype *ob)
  130. {
  131.     fixed gx,gy,gxt,gyt,nx,ny;
  132.  
  133. //
  134. // translate point to view centered coordinates
  135. //
  136.     gx = ob->x-viewx;
  137.     gy = ob->y-viewy;
  138.  
  139. //
  140. // calculate newx
  141. //
  142.     gxt = FixedMul(gx,viewcos);
  143.     gyt = FixedMul(gy,viewsin);
  144.     nx = gxt-gyt-ACTORSIZE;         // fudge the shape forward a bit, because
  145.                                     // the midpoint could put parts of the shape
  146.                                     // into an adjacent wall
  147.  
  148. //
  149. // calculate newy
  150. //
  151.     gxt = FixedMul(gx,viewsin);
  152.     gyt = FixedMul(gy,viewcos);
  153.     ny = gyt+gxt;
  154.  
  155. //
  156. // calculate perspective ratio
  157. //
  158.     ob->transx = nx;
  159.     ob->transy = ny;
  160.  
  161.     if (nx<MINDIST)                 // too close, don't overflow the divide
  162.     {
  163.         ob->viewheight = 0;
  164.         return;
  165.     }
  166.  
  167.     ob->viewx = (word)(centerx + ny*scale/nx);
  168.  
  169. //
  170. // calculate height (heightnumerator/(nx>>8))
  171. //
  172.     ob->viewheight = (word)(heightnumerator/(nx>>8));
  173. }
  174.  
  175. //==========================================================================
  176.  
  177. /*
  178. ========================
  179. =
  180. = TransformTile
  181. =
  182. = Takes paramaters:
  183. =   tx,ty               : tile the object is centered in
  184. =
  185. = globals:
  186. =   viewx,viewy         : point of view
  187. =   viewcos,viewsin     : sin/cos of viewangle
  188. =   scale               : conversion from global value to screen value
  189. =
  190. = sets:
  191. =   screenx,transx,transy,screenheight: projected edge location and size
  192. =
  193. = Returns true if the tile is withing getting distance
  194. =
  195. ========================
  196. */
  197.  
  198. boolean TransformTile (int tx, int ty, short *dispx, short *dispheight)
  199. {
  200.     fixed gx,gy,gxt,gyt,nx,ny;
  201.  
  202. //
  203. // translate point to view centered coordinates
  204. //
  205.     gx = ((int32_t)tx<<TILESHIFT)+0x8000-viewx;
  206.     gy = ((int32_t)ty<<TILESHIFT)+0x8000-viewy;
  207.  
  208. //
  209. // calculate newx
  210. //
  211.     gxt = FixedMul(gx,viewcos);
  212.     gyt = FixedMul(gy,viewsin);
  213.     nx = gxt-gyt-0x2000;            // 0x2000 is size of object
  214.  
  215. //
  216. // calculate newy
  217. //
  218.     gxt = FixedMul(gx,viewsin);
  219.     gyt = FixedMul(gy,viewcos);
  220.     ny = gyt+gxt;
  221.  
  222.  
  223. //
  224. // calculate height / perspective ratio
  225. //
  226.     if (nx<MINDIST)                 // too close, don't overflow the divide
  227.         *dispheight = 0;
  228.     else
  229.     {
  230.         *dispx = (short)(centerx + ny*scale/nx);
  231.         *dispheight = (short)(heightnumerator/(nx>>8));
  232.     }
  233.  
  234. //
  235. // see if it should be grabbed
  236. //
  237.     if (nx<TILEGLOBAL && ny>-TILEGLOBAL/2 && ny<TILEGLOBAL/2)
  238.         return true;
  239.     else
  240.         return false;
  241. }
  242.  
  243. //==========================================================================
  244.  
  245. /*
  246. ====================
  247. =
  248. = CalcHeight
  249. =
  250. = Calculates the height of xintercept,yintercept from viewx,viewy
  251. =
  252. ====================
  253. */
  254.  
  255. int CalcHeight()
  256. {
  257.     fixed z = FixedMul(xintercept - viewx, viewcos)
  258.         - FixedMul(yintercept - viewy, viewsin);
  259.     if(z < MINDIST) z = MINDIST;
  260.     int height = heightnumerator / (z >> 8);
  261.     if(height < min_wallheight) min_wallheight = height;
  262.     return height;
  263. }
  264.  
  265. //==========================================================================
  266.  
  267. /*
  268. ===================
  269. =
  270. = ScalePost
  271. =
  272. ===================
  273. */
  274.  
  275. byte *postsource;
  276. int postx;
  277. int postwidth;
  278.  
  279. void ScalePost()
  280. {
  281.     int ywcount, yoffs, yw, yd, yendoffs;
  282.     byte col;
  283.  
  284. #ifdef USE_SHADING
  285.     byte *curshades = shadetable[GetShade(wallheight[postx])];
  286. #endif
  287.  
  288.     ywcount = yd = wallheight[postx] >> 3;
  289.     if(yd <= 0) yd = 100;
  290.  
  291.     yoffs = (viewheight / 2 - ywcount) * vbufPitch;
  292.     if(yoffs < 0) yoffs = 0;
  293.     yoffs += postx;
  294.  
  295.     yendoffs = viewheight / 2 + ywcount - 1;
  296.     yw=TEXTURESIZE-1;
  297.  
  298.     while(yendoffs >= viewheight)
  299.     {
  300.         ywcount -= TEXTURESIZE/2;
  301.         while(ywcount <= 0)
  302.         {
  303.             ywcount += yd;
  304.             yw--;
  305.         }
  306.         yendoffs--;
  307.     }
  308.     if(yw < 0) return;
  309.  
  310. #ifdef USE_SHADING
  311.     col = curshades[postsource[yw]];
  312. #else
  313.     col = postsource[yw];
  314. #endif
  315.     yendoffs = yendoffs * vbufPitch + postx;
  316.     while(yoffs <= yendoffs)
  317.     {
  318.         vbuf[yendoffs] = col;
  319.         ywcount -= TEXTURESIZE/2;
  320.         if(ywcount <= 0)
  321.         {
  322.             do
  323.             {
  324.                 ywcount += yd;
  325.                 yw--;
  326.             }
  327.             while(ywcount <= 0);
  328.             if(yw < 0) break;
  329. #ifdef USE_SHADING
  330.             col = curshades[postsource[yw]];
  331. #else
  332.             col = postsource[yw];
  333. #endif
  334.         }
  335.         yendoffs -= vbufPitch;
  336.     }
  337. }
  338.  
  339. void GlobalScalePost(byte *vidbuf, unsigned pitch)
  340. {
  341.     vbuf = vidbuf;
  342.     vbufPitch = pitch;
  343.     ScalePost();
  344. }
  345.  
  346. /*
  347. ====================
  348. =
  349. = HitVertWall
  350. =
  351. = tilehit bit 7 is 0, because it's not a door tile
  352. = if bit 6 is 1 and the adjacent tile is a door tile, use door side pic
  353. =
  354. ====================
  355. */
  356.  
  357. void HitVertWall (void)
  358. {
  359.     int wallpic;
  360.     int texture;
  361.  
  362.     texture = ((yintercept+texdelta)>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
  363.     if (xtilestep == -1)
  364.     {
  365.         texture = TEXTUREMASK-texture;
  366.         xintercept += TILEGLOBAL;
  367.     }
  368.  
  369.     if(lastside==1 && lastintercept==xtile && lasttilehit==tilehit && !(lasttilehit & 0x40))
  370.     {
  371.         if((pixx&3) && texture == lasttexture)
  372.         {
  373.             ScalePost();
  374.             postx = pixx;
  375.             wallheight[pixx] = wallheight[pixx-1];
  376.             return;
  377.         }
  378.         ScalePost();
  379.         wallheight[pixx] = CalcHeight();
  380.         postsource+=texture-lasttexture;
  381.         postwidth=1;
  382.         postx=pixx;
  383.         lasttexture=texture;
  384.         return;
  385.     }
  386.  
  387.     if(lastside!=-1) ScalePost();
  388.  
  389.     lastside=1;
  390.     lastintercept=xtile;
  391.     lasttilehit=tilehit;
  392.     lasttexture=texture;
  393.     wallheight[pixx] = CalcHeight();
  394.     postx = pixx;
  395.     postwidth = 1;
  396.  
  397.     if (tilehit & 0x40)
  398.     {                                                               // check for adjacent doors
  399.         ytile = (short)(yintercept>>TILESHIFT);
  400.         if ( tilemap[xtile-xtilestep][ytile]&0x80 )
  401.             wallpic = DOORWALL+3;
  402.         else
  403.             wallpic = vertwall[tilehit & ~0x40];
  404.     }
  405.     else
  406.         wallpic = vertwall[tilehit];
  407.  
  408.     postsource = PM_GetTexture(wallpic) + texture;
  409. }
  410.  
  411.  
  412. /*
  413. ====================
  414. =
  415. = HitHorizWall
  416. =
  417. = tilehit bit 7 is 0, because it's not a door tile
  418. = if bit 6 is 1 and the adjacent tile is a door tile, use door side pic
  419. =
  420. ====================
  421. */
  422.  
  423. void HitHorizWall (void)
  424. {
  425.     int wallpic;
  426.     int texture;
  427.  
  428.     texture = ((xintercept+texdelta)>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
  429.     if (ytilestep == -1)
  430.         yintercept += TILEGLOBAL;
  431.     else
  432.         texture = TEXTUREMASK-texture;
  433.  
  434.     if(lastside==0 && lastintercept==ytile && lasttilehit==tilehit && !(lasttilehit & 0x40))
  435.     {
  436.         if((pixx&3) && texture == lasttexture)
  437.         {
  438.             ScalePost();
  439.             postx=pixx;
  440.             wallheight[pixx] = wallheight[pixx-1];
  441.             return;
  442.         }
  443.         ScalePost();
  444.         wallheight[pixx] = CalcHeight();
  445.         postsource+=texture-lasttexture;
  446.         postwidth=1;
  447.         postx=pixx;
  448.         lasttexture=texture;
  449.         return;
  450.     }
  451.  
  452.     if(lastside!=-1) ScalePost();
  453.  
  454.     lastside=0;
  455.     lastintercept=ytile;
  456.     lasttilehit=tilehit;
  457.     lasttexture=texture;
  458.     wallheight[pixx] = CalcHeight();
  459.     postx = pixx;
  460.     postwidth = 1;
  461.  
  462.     if (tilehit & 0x40)
  463.     {                                                               // check for adjacent doors
  464.         xtile = (short)(xintercept>>TILESHIFT);
  465.         if ( tilemap[xtile][ytile-ytilestep]&0x80)
  466.             wallpic = DOORWALL+2;
  467.         else
  468.             wallpic = horizwall[tilehit & ~0x40];
  469.     }
  470.     else
  471.         wallpic = horizwall[tilehit];
  472.  
  473.     postsource = PM_GetTexture(wallpic) + texture;
  474. }
  475.  
  476. //==========================================================================
  477.  
  478. /*
  479. ====================
  480. =
  481. = HitHorizDoor
  482. =
  483. ====================
  484. */
  485.  
  486. void HitHorizDoor (void)
  487. {
  488.     int doorpage;
  489.     int doornum;
  490.     int texture;
  491.  
  492.     doornum = tilehit&0x7f;
  493.     texture = ((xintercept-doorposition[doornum])>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
  494.  
  495.     if(lasttilehit==tilehit)
  496.     {
  497.         if((pixx&3) && texture == lasttexture)
  498.         {
  499.             ScalePost();
  500.             postx=pixx;
  501.             wallheight[pixx] = wallheight[pixx-1];
  502.             return;
  503.         }
  504.         ScalePost();
  505.         wallheight[pixx] = CalcHeight();
  506.         postsource+=texture-lasttexture;
  507.         postwidth=1;
  508.         postx=pixx;
  509.         lasttexture=texture;
  510.         return;
  511.     }
  512.  
  513.     if(lastside!=-1) ScalePost();
  514.  
  515.     lastside=2;
  516.     lasttilehit=tilehit;
  517.     lasttexture=texture;
  518.     wallheight[pixx] = CalcHeight();
  519.     postx = pixx;
  520.     postwidth = 1;
  521.  
  522.     switch(doorobjlist[doornum].lock)
  523.     {
  524.         case dr_normal:
  525.             doorpage = DOORWALL;
  526.             break;
  527.         case dr_lock1:
  528.         case dr_lock2:
  529.         case dr_lock3:
  530.         case dr_lock4:
  531.             doorpage = DOORWALL+6;
  532.             break;
  533.         case dr_elevator:
  534.             doorpage = DOORWALL+4;
  535.             break;
  536.     }
  537.  
  538.     postsource = PM_GetTexture(doorpage) + texture;
  539. }
  540.  
  541. //==========================================================================
  542.  
  543. /*
  544. ====================
  545. =
  546. = HitVertDoor
  547. =
  548. ====================
  549. */
  550.  
  551. void HitVertDoor (void)
  552. {
  553.     int doorpage;
  554.     int doornum;
  555.     int texture;
  556.  
  557.     doornum = tilehit&0x7f;
  558.     texture = ((yintercept-doorposition[doornum])>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
  559.  
  560.     if(lasttilehit==tilehit)
  561.     {
  562.         if((pixx&3) && texture == lasttexture)
  563.         {
  564.             ScalePost();
  565.             postx=pixx;
  566.             wallheight[pixx] = wallheight[pixx-1];
  567.             return;
  568.         }
  569.         ScalePost();
  570.         wallheight[pixx] = CalcHeight();
  571.         postsource+=texture-lasttexture;
  572.         postwidth=1;
  573.         postx=pixx;
  574.         lasttexture=texture;
  575.         return;
  576.     }
  577.  
  578.     if(lastside!=-1) ScalePost();
  579.  
  580.     lastside=2;
  581.     lasttilehit=tilehit;
  582.     lasttexture=texture;
  583.     wallheight[pixx] = CalcHeight();
  584.     postx = pixx;
  585.     postwidth = 1;
  586.  
  587.     switch(doorobjlist[doornum].lock)
  588.     {
  589.         case dr_normal:
  590.             doorpage = DOORWALL+1;
  591.             break;
  592.         case dr_lock1:
  593.         case dr_lock2:
  594.         case dr_lock3:
  595.         case dr_lock4:
  596.             doorpage = DOORWALL+7;
  597.             break;
  598.         case dr_elevator:
  599.             doorpage = DOORWALL+5;
  600.             break;
  601.     }
  602.  
  603.     postsource = PM_GetTexture(doorpage) + texture;
  604. }
  605.  
  606. //==========================================================================
  607.  
  608. #define HitHorizBorder HitHorizWall
  609. #define HitVertBorder HitVertWall
  610.  
  611. //==========================================================================
  612.  
  613. byte vgaCeiling[]=
  614. {
  615. #ifndef SPEAR
  616.  0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0xbf,
  617.  0x4e,0x4e,0x4e,0x1d,0x8d,0x4e,0x1d,0x2d,0x1d,0x8d,
  618.  0x1d,0x1d,0x1d,0x1d,0x1d,0x2d,0xdd,0x1d,0x1d,0x98,
  619.  
  620.  0x1d,0x9d,0x2d,0xdd,0xdd,0x9d,0x2d,0x4d,0x1d,0xdd,
  621.  0x7d,0x1d,0x2d,0x2d,0xdd,0xd7,0x1d,0x1d,0x1d,0x2d,
  622.  0x1d,0x1d,0x1d,0x1d,0xdd,0xdd,0x7d,0xdd,0xdd,0xdd
  623. #else
  624.  0x6f,0x4f,0x1d,0xde,0xdf,0x2e,0x7f,0x9e,0xae,0x7f,
  625.  0x1d,0xde,0xdf,0xde,0xdf,0xde,0xe1,0xdc,0x2e,0x1d,0xdc
  626. #endif
  627. };
  628.  
  629. /*
  630. =====================
  631. =
  632. = VGAClearScreen
  633. =
  634. =====================
  635. */
  636.  
  637. void VGAClearScreen (void)
  638. {
  639.     byte ceiling=vgaCeiling[gamestate.episode*10+mapon];
  640.  
  641.     int y;
  642.     byte *ptr = vbuf;
  643. #ifdef USE_SHADING
  644.     for(y = 0; y < viewheight / 2; y++, ptr += vbufPitch)
  645.         memset(ptr, shadetable[GetShade((viewheight / 2 - y) << 3)][ceiling], viewwidth);
  646.     for(; y < viewheight; y++, ptr += vbufPitch)
  647.         memset(ptr, shadetable[GetShade((y - viewheight / 2) << 3)][0x19], viewwidth);
  648. #else
  649.     for(y = 0; y < viewheight / 2; y++, ptr += vbufPitch)
  650.         memset(ptr, ceiling, viewwidth);
  651.     for(; y < viewheight; y++, ptr += vbufPitch)
  652.         memset(ptr, 0x19, viewwidth);
  653. #endif
  654. }
  655.  
  656. //==========================================================================
  657.  
  658. /*
  659. =====================
  660. =
  661. = CalcRotate
  662. =
  663. =====================
  664. */
  665.  
  666. int CalcRotate (objtype *ob)
  667. {
  668.     int angle, viewangle;
  669.  
  670.     // this isn't exactly correct, as it should vary by a trig value,
  671.     // but it is close enough with only eight rotations
  672.  
  673.     viewangle = player->angle + (centerx - ob->viewx)/8;
  674.  
  675.     if (ob->obclass == rocketobj || ob->obclass == hrocketobj)
  676.         angle = (viewangle-180) - ob->angle;
  677.     else
  678.         angle = (viewangle-180) - dirangle[ob->dir];
  679.  
  680.     angle+=ANGLES/16;
  681.     while (angle>=ANGLES)
  682.         angle-=ANGLES;
  683.     while (angle<0)
  684.         angle+=ANGLES;
  685.  
  686.     if (ob->state->rotate == 2)             // 2 rotation pain frame
  687.         return 0;               // pain with shooting frame bugfix
  688.  
  689.     return angle/(ANGLES/8);
  690. }
  691.  
  692. void ScaleShape (int xcenter, int shapenum, unsigned height, uint32_t flags)
  693. {
  694.     t_compshape *shape;
  695.     unsigned scale,pixheight;
  696.     unsigned starty,endy;
  697.     word *cmdptr;
  698.     byte *cline;
  699.     byte *line;
  700.     byte *vmem;
  701.     int actx,i,upperedge;
  702.     short newstart;
  703.     int scrstarty,screndy,lpix,rpix,pixcnt,ycnt;
  704.     unsigned j;
  705.     byte col;
  706.  
  707. #ifdef USE_SHADING
  708.     byte *curshades;
  709.     if(flags & FL_FULLBRIGHT)
  710.         curshades = shadetable[0];
  711.     else
  712.         curshades = shadetable[GetShade(height)];
  713. #endif
  714.  
  715.     shape = (t_compshape *) PM_GetSprite(shapenum);
  716.  
  717.     scale=height>>3;                 // low three bits are fractional
  718.     if(!scale) return;   // too close or far away
  719.  
  720.     pixheight=scale*SPRITESCALEFACTOR;
  721.     actx=xcenter-scale;
  722.     upperedge=viewheight/2-scale;
  723.  
  724.     cmdptr=(word *) shape->dataofs;
  725.  
  726.     for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++)
  727.     {
  728.         lpix=rpix;
  729.         if(lpix>=viewwidth) break;
  730.         pixcnt+=pixheight;
  731.         rpix=(pixcnt>>6)+actx;
  732.         if(lpix!=rpix && rpix>0)
  733.         {
  734.             if(lpix<0) lpix=0;
  735.             if(rpix>viewwidth) rpix=viewwidth,i=shape->rightpix+1;
  736.             cline=(byte *)shape + *cmdptr;
  737.             while(lpix<rpix)
  738.             {
  739.                 if(wallheight[lpix]<=(int)height)
  740.                 {
  741.                     line=cline;
  742.                     while((endy = READWORD(line)) != 0)
  743.                     {
  744.                         endy >>= 1;
  745.                         newstart = READWORD(line);
  746.                         starty = READWORD(line) >> 1;
  747.                         j=starty;
  748.                         ycnt=j*pixheight;
  749.                         screndy=(ycnt>>6)+upperedge;
  750.                         if(screndy<0) vmem=vbuf+lpix;
  751.                         else vmem=vbuf+screndy*vbufPitch+lpix;
  752.                         for(;j<endy;j++)
  753.                         {
  754.                             scrstarty=screndy;
  755.                             ycnt+=pixheight;
  756.                             screndy=(ycnt>>6)+upperedge;
  757.                             if(scrstarty!=screndy && screndy>0)
  758.                             {
  759. #ifdef USE_SHADING
  760.                                 col=curshades[((byte *)shape)[newstart+j]];
  761. #else
  762.                                 col=((byte *)shape)[newstart+j];
  763. #endif
  764.                                 if(scrstarty<0) scrstarty=0;
  765.                                 if(screndy>viewheight) screndy=viewheight,j=endy;
  766.  
  767.                                 while(scrstarty<screndy)
  768.                                 {
  769.                                     *vmem=col;
  770.                                     vmem+=vbufPitch;
  771.                                     scrstarty++;
  772.                                 }
  773.                             }
  774.                         }
  775.                     }
  776.                 }
  777.                 lpix++;
  778.             }
  779.         }
  780.     }
  781. }
  782.  
  783. void SimpleScaleShape (int xcenter, int shapenum, unsigned height)
  784. {
  785.     t_compshape   *shape;
  786.     unsigned scale,pixheight;
  787.     unsigned starty,endy;
  788.     word *cmdptr;
  789.     byte *cline;
  790.     byte *line;
  791.     int actx,i,upperedge;
  792.     short newstart;
  793.     int scrstarty,screndy,lpix,rpix,pixcnt,ycnt;
  794.     unsigned j;
  795.     byte col;
  796.     byte *vmem;
  797.  
  798.     shape = (t_compshape *) PM_GetSprite(shapenum);
  799.  
  800.     scale=height>>1;
  801.     pixheight=scale*SPRITESCALEFACTOR;
  802.     actx=xcenter-scale;
  803.     upperedge=viewheight/2-scale;
  804.  
  805.     cmdptr=shape->dataofs;
  806.  
  807.     for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++)
  808.     {
  809.         lpix=rpix;
  810.         if(lpix>=viewwidth) break;
  811.         pixcnt+=pixheight;
  812.         rpix=(pixcnt>>6)+actx;
  813.         if(lpix!=rpix && rpix>0)
  814.         {
  815.             if(lpix<0) lpix=0;
  816.             if(rpix>viewwidth) rpix=viewwidth,i=shape->rightpix+1;
  817.             cline = (byte *)shape + *cmdptr;
  818.             while(lpix<rpix)
  819.             {
  820.                 line=cline;
  821.                 while((endy = READWORD(line)) != 0)
  822.                 {
  823.                     endy >>= 1;
  824.                     newstart = READWORD(line);
  825.                     starty = READWORD(line) >> 1;
  826.                     j=starty;
  827.                     ycnt=j*pixheight;
  828.                     screndy=(ycnt>>6)+upperedge;
  829.                     if(screndy<0) vmem=vbuf+lpix;
  830.                     else vmem=vbuf+screndy*vbufPitch+lpix;
  831.                     for(;j<endy;j++)
  832.                     {
  833.                         scrstarty=screndy;
  834.                         ycnt+=pixheight;
  835.                         screndy=(ycnt>>6)+upperedge;
  836.                         if(scrstarty!=screndy && screndy>0)
  837.                         {
  838.                             col=((byte *)shape)[newstart+j];
  839.                             if(scrstarty<0) scrstarty=0;
  840.                             if(screndy>viewheight) screndy=viewheight,j=endy;
  841.  
  842.                             while(scrstarty<screndy)
  843.                             {
  844.                                 *vmem=col;
  845.                                 vmem+=vbufPitch;
  846.                                 scrstarty++;
  847.                             }
  848.                         }
  849.                     }
  850.                 }
  851.                 lpix++;
  852.             }
  853.         }
  854.     }
  855. }
  856.  
  857. /*
  858. =====================
  859. =
  860. = DrawScaleds
  861. =
  862. = Draws all objects that are visable
  863. =
  864. =====================
  865. */
  866.  
  867. #define MAXVISABLE 250
  868.  
  869. typedef struct
  870. {
  871.     short      viewx,
  872.                viewheight,
  873.                shapenum;
  874.     short      flags;          // this must be changed to uint32_t, when you
  875.                                // you need more than 16-flags for drawing
  876. #ifdef USE_DIR3DSPR
  877.     statobj_t *transsprite;
  878. #endif
  879. } visobj_t;
  880.  
  881. visobj_t vislist[MAXVISABLE];
  882. visobj_t *visptr,*visstep,*farthest;
  883.  
  884. void DrawScaleds (void)
  885. {
  886.     int      i,least,numvisable,height;
  887.     byte     *tilespot,*visspot;
  888.     unsigned spotloc;
  889.  
  890.     statobj_t *statptr;
  891.     objtype   *obj;
  892.  
  893.     visptr = &vislist[0];
  894.  
  895. //
  896. // place static objects
  897. //
  898.     for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++)
  899.     {
  900.         if ((visptr->shapenum = statptr->shapenum) == -1)
  901.             continue;                                               // object has been deleted
  902.  
  903.         if (!*statptr->visspot)
  904.             continue;                                               // not visable
  905.  
  906.         if (TransformTile (statptr->tilex,statptr->tiley,
  907.             &visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS)
  908.         {
  909.             GetBonus (statptr);
  910.             if(statptr->shapenum == -1)
  911.                 continue;                                           // object has been taken
  912.         }
  913.  
  914.         if (!visptr->viewheight)
  915.             continue;                                               // to close to the object
  916.  
  917. #ifdef USE_DIR3DSPR
  918.         if(statptr->flags & FL_DIR_MASK)
  919.             visptr->transsprite=statptr;
  920.         else
  921.             visptr->transsprite=NULL;
  922. #endif
  923.  
  924.         if (visptr < &vislist[MAXVISABLE-1])    // don't let it overflow
  925.         {
  926.             visptr->flags = (short) statptr->flags;
  927.             visptr++;
  928.         }
  929.     }
  930.  
  931. //
  932. // place active objects
  933. //
  934.     for (obj = player->next;obj;obj=obj->next)
  935.     {
  936.         if ((visptr->shapenum = obj->state->shapenum)==0)
  937.             continue;                                               // no shape
  938.  
  939.         spotloc = (obj->tilex<<mapshift)+obj->tiley;   // optimize: keep in struct?
  940.         visspot = &spotvis[0][0]+spotloc;
  941.         tilespot = &tilemap[0][0]+spotloc;
  942.  
  943.         //
  944.         // could be in any of the nine surrounding tiles
  945.         //
  946.         if (*visspot
  947.             || ( *(visspot-1) && !*(tilespot-1) )
  948.             || ( *(visspot+1) && !*(tilespot+1) )
  949.             || ( *(visspot-65) && !*(tilespot-65) )
  950.             || ( *(visspot-64) && !*(tilespot-64) )
  951.             || ( *(visspot-63) && !*(tilespot-63) )
  952.             || ( *(visspot+65) && !*(tilespot+65) )
  953.             || ( *(visspot+64) && !*(tilespot+64) )
  954.             || ( *(visspot+63) && !*(tilespot+63) ) )
  955.         {
  956.             obj->active = ac_yes;
  957.             TransformActor (obj);
  958.             if (!obj->viewheight)
  959.                 continue;                                               // too close or far away
  960.  
  961.             visptr->viewx = obj->viewx;
  962.             visptr->viewheight = obj->viewheight;
  963.             if (visptr->shapenum == -1)
  964.                 visptr->shapenum = obj->temp1;  // special shape
  965.  
  966.             if (obj->state->rotate)
  967.                 visptr->shapenum += CalcRotate (obj);
  968.  
  969.             if (visptr < &vislist[MAXVISABLE-1])    // don't let it overflow
  970.             {
  971.                 visptr->flags = (short) obj->flags;
  972. #ifdef USE_DIR3DSPR
  973.                 visptr->transsprite = NULL;
  974. #endif
  975.                 visptr++;
  976.             }
  977.             obj->flags |= FL_VISABLE;
  978.         }
  979.         else
  980.             obj->flags &= ~FL_VISABLE;
  981.     }
  982.  
  983. //
  984. // draw from back to front
  985. //
  986.     numvisable = (int) (visptr-&vislist[0]);
  987.  
  988.     if (!numvisable)
  989.         return;                                                                 // no visable objects
  990.  
  991.     for (i = 0; i<numvisable; i++)
  992.     {
  993.         least = 32000;
  994.         for (visstep=&vislist[0] ; visstep<visptr ; visstep++)
  995.         {
  996.             height = visstep->viewheight;
  997.             if (height < least)
  998.             {
  999.                 least = height;
  1000.                 farthest = visstep;
  1001.             }
  1002.         }
  1003.         //
  1004.         // draw farthest
  1005.         //
  1006. #ifdef USE_DIR3DSPR
  1007.         if(farthest->transsprite)
  1008.             Scale3DShape(vbuf, vbufPitch, farthest->transsprite);
  1009.         else
  1010. #endif
  1011.             ScaleShape(farthest->viewx, farthest->shapenum, farthest->viewheight, farthest->flags);
  1012.  
  1013.         farthest->viewheight = 32000;
  1014.     }
  1015. }
  1016.  
  1017. //==========================================================================
  1018.  
  1019. /*
  1020. ==============
  1021. =
  1022. = DrawPlayerWeapon
  1023. =
  1024. = Draw the player's hands
  1025. =
  1026. ==============
  1027. */
  1028.  
  1029. int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY, SPR_PISTOLREADY,
  1030.     SPR_MACHINEGUNREADY, SPR_CHAINREADY};
  1031.  
  1032. void DrawPlayerWeapon (void)
  1033. {
  1034.     int shapenum;
  1035.  
  1036. #ifndef SPEAR
  1037.     if (gamestate.victoryflag)
  1038.     {
  1039. #ifndef APOGEE_1_0
  1040.         if (player->state == &s_deathcam && (GetTimeCount()&32) )
  1041.             SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1);
  1042. #endif
  1043.         return;
  1044.     }
  1045. #endif
  1046.  
  1047.     if (gamestate.weapon != -1)
  1048.     {
  1049.         shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe;
  1050.         SimpleScaleShape(viewwidth/2,shapenum,viewheight+1);
  1051.     }
  1052.  
  1053.     if (demorecord || demoplayback)
  1054.         SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1);
  1055. }
  1056.  
  1057.  
  1058. //==========================================================================
  1059.  
  1060.  
  1061. /*
  1062. =====================
  1063. =
  1064. = CalcTics
  1065. =
  1066. =====================
  1067. */
  1068.  
  1069. void CalcTics (void)
  1070. {
  1071. //
  1072. // calculate tics since last refresh for adaptive timing
  1073. //
  1074.     if (lasttimecount > (int32_t) GetTimeCount())
  1075.         lasttimecount = GetTimeCount();    // if the game was paused a LONG time
  1076.  
  1077.     uint32_t curtime =  SDL_GetTicks();
  1078.     tics = (curtime * 7) / 100 - lasttimecount;
  1079.     if(!tics)
  1080.     {
  1081.         // wait until end of current tic
  1082.         SDL_Delay(((lasttimecount + 1) * 100) / 7 - curtime);
  1083.         tics = 1;
  1084.     }
  1085.  
  1086.     lasttimecount += tics;
  1087.  
  1088.     if (tics>MAXTICS)
  1089.         tics = MAXTICS;
  1090. }
  1091.  
  1092.  
  1093. //==========================================================================
  1094.  
  1095. void AsmRefresh()
  1096. {
  1097.     int32_t xstep,ystep;
  1098.     longword xpartial,ypartial;
  1099.     boolean playerInPushwallBackTile = tilemap[focaltx][focalty] == 64;
  1100.  
  1101.     for(pixx=0;pixx<viewwidth;pixx++)
  1102.     {
  1103.         short angl=midangle+pixelangle[pixx];
  1104.         if(angl<0) angl+=FINEANGLES;
  1105.         if(angl>=3600) angl-=FINEANGLES;
  1106.         if(angl<900)
  1107.         {
  1108.             xtilestep=1;
  1109.             ytilestep=-1;
  1110.             xstep=finetangent[900-1-angl];
  1111.             ystep=-finetangent[angl];
  1112.             xpartial=xpartialup;
  1113.             ypartial=ypartialdown;
  1114.         }
  1115.         else if(angl<1800)
  1116.         {
  1117.             xtilestep=-1;
  1118.             ytilestep=-1;
  1119.             xstep=-finetangent[angl-900];
  1120.             ystep=-finetangent[1800-1-angl];
  1121.             xpartial=xpartialdown;
  1122.             ypartial=ypartialdown;
  1123.         }
  1124.         else if(angl<2700)
  1125.         {
  1126.             xtilestep=-1;
  1127.             ytilestep=1;
  1128.             xstep=-finetangent[2700-1-angl];
  1129.             ystep=finetangent[angl-1800];
  1130.             xpartial=xpartialdown;
  1131.             ypartial=ypartialup;
  1132.         }
  1133.         else if(angl<3600)
  1134.         {
  1135.             xtilestep=1;
  1136.             ytilestep=1;
  1137.             xstep=finetangent[angl-2700];
  1138.             ystep=finetangent[3600-1-angl];
  1139.             xpartial=xpartialup;
  1140.             ypartial=ypartialup;
  1141.         }
  1142.         yintercept=FixedMul(ystep,xpartial)+viewy;
  1143.         xtile=focaltx+xtilestep;
  1144.         xspot=(word)((xtile<<mapshift)+((uint32_t)yintercept>>16));
  1145.         xintercept=FixedMul(xstep,ypartial)+viewx;
  1146.         ytile=focalty+ytilestep;
  1147.         yspot=(word)((((uint32_t)xintercept>>16)<<mapshift)+ytile);
  1148.         texdelta=0;
  1149.  
  1150.         // Special treatment when player is in back tile of pushwall
  1151.         if(playerInPushwallBackTile)
  1152.         {
  1153.             if(    pwalldir == di_east && xtilestep ==  1
  1154.                 || pwalldir == di_west && xtilestep == -1)
  1155.             {
  1156.                 int32_t yintbuf = yintercept - ((ystep * (64 - pwallpos)) >> 6);
  1157.                 if((yintbuf >> 16) == focalty)   // ray hits pushwall back?
  1158.                 {
  1159.                     if(pwalldir == di_east)
  1160.                         xintercept = (focaltx << TILESHIFT) + (pwallpos << 10);
  1161.                     else
  1162.                         xintercept = (focaltx << TILESHIFT) - TILEGLOBAL + ((64 - pwallpos) << 10);
  1163.                     yintercept = yintbuf;
  1164.                     ytile = (short) (yintercept >> TILESHIFT);
  1165.                     tilehit = pwalltile;
  1166.                     HitVertWall();
  1167.                     continue;
  1168.                 }
  1169.             }
  1170.             else if(pwalldir == di_south && ytilestep ==  1
  1171.                 ||  pwalldir == di_north && ytilestep == -1)
  1172.             {
  1173.                 int32_t xintbuf = xintercept - ((xstep * (64 - pwallpos)) >> 6);
  1174.                 if((xintbuf >> 16) == focaltx)   // ray hits pushwall back?
  1175.                 {
  1176.                     xintercept = xintbuf;
  1177.                     if(pwalldir == di_south)
  1178.                         yintercept = (focalty << TILESHIFT) + (pwallpos << 10);
  1179.                     else
  1180.                         yintercept = (focalty << TILESHIFT) - TILEGLOBAL + ((64 - pwallpos) << 10);
  1181.                     xtile = (short) (xintercept >> TILESHIFT);
  1182.                     tilehit = pwalltile;
  1183.                     HitHorizWall();
  1184.                     continue;
  1185.                 }
  1186.             }
  1187.         }
  1188.  
  1189.         do
  1190.         {
  1191.             if(ytilestep==-1 && (yintercept>>16)<=ytile) goto horizentry;
  1192.             if(ytilestep==1 && (yintercept>>16)>=ytile) goto horizentry;
  1193. vertentry:
  1194.             if((uint32_t)yintercept>mapheight*65536-1 || (word)xtile>=mapwidth)
  1195.             {
  1196.                 if(xtile<0) xintercept=0, xtile=0;
  1197.                 else if(xtile>=mapwidth) xintercept=mapwidth<<TILESHIFT, xtile=mapwidth-1;
  1198.                 else xtile=(short) (xintercept >> TILESHIFT);
  1199.                 if(yintercept<0) yintercept=0, ytile=0;
  1200.                 else if(yintercept>=(mapheight<<TILESHIFT)) yintercept=mapheight<<TILESHIFT, ytile=mapheight-1;
  1201.                 yspot=0xffff;
  1202.                 tilehit=0;
  1203.                 HitHorizBorder();
  1204.                 break;
  1205.             }
  1206.             if(xspot>=maparea) break;
  1207.             tilehit=((byte *)tilemap)[xspot];
  1208.             if(tilehit)
  1209.             {
  1210.                 if(tilehit&0x80)
  1211.                 {
  1212.                     int32_t yintbuf=yintercept+(ystep>>1);
  1213.                     if((yintbuf>>16)!=(yintercept>>16))
  1214.                         goto passvert;
  1215.                     if((word)yintbuf<doorposition[tilehit&0x7f])
  1216.                         goto passvert;
  1217.                     yintercept=yintbuf;
  1218.                     xintercept=(xtile<<TILESHIFT)|0x8000;
  1219.                     ytile = (short) (yintercept >> TILESHIFT);
  1220.                     HitVertDoor();
  1221.                 }
  1222.                 else
  1223.                 {
  1224.                     if(tilehit==64)
  1225.                     {
  1226.                         if(pwalldir==di_west || pwalldir==di_east)
  1227.                         {
  1228.                                 int32_t yintbuf;
  1229.                             int pwallposnorm;
  1230.                             int pwallposinv;
  1231.                             if(pwalldir==di_west)
  1232.                             {
  1233.                                 pwallposnorm = 64-pwallpos;
  1234.                                 pwallposinv = pwallpos;
  1235.                             }
  1236.                             else
  1237.                             {
  1238.                                 pwallposnorm = pwallpos;
  1239.                                 pwallposinv = 64-pwallpos;
  1240.                             }
  1241.                             if(pwalldir == di_east && xtile==pwallx && ((uint32_t)yintercept>>16)==pwally
  1242.                                 || pwalldir == di_west && !(xtile==pwallx && ((uint32_t)yintercept>>16)==pwally))
  1243.                             {
  1244.                                 yintbuf=yintercept+((ystep*pwallposnorm)>>6);
  1245.                                 if((yintbuf>>16)!=(yintercept>>16))
  1246.                                     goto passvert;
  1247.  
  1248.                                 xintercept=(xtile<<TILESHIFT)+TILEGLOBAL-(pwallposinv<<10);
  1249.                                 yintercept=yintbuf;
  1250.                                 ytile = (short) (yintercept >> TILESHIFT);
  1251.                                 tilehit=pwalltile;
  1252.                                 HitVertWall();
  1253.                             }
  1254.                             else
  1255.                             {
  1256.                                 yintbuf=yintercept+((ystep*pwallposinv)>>6);
  1257.                                 if((yintbuf>>16)!=(yintercept>>16))
  1258.                                     goto passvert;
  1259.  
  1260.                                 xintercept=(xtile<<TILESHIFT)-(pwallposinv<<10);
  1261.                                 yintercept=yintbuf;
  1262.                                 ytile = (short) (yintercept >> TILESHIFT);
  1263.                                 tilehit=pwalltile;
  1264.                                 HitVertWall();
  1265.                             }
  1266.                         }
  1267.                         else
  1268.                         {
  1269.                             int pwallposi = pwallpos;
  1270.                             if(pwalldir==di_north) pwallposi = 64-pwallpos;
  1271.                             if(pwalldir==di_south && (word)yintercept<(pwallposi<<10)
  1272.                                 || pwalldir==di_north && (word)yintercept>(pwallposi<<10))
  1273.                             {
  1274.                                 if(((uint32_t)yintercept>>16)==pwally && xtile==pwallx)
  1275.                                 {
  1276.                                     if(pwalldir==di_south && (int32_t)((word)yintercept)+ystep<(pwallposi<<10)
  1277.                                             || pwalldir==di_north && (int32_t)((word)yintercept)+ystep>(pwallposi<<10))
  1278.                                         goto passvert;
  1279.  
  1280.                                     if(pwalldir==di_south)
  1281.                                         yintercept=(yintercept&0xffff0000)+(pwallposi<<10);
  1282.                                     else
  1283.                                         yintercept=(yintercept&0xffff0000)-TILEGLOBAL+(pwallposi<<10);
  1284.                                     xintercept=xintercept-((xstep*(64-pwallpos))>>6);
  1285.                                     xtile = (short) (xintercept >> TILESHIFT);
  1286.                                     tilehit=pwalltile;
  1287.                                     HitHorizWall();
  1288.                                 }
  1289.                                 else
  1290.                                 {
  1291.                                     texdelta = -(pwallposi<<10);
  1292.                                     xintercept=xtile<<TILESHIFT;
  1293.                                     ytile = (short) (yintercept >> TILESHIFT);
  1294.                                     tilehit=pwalltile;
  1295.                                     HitVertWall();
  1296.                                 }
  1297.                             }
  1298.                             else
  1299.                             {
  1300.                                 if(((uint32_t)yintercept>>16)==pwally && xtile==pwallx)
  1301.                                 {
  1302.                                     texdelta = -(pwallposi<<10);
  1303.                                     xintercept=xtile<<TILESHIFT;
  1304.                                     ytile = (short) (yintercept >> TILESHIFT);
  1305.                                     tilehit=pwalltile;
  1306.                                     HitVertWall();
  1307.                                 }
  1308.                                 else
  1309.                                 {
  1310.                                     if(pwalldir==di_south && (int32_t)((word)yintercept)+ystep>(pwallposi<<10)
  1311.                                             || pwalldir==di_north && (int32_t)((word)yintercept)+ystep<(pwallposi<<10))
  1312.                                         goto passvert;
  1313.  
  1314.                                     if(pwalldir==di_south)
  1315.                                         yintercept=(yintercept&0xffff0000)-((64-pwallpos)<<10);
  1316.                                     else
  1317.                                         yintercept=(yintercept&0xffff0000)+((64-pwallpos)<<10);
  1318.                                     xintercept=xintercept-((xstep*pwallpos)>>6);
  1319.                                     xtile = (short) (xintercept >> TILESHIFT);
  1320.                                     tilehit=pwalltile;
  1321.                                     HitHorizWall();
  1322.                                 }
  1323.                             }
  1324.                         }
  1325.                     }
  1326.                     else
  1327.                     {
  1328.                         xintercept=xtile<<TILESHIFT;
  1329.                         ytile = (short) (yintercept >> TILESHIFT);
  1330.                         HitVertWall();
  1331.                     }
  1332.                 }
  1333.                 break;
  1334.             }
  1335. passvert:
  1336.             *((byte *)spotvis+xspot)=1;
  1337.             xtile+=xtilestep;
  1338.             yintercept+=ystep;
  1339.             xspot=(word)((xtile<<mapshift)+((uint32_t)yintercept>>16));
  1340.         }
  1341.         while(1);
  1342.         continue;
  1343.  
  1344.         do
  1345.         {
  1346.             if(xtilestep==-1 && (xintercept>>16)<=xtile) goto vertentry;
  1347.             if(xtilestep==1 && (xintercept>>16)>=xtile) goto vertentry;
  1348. horizentry:
  1349.             if((uint32_t)xintercept>mapwidth*65536-1 || (word)ytile>=mapheight)
  1350.             {
  1351.                 if(ytile<0) yintercept=0, ytile=0;
  1352.                 else if(ytile>=mapheight) yintercept=mapheight<<TILESHIFT, ytile=mapheight-1;
  1353.                 else ytile=(short) (yintercept >> TILESHIFT);
  1354.                 if(xintercept<0) xintercept=0, xtile=0;
  1355.                 else if(xintercept>=(mapwidth<<TILESHIFT)) xintercept=mapwidth<<TILESHIFT, xtile=mapwidth-1;
  1356.                 xspot=0xffff;
  1357.                 tilehit=0;
  1358.                 HitVertBorder();
  1359.                 break;
  1360.             }
  1361.             if(yspot>=maparea) break;
  1362.             tilehit=((byte *)tilemap)[yspot];
  1363.             if(tilehit)
  1364.             {
  1365.                 if(tilehit&0x80)
  1366.                 {
  1367.                     int32_t xintbuf=xintercept+(xstep>>1);
  1368.                     if((xintbuf>>16)!=(xintercept>>16))
  1369.                         goto passhoriz;
  1370.                     if((word)xintbuf<doorposition[tilehit&0x7f])
  1371.                         goto passhoriz;
  1372.                     xintercept=xintbuf;
  1373.                     yintercept=(ytile<<TILESHIFT)+0x8000;
  1374.                     xtile = (short) (xintercept >> TILESHIFT);
  1375.                     HitHorizDoor();
  1376.                 }
  1377.                 else
  1378.                 {
  1379.                     if(tilehit==64)
  1380.                     {
  1381.                         if(pwalldir==di_north || pwalldir==di_south)
  1382.                         {
  1383.                             int32_t xintbuf;
  1384.                             int pwallposnorm;
  1385.                             int pwallposinv;
  1386.                             if(pwalldir==di_north)
  1387.                             {
  1388.                                 pwallposnorm = 64-pwallpos;
  1389.                                 pwallposinv = pwallpos;
  1390.                             }
  1391.                             else
  1392.                             {
  1393.                                 pwallposnorm = pwallpos;
  1394.                                 pwallposinv = 64-pwallpos;
  1395.                             }
  1396.                             if(pwalldir == di_south && ytile==pwally && ((uint32_t)xintercept>>16)==pwallx
  1397.                                 || pwalldir == di_north && !(ytile==pwally && ((uint32_t)xintercept>>16)==pwallx))
  1398.                             {
  1399.                                 xintbuf=xintercept+((xstep*pwallposnorm)>>6);
  1400.                                 if((xintbuf>>16)!=(xintercept>>16))
  1401.                                     goto passhoriz;
  1402.  
  1403.                                 yintercept=(ytile<<TILESHIFT)+TILEGLOBAL-(pwallposinv<<10);
  1404.                                 xintercept=xintbuf;
  1405.                                 xtile = (short) (xintercept >> TILESHIFT);
  1406.                                 tilehit=pwalltile;
  1407.                                 HitHorizWall();
  1408.                             }
  1409.                             else
  1410.                             {
  1411.                                 xintbuf=xintercept+((xstep*pwallposinv)>>6);
  1412.                                 if((xintbuf>>16)!=(xintercept>>16))
  1413.                                     goto passhoriz;
  1414.  
  1415.                                 yintercept=(ytile<<TILESHIFT)-(pwallposinv<<10);
  1416.                                 xintercept=xintbuf;
  1417.                                 xtile = (short) (xintercept >> TILESHIFT);
  1418.                                 tilehit=pwalltile;
  1419.                                 HitHorizWall();
  1420.                             }
  1421.                         }
  1422.                         else
  1423.                         {
  1424.                             int pwallposi = pwallpos;
  1425.                             if(pwalldir==di_west) pwallposi = 64-pwallpos;
  1426.                             if(pwalldir==di_east && (word)xintercept<(pwallposi<<10)
  1427.                                     || pwalldir==di_west && (word)xintercept>(pwallposi<<10))
  1428.                             {
  1429.                                 if(((uint32_t)xintercept>>16)==pwallx && ytile==pwally)
  1430.                                 {
  1431.                                     if(pwalldir==di_east && (int32_t)((word)xintercept)+xstep<(pwallposi<<10)
  1432.                                             || pwalldir==di_west && (int32_t)((word)xintercept)+xstep>(pwallposi<<10))
  1433.                                         goto passhoriz;
  1434.  
  1435.                                     if(pwalldir==di_east)
  1436.                                         xintercept=(xintercept&0xffff0000)+(pwallposi<<10);
  1437.                                     else
  1438.                                         xintercept=(xintercept&0xffff0000)-TILEGLOBAL+(pwallposi<<10);
  1439.                                     yintercept=yintercept-((ystep*(64-pwallpos))>>6);
  1440.                                     ytile = (short) (yintercept >> TILESHIFT);
  1441.                                     tilehit=pwalltile;
  1442.                                     HitVertWall();
  1443.                                 }
  1444.                                 else
  1445.                                 {
  1446.                                     texdelta = -(pwallposi<<10);
  1447.                                     yintercept=ytile<<TILESHIFT;
  1448.                                     xtile = (short) (xintercept >> TILESHIFT);
  1449.                                     tilehit=pwalltile;
  1450.                                     HitHorizWall();
  1451.                                 }
  1452.                             }
  1453.                             else
  1454.                             {
  1455.                                 if(((uint32_t)xintercept>>16)==pwallx && ytile==pwally)
  1456.                                 {
  1457.                                     texdelta = -(pwallposi<<10);
  1458.                                     yintercept=ytile<<TILESHIFT;
  1459.                                     xtile = (short) (xintercept >> TILESHIFT);
  1460.                                     tilehit=pwalltile;
  1461.                                     HitHorizWall();
  1462.                                 }
  1463.                                 else
  1464.                                 {
  1465.                                     if(pwalldir==di_east && (int32_t)((word)xintercept)+xstep>(pwallposi<<10)
  1466.                                             || pwalldir==di_west && (int32_t)((word)xintercept)+xstep<(pwallposi<<10))
  1467.                                         goto passhoriz;
  1468.  
  1469.                                     if(pwalldir==di_east)
  1470.                                         xintercept=(xintercept&0xffff0000)-((64-pwallpos)<<10);
  1471.                                     else
  1472.                                         xintercept=(xintercept&0xffff0000)+((64-pwallpos)<<10);
  1473.                                     yintercept=yintercept-((ystep*pwallpos)>>6);
  1474.                                     ytile = (short) (yintercept >> TILESHIFT);
  1475.                                     tilehit=pwalltile;
  1476.                                     HitVertWall();
  1477.                                 }
  1478.                             }
  1479.                         }
  1480.                     }
  1481.                     else
  1482.                     {
  1483.                         yintercept=ytile<<TILESHIFT;
  1484.                         xtile = (short) (xintercept >> TILESHIFT);
  1485.                         HitHorizWall();
  1486.                     }
  1487.                 }
  1488.                 break;
  1489.             }
  1490. passhoriz:
  1491.             *((byte *)spotvis+yspot)=1;
  1492.             ytile+=ytilestep;
  1493.             xintercept+=xstep;
  1494.             yspot=(word)((((uint32_t)xintercept>>16)<<mapshift)+ytile);
  1495.         }
  1496.         while(1);
  1497.     }
  1498. }
  1499.  
  1500. /*
  1501. ====================
  1502. =
  1503. = WallRefresh
  1504. =
  1505. ====================
  1506. */
  1507.  
  1508. void WallRefresh (void)
  1509. {
  1510.     xpartialdown = viewx&(TILEGLOBAL-1);
  1511.     xpartialup = TILEGLOBAL-xpartialdown;
  1512.     ypartialdown = viewy&(TILEGLOBAL-1);
  1513.     ypartialup = TILEGLOBAL-ypartialdown;
  1514.  
  1515.     min_wallheight = viewheight;
  1516.     lastside = -1;                  // the first pixel is on a new wall
  1517.     AsmRefresh ();
  1518.     ScalePost ();                   // no more optimization on last post
  1519. }
  1520.  
  1521. void CalcViewVariables()
  1522. {
  1523.     viewangle = player->angle;
  1524.     midangle = viewangle*(FINEANGLES/ANGLES);
  1525.     viewsin = sintable[viewangle];
  1526.     viewcos = costable[viewangle];
  1527.     viewx = player->x - FixedMul(focallength,viewcos);
  1528.     viewy = player->y + FixedMul(focallength,viewsin);
  1529.  
  1530.     focaltx = (short)(viewx>>TILESHIFT);
  1531.     focalty = (short)(viewy>>TILESHIFT);
  1532.  
  1533.     viewtx = (short)(player->x >> TILESHIFT);
  1534.     viewty = (short)(player->y >> TILESHIFT);
  1535. }
  1536.  
  1537. //==========================================================================
  1538.  
  1539. /*
  1540. ========================
  1541. =
  1542. = ThreeDRefresh
  1543. =
  1544. ========================
  1545. */
  1546.  
  1547. void    ThreeDRefresh (void)
  1548. {
  1549. //
  1550. // clear out the traced array
  1551. //
  1552.     memset(spotvis,0,maparea);
  1553.     spotvis[player->tilex][player->tiley] = 1;       // Detect all sprites over player fix
  1554.  
  1555.     vbuf = VL_LockSurface(screenBuffer);
  1556.     if(vbuf == NULL) return;
  1557.  
  1558.     vbuf += screenofs;
  1559.     vbufPitch = bufferPitch;
  1560.  
  1561.     CalcViewVariables();
  1562.  
  1563. //
  1564. // follow the walls from there to the right, drawing as we go
  1565. //
  1566.     VGAClearScreen ();
  1567. #if defined(USE_FEATUREFLAGS) && defined(USE_STARSKY)
  1568.     if(GetFeatureFlags() & FF_STARSKY)
  1569.         DrawStarSky(vbuf, vbufPitch);
  1570. #endif
  1571.  
  1572.     WallRefresh ();
  1573.  
  1574. #if defined(USE_FEATUREFLAGS) && defined(USE_PARALLAX)
  1575.     if(GetFeatureFlags() & FF_PARALLAXSKY)
  1576.         DrawParallax(vbuf, vbufPitch);
  1577. #endif
  1578. #if defined(USE_FEATUREFLAGS) && defined(USE_CLOUDSKY)
  1579.     if(GetFeatureFlags() & FF_CLOUDSKY)
  1580.         DrawClouds(vbuf, vbufPitch, min_wallheight);
  1581. #endif
  1582. #ifdef USE_FLOORCEILINGTEX
  1583.     DrawFloorAndCeiling(vbuf, vbufPitch, min_wallheight);
  1584. #endif
  1585.  
  1586. //
  1587. // draw all the scaled images
  1588. //
  1589.     DrawScaleds();                  // draw scaled stuff
  1590.  
  1591. #if defined(USE_FEATUREFLAGS) && defined(USE_RAIN)
  1592.     if(GetFeatureFlags() & FF_RAIN)
  1593.         DrawRain(vbuf, vbufPitch);
  1594. #endif
  1595. #if defined(USE_FEATUREFLAGS) && defined(USE_SNOW)
  1596.     if(GetFeatureFlags() & FF_SNOW)
  1597.         DrawSnow(vbuf, vbufPitch);
  1598. #endif
  1599.  
  1600.     DrawPlayerWeapon ();    // draw player's hands
  1601.  
  1602.     if(Keyboard[sc_Tab] && viewsize == 21 && gamestate.weapon != -1)
  1603.         ShowActStatus();
  1604.  
  1605.     VL_UnlockSurface(screenBuffer);
  1606.     vbuf = NULL;
  1607.  
  1608. //
  1609. // show screen and time last cycle
  1610. //
  1611.  
  1612.     if (fizzlein)
  1613.     {
  1614.         FizzleFade(screenBuffer, 0, 0, screenWidth, screenHeight, 20, false);
  1615.         fizzlein = false;
  1616.  
  1617.         lasttimecount = GetTimeCount();          // don't make a big tic count
  1618.     }
  1619.     else
  1620.     {
  1621. #ifndef REMDEBUG
  1622.         if (fpscounter)
  1623.         {
  1624.             fontnumber = 0;
  1625.             SETFONTCOLOR(7,127);
  1626.             PrintX=4; PrintY=1;
  1627.             VWB_Bar(0,0,50,10,bordercol);
  1628.             US_PrintSigned(fps);
  1629.             US_Print(" fps");
  1630.         }
  1631. #endif
  1632.         SDL_BlitSurface(screenBuffer, NULL, screen, NULL);
  1633.         SDL_Flip(screen);
  1634.     }
  1635.  
  1636. #ifndef REMDEBUG
  1637.     if (fpscounter)
  1638.     {
  1639.         fps_frames++;
  1640.         fps_time+=tics;
  1641.  
  1642.         if(fps_time>35)
  1643.         {
  1644.             fps_time-=35;
  1645.             fps=fps_frames<<1;
  1646.             fps_frames=0;
  1647.         }
  1648.     }
  1649. #endif
  1650. }
  1651.