summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs/wolf3d/wl_draw.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2019-07-07 22:00:20 -0400
committerFranklin Wei <git@fwei.tk>2019-07-09 11:20:55 -0400
commit3f59fc8b771625aca9c3aefe03cf1038d8461963 (patch)
treee0623a323613baa0b0993411b38bcaed144b27ed /apps/plugins/sdl/progs/wolf3d/wl_draw.c
parent439a0d1d91fa040d261fc39b87278bc9f5391dcc (diff)
downloadrockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.gz
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.bz2
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.zip
Wolfenstein 3-D!
This is a port of Wolf4SDL, which is derived from the original id software source release. The port runs on top of the SDL plugin runtime and is loaded as an overlay. Licensing of the game code is not an issue, as discussed below (essentially, the Debian project treats Wolf4SDL as GPLv2, with an email from John Carmack backing it up): http://forums.rockbox.org/index.php?topic=52872 Included is a copy of MAME's Yamaha OPL sound chip emulator (fmopl_gpl.c). This file was not part of the original Wolf4SDL source (which includes a non-GPL'd version), but was rather rebased from from a later MAME source which had been relicensed to GPLv2. Change-Id: I64c2ba035e0be7e2f49252f40640641416613439
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_draw.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/wl_draw.c1647
1 files changed, 1647 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_draw.c b/apps/plugins/sdl/progs/wolf3d/wl_draw.c
new file mode 100644
index 0000000000..625e93dc0a
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/wl_draw.c
@@ -0,0 +1,1647 @@
+// WL_DRAW.C
+
+#include "wl_def.h"
+#pragma hdrstop
+
+#include "wl_cloudsky.h"
+#include "wl_atmos.h"
+#include "wl_shade.h"
+
+/*
+=============================================================================
+
+ LOCAL CONSTANTS
+
+=============================================================================
+*/
+
+// the door is the last picture before the sprites
+#define DOORWALL (PMSpriteStart-8)
+
+#define ACTORSIZE 0x4000
+
+/*
+=============================================================================
+
+ GLOBAL VARIABLES
+
+=============================================================================
+*/
+
+static byte *vbuf = NULL;
+unsigned vbufPitch = 0;
+
+int32_t lasttimecount;
+int32_t frameon;
+boolean fpscounter;
+
+int fps_frames=0, fps_time=0, fps=0;
+
+int *wallheight;
+int min_wallheight;
+
+//
+// math tables
+//
+short *pixelangle;
+int32_t finetangent[FINEANGLES/4];
+fixed sintable[ANGLES+ANGLES/4];
+fixed *costable = sintable+(ANGLES/4);
+
+//
+// refresh variables
+//
+fixed viewx,viewy; // the focal point
+short viewangle;
+fixed viewsin,viewcos;
+
+void TransformActor (objtype *ob);
+void BuildTables (void);
+void ClearScreen (void);
+int CalcRotate (objtype *ob);
+void DrawScaleds (void);
+void CalcTics (void);
+void ThreeDRefresh (void);
+
+
+
+//
+// wall optimization variables
+//
+int lastside; // true for vertical
+int32_t lastintercept;
+int lasttilehit;
+int lasttexture;
+
+//
+// ray tracing variables
+//
+short focaltx,focalty,viewtx,viewty;
+longword xpartialup,xpartialdown,ypartialup,ypartialdown;
+
+short midangle,angle;
+
+word tilehit;
+int pixx;
+
+short xtile,ytile;
+short xtilestep,ytilestep;
+int32_t xintercept,yintercept;
+word xstep,ystep;
+word xspot,yspot;
+int texdelta;
+
+word horizwall[MAXWALLTILES],vertwall[MAXWALLTILES];
+
+
+/*
+============================================================================
+
+ 3 - D DEFINITIONS
+
+============================================================================
+*/
+
+/*
+========================
+=
+= TransformActor
+=
+= Takes paramaters:
+= gx,gy : globalx/globaly of point
+=
+= globals:
+= viewx,viewy : point of view
+= viewcos,viewsin : sin/cos of viewangle
+= scale : conversion from global value to screen value
+=
+= sets:
+= screenx,transx,transy,screenheight: projected edge location and size
+=
+========================
+*/
+
+
+//
+// transform actor
+//
+void TransformActor (objtype *ob)
+{
+ fixed gx,gy,gxt,gyt,nx,ny;
+
+//
+// translate point to view centered coordinates
+//
+ gx = ob->x-viewx;
+ gy = ob->y-viewy;
+
+//
+// calculate newx
+//
+ gxt = FixedMul(gx,viewcos);
+ gyt = FixedMul(gy,viewsin);
+ nx = gxt-gyt-ACTORSIZE; // fudge the shape forward a bit, because
+ // the midpoint could put parts of the shape
+ // into an adjacent wall
+
+//
+// calculate newy
+//
+ gxt = FixedMul(gx,viewsin);
+ gyt = FixedMul(gy,viewcos);
+ ny = gyt+gxt;
+
+//
+// calculate perspective ratio
+//
+ ob->transx = nx;
+ ob->transy = ny;
+
+ if (nx<MINDIST) // too close, don't overflow the divide
+ {
+ ob->viewheight = 0;
+ return;
+ }
+
+ ob->viewx = (word)(centerx + ny*scale/nx);
+
+//
+// calculate height (heightnumerator/(nx>>8))
+//
+ ob->viewheight = (word)(heightnumerator/(nx>>8));
+}
+
+//==========================================================================
+
+/*
+========================
+=
+= TransformTile
+=
+= Takes paramaters:
+= tx,ty : tile the object is centered in
+=
+= globals:
+= viewx,viewy : point of view
+= viewcos,viewsin : sin/cos of viewangle
+= scale : conversion from global value to screen value
+=
+= sets:
+= screenx,transx,transy,screenheight: projected edge location and size
+=
+= Returns true if the tile is withing getting distance
+=
+========================
+*/
+
+boolean TransformTile (int tx, int ty, short *dispx, short *dispheight)
+{
+ fixed gx,gy,gxt,gyt,nx,ny;
+
+//
+// translate point to view centered coordinates
+//
+ gx = ((int32_t)tx<<TILESHIFT)+0x8000-viewx;
+ gy = ((int32_t)ty<<TILESHIFT)+0x8000-viewy;
+
+//
+// calculate newx
+//
+ gxt = FixedMul(gx,viewcos);
+ gyt = FixedMul(gy,viewsin);
+ nx = gxt-gyt-0x2000; // 0x2000 is size of object
+
+//
+// calculate newy
+//
+ gxt = FixedMul(gx,viewsin);
+ gyt = FixedMul(gy,viewcos);
+ ny = gyt+gxt;
+
+
+//
+// calculate height / perspective ratio
+//
+ if (nx<MINDIST) // too close, don't overflow the divide
+ *dispheight = 0;
+ else
+ {
+ *dispx = (short)(centerx + ny*scale/nx);
+ *dispheight = (short)(heightnumerator/(nx>>8));
+ }
+
+//
+// see if it should be grabbed
+//
+ if (nx<TILEGLOBAL && ny>-TILEGLOBAL/2 && ny<TILEGLOBAL/2)
+ return true;
+ else
+ return false;
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= CalcHeight
+=
+= Calculates the height of xintercept,yintercept from viewx,viewy
+=
+====================
+*/
+
+int CalcHeight()
+{
+ fixed z = FixedMul(xintercept - viewx, viewcos)
+ - FixedMul(yintercept - viewy, viewsin);
+ if(z < MINDIST) z = MINDIST;
+ int height = heightnumerator / (z >> 8);
+ if(height < min_wallheight) min_wallheight = height;
+ return height;
+}
+
+//==========================================================================
+
+/*
+===================
+=
+= ScalePost
+=
+===================
+*/
+
+byte *postsource;
+int postx;
+int postwidth;
+
+void ScalePost()
+{
+ int ywcount, yoffs, yw, yd, yendoffs;
+ byte col;
+
+#ifdef USE_SHADING
+ byte *curshades = shadetable[GetShade(wallheight[postx])];
+#endif
+
+ ywcount = yd = wallheight[postx] >> 3;
+ if(yd <= 0) yd = 100;
+
+ yoffs = (viewheight / 2 - ywcount) * vbufPitch;
+ if(yoffs < 0) yoffs = 0;
+ yoffs += postx;
+
+ yendoffs = viewheight / 2 + ywcount - 1;
+ yw=TEXTURESIZE-1;
+
+ while(yendoffs >= viewheight)
+ {
+ ywcount -= TEXTURESIZE/2;
+ while(ywcount <= 0)
+ {
+ ywcount += yd;
+ yw--;
+ }
+ yendoffs--;
+ }
+ if(yw < 0) return;
+
+#ifdef USE_SHADING
+ col = curshades[postsource[yw]];
+#else
+ col = postsource[yw];
+#endif
+ yendoffs = yendoffs * vbufPitch + postx;
+ while(yoffs <= yendoffs)
+ {
+ vbuf[yendoffs] = col;
+ ywcount -= TEXTURESIZE/2;
+ if(ywcount <= 0)
+ {
+ do
+ {
+ ywcount += yd;
+ yw--;
+ }
+ while(ywcount <= 0);
+ if(yw < 0) break;
+#ifdef USE_SHADING
+ col = curshades[postsource[yw]];
+#else
+ col = postsource[yw];
+#endif
+ }
+ yendoffs -= vbufPitch;
+ }
+}
+
+void GlobalScalePost(byte *vidbuf, unsigned pitch)
+{
+ vbuf = vidbuf;
+ vbufPitch = pitch;
+ ScalePost();
+}
+
+/*
+====================
+=
+= HitVertWall
+=
+= tilehit bit 7 is 0, because it's not a door tile
+= if bit 6 is 1 and the adjacent tile is a door tile, use door side pic
+=
+====================
+*/
+
+void HitVertWall (void)
+{
+ int wallpic;
+ int texture;
+
+ texture = ((yintercept+texdelta)>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
+ if (xtilestep == -1)
+ {
+ texture = TEXTUREMASK-texture;
+ xintercept += TILEGLOBAL;
+ }
+
+ if(lastside==1 && lastintercept==xtile && lasttilehit==tilehit && !(lasttilehit & 0x40))
+ {
+ if((pixx&3) && texture == lasttexture)
+ {
+ ScalePost();
+ postx = pixx;
+ wallheight[pixx] = wallheight[pixx-1];
+ return;
+ }
+ ScalePost();
+ wallheight[pixx] = CalcHeight();
+ postsource+=texture-lasttexture;
+ postwidth=1;
+ postx=pixx;
+ lasttexture=texture;
+ return;
+ }
+
+ if(lastside!=-1) ScalePost();
+
+ lastside=1;
+ lastintercept=xtile;
+ lasttilehit=tilehit;
+ lasttexture=texture;
+ wallheight[pixx] = CalcHeight();
+ postx = pixx;
+ postwidth = 1;
+
+ if (tilehit & 0x40)
+ { // check for adjacent doors
+ ytile = (short)(yintercept>>TILESHIFT);
+ if ( tilemap[xtile-xtilestep][ytile]&0x80 )
+ wallpic = DOORWALL+3;
+ else
+ wallpic = vertwall[tilehit & ~0x40];
+ }
+ else
+ wallpic = vertwall[tilehit];
+
+ postsource = PM_GetTexture(wallpic) + texture;
+}
+
+
+/*
+====================
+=
+= HitHorizWall
+=
+= tilehit bit 7 is 0, because it's not a door tile
+= if bit 6 is 1 and the adjacent tile is a door tile, use door side pic
+=
+====================
+*/
+
+void HitHorizWall (void)
+{
+ int wallpic;
+ int texture;
+
+ texture = ((xintercept+texdelta)>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
+ if (ytilestep == -1)
+ yintercept += TILEGLOBAL;
+ else
+ texture = TEXTUREMASK-texture;
+
+ if(lastside==0 && lastintercept==ytile && lasttilehit==tilehit && !(lasttilehit & 0x40))
+ {
+ if((pixx&3) && texture == lasttexture)
+ {
+ ScalePost();
+ postx=pixx;
+ wallheight[pixx] = wallheight[pixx-1];
+ return;
+ }
+ ScalePost();
+ wallheight[pixx] = CalcHeight();
+ postsource+=texture-lasttexture;
+ postwidth=1;
+ postx=pixx;
+ lasttexture=texture;
+ return;
+ }
+
+ if(lastside!=-1) ScalePost();
+
+ lastside=0;
+ lastintercept=ytile;
+ lasttilehit=tilehit;
+ lasttexture=texture;
+ wallheight[pixx] = CalcHeight();
+ postx = pixx;
+ postwidth = 1;
+
+ if (tilehit & 0x40)
+ { // check for adjacent doors
+ xtile = (short)(xintercept>>TILESHIFT);
+ if ( tilemap[xtile][ytile-ytilestep]&0x80)
+ wallpic = DOORWALL+2;
+ else
+ wallpic = horizwall[tilehit & ~0x40];
+ }
+ else
+ wallpic = horizwall[tilehit];
+
+ postsource = PM_GetTexture(wallpic) + texture;
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= HitHorizDoor
+=
+====================
+*/
+
+void HitHorizDoor (void)
+{
+ int doorpage;
+ int doornum;
+ int texture;
+
+ doornum = tilehit&0x7f;
+ texture = ((xintercept-doorposition[doornum])>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
+
+ if(lasttilehit==tilehit)
+ {
+ if((pixx&3) && texture == lasttexture)
+ {
+ ScalePost();
+ postx=pixx;
+ wallheight[pixx] = wallheight[pixx-1];
+ return;
+ }
+ ScalePost();
+ wallheight[pixx] = CalcHeight();
+ postsource+=texture-lasttexture;
+ postwidth=1;
+ postx=pixx;
+ lasttexture=texture;
+ return;
+ }
+
+ if(lastside!=-1) ScalePost();
+
+ lastside=2;
+ lasttilehit=tilehit;
+ lasttexture=texture;
+ wallheight[pixx] = CalcHeight();
+ postx = pixx;
+ postwidth = 1;
+
+ switch(doorobjlist[doornum].lock)
+ {
+ case dr_normal:
+ doorpage = DOORWALL;
+ break;
+ case dr_lock1:
+ case dr_lock2:
+ case dr_lock3:
+ case dr_lock4:
+ doorpage = DOORWALL+6;
+ break;
+ case dr_elevator:
+ doorpage = DOORWALL+4;
+ break;
+ }
+
+ postsource = PM_GetTexture(doorpage) + texture;
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= HitVertDoor
+=
+====================
+*/
+
+void HitVertDoor (void)
+{
+ int doorpage;
+ int doornum;
+ int texture;
+
+ doornum = tilehit&0x7f;
+ texture = ((yintercept-doorposition[doornum])>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK;
+
+ if(lasttilehit==tilehit)
+ {
+ if((pixx&3) && texture == lasttexture)
+ {
+ ScalePost();
+ postx=pixx;
+ wallheight[pixx] = wallheight[pixx-1];
+ return;
+ }
+ ScalePost();
+ wallheight[pixx] = CalcHeight();
+ postsource+=texture-lasttexture;
+ postwidth=1;
+ postx=pixx;
+ lasttexture=texture;
+ return;
+ }
+
+ if(lastside!=-1) ScalePost();
+
+ lastside=2;
+ lasttilehit=tilehit;
+ lasttexture=texture;
+ wallheight[pixx] = CalcHeight();
+ postx = pixx;
+ postwidth = 1;
+
+ switch(doorobjlist[doornum].lock)
+ {
+ case dr_normal:
+ doorpage = DOORWALL+1;
+ break;
+ case dr_lock1:
+ case dr_lock2:
+ case dr_lock3:
+ case dr_lock4:
+ doorpage = DOORWALL+7;
+ break;
+ case dr_elevator:
+ doorpage = DOORWALL+5;
+ break;
+ }
+
+ postsource = PM_GetTexture(doorpage) + texture;
+}
+
+//==========================================================================
+
+#define HitHorizBorder HitHorizWall
+#define HitVertBorder HitVertWall
+
+//==========================================================================
+
+byte vgaCeiling[]=
+{
+#ifndef SPEAR
+ 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0xbf,
+ 0x4e,0x4e,0x4e,0x1d,0x8d,0x4e,0x1d,0x2d,0x1d,0x8d,
+ 0x1d,0x1d,0x1d,0x1d,0x1d,0x2d,0xdd,0x1d,0x1d,0x98,
+
+ 0x1d,0x9d,0x2d,0xdd,0xdd,0x9d,0x2d,0x4d,0x1d,0xdd,
+ 0x7d,0x1d,0x2d,0x2d,0xdd,0xd7,0x1d,0x1d,0x1d,0x2d,
+ 0x1d,0x1d,0x1d,0x1d,0xdd,0xdd,0x7d,0xdd,0xdd,0xdd
+#else
+ 0x6f,0x4f,0x1d,0xde,0xdf,0x2e,0x7f,0x9e,0xae,0x7f,
+ 0x1d,0xde,0xdf,0xde,0xdf,0xde,0xe1,0xdc,0x2e,0x1d,0xdc
+#endif
+};
+
+/*
+=====================
+=
+= VGAClearScreen
+=
+=====================
+*/
+
+void VGAClearScreen (void)
+{
+ byte ceiling=vgaCeiling[gamestate.episode*10+mapon];
+
+ int y;
+ byte *ptr = vbuf;
+#ifdef USE_SHADING
+ for(y = 0; y < viewheight / 2; y++, ptr += vbufPitch)
+ memset(ptr, shadetable[GetShade((viewheight / 2 - y) << 3)][ceiling], viewwidth);
+ for(; y < viewheight; y++, ptr += vbufPitch)
+ memset(ptr, shadetable[GetShade((y - viewheight / 2) << 3)][0x19], viewwidth);
+#else
+ for(y = 0; y < viewheight / 2; y++, ptr += vbufPitch)
+ memset(ptr, ceiling, viewwidth);
+ for(; y < viewheight; y++, ptr += vbufPitch)
+ memset(ptr, 0x19, viewwidth);
+#endif
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= CalcRotate
+=
+=====================
+*/
+
+int CalcRotate (objtype *ob)
+{
+ int angle, viewangle;
+
+ // this isn't exactly correct, as it should vary by a trig value,
+ // but it is close enough with only eight rotations
+
+ viewangle = player->angle + (centerx - ob->viewx)/8;
+
+ if (ob->obclass == rocketobj || ob->obclass == hrocketobj)
+ angle = (viewangle-180) - ob->angle;
+ else
+ angle = (viewangle-180) - dirangle[ob->dir];
+
+ angle+=ANGLES/16;
+ while (angle>=ANGLES)
+ angle-=ANGLES;
+ while (angle<0)
+ angle+=ANGLES;
+
+ if (ob->state->rotate == 2) // 2 rotation pain frame
+ return 0; // pain with shooting frame bugfix
+
+ return angle/(ANGLES/8);
+}
+
+void ScaleShape (int xcenter, int shapenum, unsigned height, uint32_t flags)
+{
+ t_compshape *shape;
+ unsigned scale,pixheight;
+ unsigned starty,endy;
+ word *cmdptr;
+ byte *cline;
+ byte *line;
+ byte *vmem;
+ int actx,i,upperedge;
+ short newstart;
+ int scrstarty,screndy,lpix,rpix,pixcnt,ycnt;
+ unsigned j;
+ byte col;
+
+#ifdef USE_SHADING
+ byte *curshades;
+ if(flags & FL_FULLBRIGHT)
+ curshades = shadetable[0];
+ else
+ curshades = shadetable[GetShade(height)];
+#endif
+
+ shape = (t_compshape *) PM_GetSprite(shapenum);
+
+ scale=height>>3; // low three bits are fractional
+ if(!scale) return; // too close or far away
+
+ pixheight=scale*SPRITESCALEFACTOR;
+ actx=xcenter-scale;
+ upperedge=viewheight/2-scale;
+
+ cmdptr=(word *) shape->dataofs;
+
+ for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++)
+ {
+ lpix=rpix;
+ if(lpix>=viewwidth) break;
+ pixcnt+=pixheight;
+ rpix=(pixcnt>>6)+actx;
+ if(lpix!=rpix && rpix>0)
+ {
+ if(lpix<0) lpix=0;
+ if(rpix>viewwidth) rpix=viewwidth,i=shape->rightpix+1;
+ cline=(byte *)shape + *cmdptr;
+ while(lpix<rpix)
+ {
+ if(wallheight[lpix]<=(int)height)
+ {
+ line=cline;
+ while((endy = READWORD(&line)) != 0)
+ {
+ endy >>= 1;
+ newstart = READWORD(&line);
+ starty = READWORD(&line) >> 1;
+ j=starty;
+ ycnt=j*pixheight;
+ screndy=(ycnt>>6)+upperedge;
+ if(screndy<0) vmem=vbuf+lpix;
+ else vmem=vbuf+screndy*vbufPitch+lpix;
+ for(;j<endy;j++)
+ {
+ scrstarty=screndy;
+ ycnt+=pixheight;
+ screndy=(ycnt>>6)+upperedge;
+ if(scrstarty!=screndy && screndy>0)
+ {
+#ifdef USE_SHADING
+ col=curshades[((byte *)shape)[newstart+j]];
+#else
+ col=((byte *)shape)[newstart+j];
+#endif
+ if(scrstarty<0) scrstarty=0;
+ if(screndy>viewheight) screndy=viewheight,j=endy;
+
+ while(scrstarty<screndy)
+ {
+ *vmem=col;
+ vmem+=vbufPitch;
+ scrstarty++;
+ }
+ }
+ }
+ }
+ }
+ lpix++;
+ }
+ }
+ }
+}
+
+void SimpleScaleShape (int xcenter, int shapenum, unsigned height)
+{
+ t_compshape *shape;
+ unsigned scale,pixheight;
+ unsigned starty,endy;
+ word *cmdptr;
+ byte *cline;
+ byte *line;
+ int actx,i,upperedge;
+ short newstart;
+ int scrstarty,screndy,lpix,rpix,pixcnt,ycnt;
+ unsigned j;
+ byte col;
+ byte *vmem;
+
+ shape = (t_compshape *) PM_GetSprite(shapenum);
+
+ scale=height>>1;
+ pixheight=scale*SPRITESCALEFACTOR;
+ actx=xcenter-scale;
+ upperedge=viewheight/2-scale;
+
+ cmdptr=shape->dataofs;
+
+ for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++)
+ {
+ lpix=rpix;
+ if(lpix>=viewwidth) break;
+ pixcnt+=pixheight;
+ rpix=(pixcnt>>6)+actx;
+ if(lpix!=rpix && rpix>0)
+ {
+ if(lpix<0) lpix=0;
+ if(rpix>viewwidth) rpix=viewwidth,i=shape->rightpix+1;
+ cline = (byte *)shape + *cmdptr;
+ while(lpix<rpix)
+ {
+ line=cline;
+ while((endy = READWORD(&line)) != 0)
+ {
+ endy >>= 1;
+ newstart = READWORD(&line);
+ starty = READWORD(&line) >> 1;
+ j=starty;
+ ycnt=j*pixheight;
+ screndy=(ycnt>>6)+upperedge;
+ if(screndy<0) vmem=vbuf+lpix;
+ else vmem=vbuf+screndy*vbufPitch+lpix;
+ for(;j<endy;j++)
+ {
+ scrstarty=screndy;
+ ycnt+=pixheight;
+ screndy=(ycnt>>6)+upperedge;
+ if(scrstarty!=screndy && screndy>0)
+ {
+ col=((byte *)shape)[newstart+j];
+ if(scrstarty<0) scrstarty=0;
+ if(screndy>viewheight) screndy=viewheight,j=endy;
+
+ while(scrstarty<screndy)
+ {
+ *vmem=col;
+ vmem+=vbufPitch;
+ scrstarty++;
+ }
+ }
+ }
+ }
+ lpix++;
+ }
+ }
+ }
+}
+
+/*
+=====================
+=
+= DrawScaleds
+=
+= Draws all objects that are visable
+=
+=====================
+*/
+
+#define MAXVISABLE 250
+
+typedef struct
+{
+ short viewx,
+ viewheight,
+ shapenum;
+ short flags; // this must be changed to uint32_t, when you
+ // you need more than 16-flags for drawing
+#ifdef USE_DIR3DSPR
+ statobj_t *transsprite;
+#endif
+} visobj_t;
+
+visobj_t vislist[MAXVISABLE];
+visobj_t *visptr,*visstep,*farthest;
+
+void DrawScaleds (void)
+{
+ int i,least,numvisable,height;
+ byte *tilespot,*visspot;
+ unsigned spotloc;
+
+ statobj_t *statptr;
+ objtype *obj;
+
+ visptr = &vislist[0];
+
+//
+// place static objects
+//
+ for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++)
+ {
+ if ((visptr->shapenum = statptr->shapenum) == -1)
+ continue; // object has been deleted
+
+ if (!*statptr->visspot)
+ continue; // not visable
+
+ if (TransformTile (statptr->tilex,statptr->tiley,
+ &visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS)
+ {
+ GetBonus (statptr);
+ if(statptr->shapenum == -1)
+ continue; // object has been taken
+ }
+
+ if (!visptr->viewheight)
+ continue; // to close to the object
+
+#ifdef USE_DIR3DSPR
+ if(statptr->flags & FL_DIR_MASK)
+ visptr->transsprite=statptr;
+ else
+ visptr->transsprite=NULL;
+#endif
+
+ if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
+ {
+ visptr->flags = (short) statptr->flags;
+ visptr++;
+ }
+ }
+
+//
+// place active objects
+//
+ for (obj = player->next;obj;obj=obj->next)
+ {
+ if ((visptr->shapenum = obj->state->shapenum)==0)
+ continue; // no shape
+
+ spotloc = (obj->tilex<<mapshift)+obj->tiley; // optimize: keep in struct?
+ visspot = &spotvis[0][0]+spotloc;
+ tilespot = &tilemap[0][0]+spotloc;
+
+ //
+ // could be in any of the nine surrounding tiles
+ //
+ if (*visspot
+ || ( *(visspot-1) && !*(tilespot-1) )
+ || ( *(visspot+1) && !*(tilespot+1) )
+ || ( *(visspot-65) && !*(tilespot-65) )
+ || ( *(visspot-64) && !*(tilespot-64) )
+ || ( *(visspot-63) && !*(tilespot-63) )
+ || ( *(visspot+65) && !*(tilespot+65) )
+ || ( *(visspot+64) && !*(tilespot+64) )
+ || ( *(visspot+63) && !*(tilespot+63) ) )
+ {
+ obj->active = ac_yes;
+ TransformActor (obj);
+ if (!obj->viewheight)
+ continue; // too close or far away
+
+ visptr->viewx = obj->viewx;
+ visptr->viewheight = obj->viewheight;
+ if (visptr->shapenum == -1)
+ visptr->shapenum = obj->temp1; // special shape
+
+ if (obj->state->rotate)
+ visptr->shapenum += CalcRotate (obj);
+
+ if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
+ {
+ visptr->flags = (short) obj->flags;
+#ifdef USE_DIR3DSPR
+ visptr->transsprite = NULL;
+#endif
+ visptr++;
+ }
+ obj->flags |= FL_VISABLE;
+ }
+ else
+ obj->flags &= ~FL_VISABLE;
+ }
+
+//
+// draw from back to front
+//
+ numvisable = (int) (visptr-&vislist[0]);
+
+ if (!numvisable)
+ return; // no visable objects
+
+ for (i = 0; i<numvisable; i++)
+ {
+ least = 32000;
+ for (visstep=&vislist[0] ; visstep<visptr ; visstep++)
+ {
+ height = visstep->viewheight;
+ if (height < least)
+ {
+ least = height;
+ farthest = visstep;
+ }
+ }
+ //
+ // draw farthest
+ //
+#ifdef USE_DIR3DSPR
+ if(farthest->transsprite)
+ Scale3DShape(vbuf, vbufPitch, farthest->transsprite);
+ else
+#endif
+ ScaleShape(farthest->viewx, farthest->shapenum, farthest->viewheight, farthest->flags);
+
+ farthest->viewheight = 32000;
+ }
+}
+
+//==========================================================================
+
+/*
+==============
+=
+= DrawPlayerWeapon
+=
+= Draw the player's hands
+=
+==============
+*/
+
+int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY, SPR_PISTOLREADY,
+ SPR_MACHINEGUNREADY, SPR_CHAINREADY};
+
+void DrawPlayerWeapon (void)
+{
+ int shapenum;
+
+#ifndef SPEAR
+ if (gamestate.victoryflag)
+ {
+#ifndef APOGEE_1_0
+ if (player->state == &s_deathcam && (GetTimeCount()&32) )
+ SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1);
+#endif
+ return;
+ }
+#endif
+
+ if (gamestate.weapon != -1)
+ {
+ shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe;
+ SimpleScaleShape(viewwidth/2,shapenum,viewheight+1);
+ }
+
+ if (demorecord || demoplayback)
+ SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1);
+}
+
+
+//==========================================================================
+
+
+/*
+=====================
+=
+= CalcTics
+=
+=====================
+*/
+
+void CalcTics (void)
+{
+//
+// calculate tics since last refresh for adaptive timing
+//
+ if (lasttimecount > (int32_t) GetTimeCount())
+ lasttimecount = GetTimeCount(); // if the game was paused a LONG time
+
+ uint32_t curtime = SDL_GetTicks();
+ tics = (curtime * 7) / 100 - lasttimecount;
+ if(!tics)
+ {
+ // wait until end of current tic
+ SDL_Delay(((lasttimecount + 1) * 100) / 7 - curtime);
+ tics = 1;
+ }
+
+ lasttimecount += tics;
+
+ if (tics>MAXTICS)
+ tics = MAXTICS;
+}
+
+
+//==========================================================================
+
+void AsmRefresh()
+{
+ int32_t xstep,ystep;
+ longword xpartial,ypartial;
+ boolean playerInPushwallBackTile = tilemap[focaltx][focalty] == 64;
+
+ for(pixx=0;pixx<viewwidth;pixx++)
+ {
+ short angl=midangle+pixelangle[pixx];
+ if(angl<0) angl+=FINEANGLES;
+ if(angl>=3600) angl-=FINEANGLES;
+ if(angl<900)
+ {
+ xtilestep=1;
+ ytilestep=-1;
+ xstep=finetangent[900-1-angl];
+ ystep=-finetangent[angl];
+ xpartial=xpartialup;
+ ypartial=ypartialdown;
+ }
+ else if(angl<1800)
+ {
+ xtilestep=-1;
+ ytilestep=-1;
+ xstep=-finetangent[angl-900];
+ ystep=-finetangent[1800-1-angl];
+ xpartial=xpartialdown;
+ ypartial=ypartialdown;
+ }
+ else if(angl<2700)
+ {
+ xtilestep=-1;
+ ytilestep=1;
+ xstep=-finetangent[2700-1-angl];
+ ystep=finetangent[angl-1800];
+ xpartial=xpartialdown;
+ ypartial=ypartialup;
+ }
+ else if(angl<3600)
+ {
+ xtilestep=1;
+ ytilestep=1;
+ xstep=finetangent[angl-2700];
+ ystep=finetangent[3600-1-angl];
+ xpartial=xpartialup;
+ ypartial=ypartialup;
+ }
+ yintercept=FixedMul(ystep,xpartial)+viewy;
+ xtile=focaltx+xtilestep;
+ xspot=(word)((xtile<<mapshift)+((uint32_t)yintercept>>16));
+ xintercept=FixedMul(xstep,ypartial)+viewx;
+ ytile=focalty+ytilestep;
+ yspot=(word)((((uint32_t)xintercept>>16)<<mapshift)+ytile);
+ texdelta=0;
+
+ // Special treatment when player is in back tile of pushwall
+ if(playerInPushwallBackTile)
+ {
+ if( pwalldir == di_east && xtilestep == 1
+ || pwalldir == di_west && xtilestep == -1)
+ {
+ int32_t yintbuf = yintercept - ((ystep * (64 - pwallpos)) >> 6);
+ if((yintbuf >> 16) == focalty) // ray hits pushwall back?
+ {
+ if(pwalldir == di_east)
+ xintercept = (focaltx << TILESHIFT) + (pwallpos << 10);
+ else
+ xintercept = (focaltx << TILESHIFT) - TILEGLOBAL + ((64 - pwallpos) << 10);
+ yintercept = yintbuf;
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit = pwalltile;
+ HitVertWall();
+ continue;
+ }
+ }
+ else if(pwalldir == di_south && ytilestep == 1
+ || pwalldir == di_north && ytilestep == -1)
+ {
+ int32_t xintbuf = xintercept - ((xstep * (64 - pwallpos)) >> 6);
+ if((xintbuf >> 16) == focaltx) // ray hits pushwall back?
+ {
+ xintercept = xintbuf;
+ if(pwalldir == di_south)
+ yintercept = (focalty << TILESHIFT) + (pwallpos << 10);
+ else
+ yintercept = (focalty << TILESHIFT) - TILEGLOBAL + ((64 - pwallpos) << 10);
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit = pwalltile;
+ HitHorizWall();
+ continue;
+ }
+ }
+ }
+
+ do
+ {
+ if(ytilestep==-1 && (yintercept>>16)<=ytile) goto horizentry;
+ if(ytilestep==1 && (yintercept>>16)>=ytile) goto horizentry;
+vertentry:
+ if((uint32_t)yintercept>mapheight*65536-1 || (word)xtile>=mapwidth)
+ {
+ if(xtile<0) xintercept=0, xtile=0;
+ else if(xtile>=mapwidth) xintercept=mapwidth<<TILESHIFT, xtile=mapwidth-1;
+ else xtile=(short) (xintercept >> TILESHIFT);
+ if(yintercept<0) yintercept=0, ytile=0;
+ else if(yintercept>=(mapheight<<TILESHIFT)) yintercept=mapheight<<TILESHIFT, ytile=mapheight-1;
+ yspot=0xffff;
+ tilehit=0;
+ HitHorizBorder();
+ break;
+ }
+ if(xspot>=maparea) break;
+ tilehit=((byte *)tilemap)[xspot];
+ if(tilehit)
+ {
+ if(tilehit&0x80)
+ {
+ int32_t yintbuf=yintercept+(ystep>>1);
+ if((yintbuf>>16)!=(yintercept>>16))
+ goto passvert;
+ if((word)yintbuf<doorposition[tilehit&0x7f])
+ goto passvert;
+ yintercept=yintbuf;
+ xintercept=(xtile<<TILESHIFT)|0x8000;
+ ytile = (short) (yintercept >> TILESHIFT);
+ HitVertDoor();
+ }
+ else
+ {
+ if(tilehit==64)
+ {
+ if(pwalldir==di_west || pwalldir==di_east)
+ {
+ int32_t yintbuf;
+ int pwallposnorm;
+ int pwallposinv;
+ if(pwalldir==di_west)
+ {
+ pwallposnorm = 64-pwallpos;
+ pwallposinv = pwallpos;
+ }
+ else
+ {
+ pwallposnorm = pwallpos;
+ pwallposinv = 64-pwallpos;
+ }
+ if(pwalldir == di_east && xtile==pwallx && ((uint32_t)yintercept>>16)==pwally
+ || pwalldir == di_west && !(xtile==pwallx && ((uint32_t)yintercept>>16)==pwally))
+ {
+ yintbuf=yintercept+((ystep*pwallposnorm)>>6);
+ if((yintbuf>>16)!=(yintercept>>16))
+ goto passvert;
+
+ xintercept=(xtile<<TILESHIFT)+TILEGLOBAL-(pwallposinv<<10);
+ yintercept=yintbuf;
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitVertWall();
+ }
+ else
+ {
+ yintbuf=yintercept+((ystep*pwallposinv)>>6);
+ if((yintbuf>>16)!=(yintercept>>16))
+ goto passvert;
+
+ xintercept=(xtile<<TILESHIFT)-(pwallposinv<<10);
+ yintercept=yintbuf;
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitVertWall();
+ }
+ }
+ else
+ {
+ int pwallposi = pwallpos;
+ if(pwalldir==di_north) pwallposi = 64-pwallpos;
+ if(pwalldir==di_south && (word)yintercept<(pwallposi<<10)
+ || pwalldir==di_north && (word)yintercept>(pwallposi<<10))
+ {
+ if(((uint32_t)yintercept>>16)==pwally && xtile==pwallx)
+ {
+ if(pwalldir==di_south && (int32_t)((word)yintercept)+ystep<(pwallposi<<10)
+ || pwalldir==di_north && (int32_t)((word)yintercept)+ystep>(pwallposi<<10))
+ goto passvert;
+
+ if(pwalldir==di_south)
+ yintercept=(yintercept&0xffff0000)+(pwallposi<<10);
+ else
+ yintercept=(yintercept&0xffff0000)-TILEGLOBAL+(pwallposi<<10);
+ xintercept=xintercept-((xstep*(64-pwallpos))>>6);
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitHorizWall();
+ }
+ else
+ {
+ texdelta = -(pwallposi<<10);
+ xintercept=xtile<<TILESHIFT;
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitVertWall();
+ }
+ }
+ else
+ {
+ if(((uint32_t)yintercept>>16)==pwally && xtile==pwallx)
+ {
+ texdelta = -(pwallposi<<10);
+ xintercept=xtile<<TILESHIFT;
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitVertWall();
+ }
+ else
+ {
+ if(pwalldir==di_south && (int32_t)((word)yintercept)+ystep>(pwallposi<<10)
+ || pwalldir==di_north && (int32_t)((word)yintercept)+ystep<(pwallposi<<10))
+ goto passvert;
+
+ if(pwalldir==di_south)
+ yintercept=(yintercept&0xffff0000)-((64-pwallpos)<<10);
+ else
+ yintercept=(yintercept&0xffff0000)+((64-pwallpos)<<10);
+ xintercept=xintercept-((xstep*pwallpos)>>6);
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitHorizWall();
+ }
+ }
+ }
+ }
+ else
+ {
+ xintercept=xtile<<TILESHIFT;
+ ytile = (short) (yintercept >> TILESHIFT);
+ HitVertWall();
+ }
+ }
+ break;
+ }
+passvert:
+ *((byte *)spotvis+xspot)=1;
+ xtile+=xtilestep;
+ yintercept+=ystep;
+ xspot=(word)((xtile<<mapshift)+((uint32_t)yintercept>>16));
+ }
+ while(1);
+ continue;
+
+ do
+ {
+ if(xtilestep==-1 && (xintercept>>16)<=xtile) goto vertentry;
+ if(xtilestep==1 && (xintercept>>16)>=xtile) goto vertentry;
+horizentry:
+ if((uint32_t)xintercept>mapwidth*65536-1 || (word)ytile>=mapheight)
+ {
+ if(ytile<0) yintercept=0, ytile=0;
+ else if(ytile>=mapheight) yintercept=mapheight<<TILESHIFT, ytile=mapheight-1;
+ else ytile=(short) (yintercept >> TILESHIFT);
+ if(xintercept<0) xintercept=0, xtile=0;
+ else if(xintercept>=(mapwidth<<TILESHIFT)) xintercept=mapwidth<<TILESHIFT, xtile=mapwidth-1;
+ xspot=0xffff;
+ tilehit=0;
+ HitVertBorder();
+ break;
+ }
+ if(yspot>=maparea) break;
+ tilehit=((byte *)tilemap)[yspot];
+ if(tilehit)
+ {
+ if(tilehit&0x80)
+ {
+ int32_t xintbuf=xintercept+(xstep>>1);
+ if((xintbuf>>16)!=(xintercept>>16))
+ goto passhoriz;
+ if((word)xintbuf<doorposition[tilehit&0x7f])
+ goto passhoriz;
+ xintercept=xintbuf;
+ yintercept=(ytile<<TILESHIFT)+0x8000;
+ xtile = (short) (xintercept >> TILESHIFT);
+ HitHorizDoor();
+ }
+ else
+ {
+ if(tilehit==64)
+ {
+ if(pwalldir==di_north || pwalldir==di_south)
+ {
+ int32_t xintbuf;
+ int pwallposnorm;
+ int pwallposinv;
+ if(pwalldir==di_north)
+ {
+ pwallposnorm = 64-pwallpos;
+ pwallposinv = pwallpos;
+ }
+ else
+ {
+ pwallposnorm = pwallpos;
+ pwallposinv = 64-pwallpos;
+ }
+ if(pwalldir == di_south && ytile==pwally && ((uint32_t)xintercept>>16)==pwallx
+ || pwalldir == di_north && !(ytile==pwally && ((uint32_t)xintercept>>16)==pwallx))
+ {
+ xintbuf=xintercept+((xstep*pwallposnorm)>>6);
+ if((xintbuf>>16)!=(xintercept>>16))
+ goto passhoriz;
+
+ yintercept=(ytile<<TILESHIFT)+TILEGLOBAL-(pwallposinv<<10);
+ xintercept=xintbuf;
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitHorizWall();
+ }
+ else
+ {
+ xintbuf=xintercept+((xstep*pwallposinv)>>6);
+ if((xintbuf>>16)!=(xintercept>>16))
+ goto passhoriz;
+
+ yintercept=(ytile<<TILESHIFT)-(pwallposinv<<10);
+ xintercept=xintbuf;
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitHorizWall();
+ }
+ }
+ else
+ {
+ int pwallposi = pwallpos;
+ if(pwalldir==di_west) pwallposi = 64-pwallpos;
+ if(pwalldir==di_east && (word)xintercept<(pwallposi<<10)
+ || pwalldir==di_west && (word)xintercept>(pwallposi<<10))
+ {
+ if(((uint32_t)xintercept>>16)==pwallx && ytile==pwally)
+ {
+ if(pwalldir==di_east && (int32_t)((word)xintercept)+xstep<(pwallposi<<10)
+ || pwalldir==di_west && (int32_t)((word)xintercept)+xstep>(pwallposi<<10))
+ goto passhoriz;
+
+ if(pwalldir==di_east)
+ xintercept=(xintercept&0xffff0000)+(pwallposi<<10);
+ else
+ xintercept=(xintercept&0xffff0000)-TILEGLOBAL+(pwallposi<<10);
+ yintercept=yintercept-((ystep*(64-pwallpos))>>6);
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitVertWall();
+ }
+ else
+ {
+ texdelta = -(pwallposi<<10);
+ yintercept=ytile<<TILESHIFT;
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitHorizWall();
+ }
+ }
+ else
+ {
+ if(((uint32_t)xintercept>>16)==pwallx && ytile==pwally)
+ {
+ texdelta = -(pwallposi<<10);
+ yintercept=ytile<<TILESHIFT;
+ xtile = (short) (xintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitHorizWall();
+ }
+ else
+ {
+ if(pwalldir==di_east && (int32_t)((word)xintercept)+xstep>(pwallposi<<10)
+ || pwalldir==di_west && (int32_t)((word)xintercept)+xstep<(pwallposi<<10))
+ goto passhoriz;
+
+ if(pwalldir==di_east)
+ xintercept=(xintercept&0xffff0000)-((64-pwallpos)<<10);
+ else
+ xintercept=(xintercept&0xffff0000)+((64-pwallpos)<<10);
+ yintercept=yintercept-((ystep*pwallpos)>>6);
+ ytile = (short) (yintercept >> TILESHIFT);
+ tilehit=pwalltile;
+ HitVertWall();
+ }
+ }
+ }
+ }
+ else
+ {
+ yintercept=ytile<<TILESHIFT;
+ xtile = (short) (xintercept >> TILESHIFT);
+ HitHorizWall();
+ }
+ }
+ break;
+ }
+passhoriz:
+ *((byte *)spotvis+yspot)=1;
+ ytile+=ytilestep;
+ xintercept+=xstep;
+ yspot=(word)((((uint32_t)xintercept>>16)<<mapshift)+ytile);
+ }
+ while(1);
+ }
+}
+
+/*
+====================
+=
+= WallRefresh
+=
+====================
+*/
+
+void WallRefresh (void)
+{
+ xpartialdown = viewx&(TILEGLOBAL-1);
+ xpartialup = TILEGLOBAL-xpartialdown;
+ ypartialdown = viewy&(TILEGLOBAL-1);
+ ypartialup = TILEGLOBAL-ypartialdown;
+
+ min_wallheight = viewheight;
+ lastside = -1; // the first pixel is on a new wall
+ AsmRefresh ();
+ ScalePost (); // no more optimization on last post
+}
+
+void CalcViewVariables()
+{
+ viewangle = player->angle;
+ midangle = viewangle*(FINEANGLES/ANGLES);
+ viewsin = sintable[viewangle];
+ viewcos = costable[viewangle];
+ viewx = player->x - FixedMul(focallength,viewcos);
+ viewy = player->y + FixedMul(focallength,viewsin);
+
+ focaltx = (short)(viewx>>TILESHIFT);
+ focalty = (short)(viewy>>TILESHIFT);
+
+ viewtx = (short)(player->x >> TILESHIFT);
+ viewty = (short)(player->y >> TILESHIFT);
+}
+
+//==========================================================================
+
+/*
+========================
+=
+= ThreeDRefresh
+=
+========================
+*/
+
+void ThreeDRefresh (void)
+{
+//
+// clear out the traced array
+//
+ memset(spotvis,0,maparea);
+ spotvis[player->tilex][player->tiley] = 1; // Detect all sprites over player fix
+
+ vbuf = VL_LockSurface(screenBuffer);
+ vbuf+=screenofs;
+ vbufPitch = bufferPitch;
+
+ CalcViewVariables();
+
+//
+// follow the walls from there to the right, drawing as we go
+//
+ VGAClearScreen ();
+#if defined(USE_FEATUREFLAGS) && defined(USE_STARSKY)
+ if(GetFeatureFlags() & FF_STARSKY)
+ DrawStarSky(vbuf, vbufPitch);
+#endif
+
+ WallRefresh ();
+
+#if defined(USE_FEATUREFLAGS) && defined(USE_PARALLAX)
+ if(GetFeatureFlags() & FF_PARALLAXSKY)
+ DrawParallax(vbuf, vbufPitch);
+#endif
+#if defined(USE_FEATUREFLAGS) && defined(USE_CLOUDSKY)
+ if(GetFeatureFlags() & FF_CLOUDSKY)
+ DrawClouds(vbuf, vbufPitch, min_wallheight);
+#endif
+#ifdef USE_FLOORCEILINGTEX
+ DrawFloorAndCeiling(vbuf, vbufPitch, min_wallheight);
+#endif
+
+//
+// draw all the scaled images
+//
+ DrawScaleds(); // draw scaled stuff
+
+#if defined(USE_FEATUREFLAGS) && defined(USE_RAIN)
+ if(GetFeatureFlags() & FF_RAIN)
+ DrawRain(vbuf, vbufPitch);
+#endif
+#if defined(USE_FEATUREFLAGS) && defined(USE_SNOW)
+ if(GetFeatureFlags() & FF_SNOW)
+ DrawSnow(vbuf, vbufPitch);
+#endif
+
+ DrawPlayerWeapon (); // draw player's hands
+
+ if(Keyboard[sc_Tab] && viewsize == 21 && gamestate.weapon != -1)
+ ShowActStatus();
+
+ VL_UnlockSurface(screenBuffer);
+ vbuf = NULL;
+
+//
+// show screen and time last cycle
+//
+
+ if (fizzlein)
+ {
+ FizzleFade(screenBuffer, 0, 0, screenWidth, screenHeight, 20, false);
+ fizzlein = false;
+
+ lasttimecount = GetTimeCount(); // don't make a big tic count
+ }
+ else
+ {
+#ifndef REMDEBUG
+ if (fpscounter)
+ {
+ fontnumber = 0;
+ SETFONTCOLOR(7,127);
+ PrintX=4; PrintY=1;
+ VWB_Bar(0,0,50,10,bordercol);
+ US_PrintSigned(fps);
+ US_Print(" fps");
+ }
+#endif
+ SDL_BlitSurface(screenBuffer, NULL, screen, NULL);
+ SDL_Flip(screen);
+ }
+
+#ifndef REMDEBUG
+ if (fpscounter)
+ {
+ fps_frames++;
+ fps_time+=tics;
+
+ if(fps_time>35)
+ {
+ fps_time-=35;
+ fps=fps_frames<<1;
+ fps_frames=0;
+ }
+ }
+#endif
+}