Subversion Repositories Kolibri OS

Rev

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

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