summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/wolf3d/wl_draw.c
diff options
context:
space:
mode:
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 @@
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
31static byte *vbuf = NULL;
32unsigned vbufPitch = 0;
33
34int32_t lasttimecount;
35int32_t frameon;
36boolean fpscounter;
37
38int fps_frames=0, fps_time=0, fps=0;
39
40int *wallheight;
41int min_wallheight;
42
43//
44// math tables
45//
46short *pixelangle;
47int32_t finetangent[FINEANGLES/4];
48fixed sintable[ANGLES+ANGLES/4];
49fixed *costable = sintable+(ANGLES/4);
50
51//
52// refresh variables
53//
54fixed viewx,viewy; // the focal point
55short viewangle;
56fixed viewsin,viewcos;
57
58void TransformActor (objtype *ob);
59void BuildTables (void);
60void ClearScreen (void);
61int CalcRotate (objtype *ob);
62void DrawScaleds (void);
63void CalcTics (void);
64void ThreeDRefresh (void);
65
66
67
68//
69// wall optimization variables
70//
71int lastside; // true for vertical
72int32_t lastintercept;
73int lasttilehit;
74int lasttexture;
75
76//
77// ray tracing variables
78//
79short focaltx,focalty,viewtx,viewty;
80longword xpartialup,xpartialdown,ypartialup,ypartialdown;
81
82short midangle,angle;
83
84word tilehit;
85int pixx;
86
87short xtile,ytile;
88short xtilestep,ytilestep;
89int32_t xintercept,yintercept;
90word xstep,ystep;
91word xspot,yspot;
92int texdelta;
93
94word 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//
128void 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
197boolean 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
254int 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
274byte *postsource;
275int postx;
276int postwidth;
277
278void 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
338void 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
356void 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
422void 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
485void 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
550void 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
612byte 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
636void 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
665int 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
691void 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
782void 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
868typedef 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
880visobj_t vislist[MAXVISABLE];
881visobj_t *visptr,*visstep,*farthest;
882
883void 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
1028int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY, SPR_PISTOLREADY,
1029 SPR_MACHINEGUNREADY, SPR_CHAINREADY};
1030
1031void 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
1068void 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
1094void 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;
1192vertentry:
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 }
1334passvert:
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;
1347horizentry:
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 }
1489passhoriz:
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
1507void 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
1520void 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
1546void 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 vbuf+=screenofs;
1556 vbufPitch = bufferPitch;
1557
1558 CalcViewVariables();
1559
1560//
1561// follow the walls from there to the right, drawing as we go
1562//
1563 VGAClearScreen ();
1564#if defined(USE_FEATUREFLAGS) && defined(USE_STARSKY)
1565 if(GetFeatureFlags() & FF_STARSKY)
1566 DrawStarSky(vbuf, vbufPitch);
1567#endif
1568
1569 WallRefresh ();
1570
1571#if defined(USE_FEATUREFLAGS) && defined(USE_PARALLAX)
1572 if(GetFeatureFlags() & FF_PARALLAXSKY)
1573 DrawParallax(vbuf, vbufPitch);
1574#endif
1575#if defined(USE_FEATUREFLAGS) && defined(USE_CLOUDSKY)
1576 if(GetFeatureFlags() & FF_CLOUDSKY)
1577 DrawClouds(vbuf, vbufPitch, min_wallheight);
1578#endif
1579#ifdef USE_FLOORCEILINGTEX
1580 DrawFloorAndCeiling(vbuf, vbufPitch, min_wallheight);
1581#endif
1582
1583//
1584// draw all the scaled images
1585//
1586 DrawScaleds(); // draw scaled stuff
1587
1588#if defined(USE_FEATUREFLAGS) && defined(USE_RAIN)
1589 if(GetFeatureFlags() & FF_RAIN)
1590 DrawRain(vbuf, vbufPitch);
1591#endif
1592#if defined(USE_FEATUREFLAGS) && defined(USE_SNOW)
1593 if(GetFeatureFlags() & FF_SNOW)
1594 DrawSnow(vbuf, vbufPitch);
1595#endif
1596
1597 DrawPlayerWeapon (); // draw player's hands
1598
1599 if(Keyboard[sc_Tab] && viewsize == 21 && gamestate.weapon != -1)
1600 ShowActStatus();
1601
1602 VL_UnlockSurface(screenBuffer);
1603 vbuf = NULL;
1604
1605//
1606// show screen and time last cycle
1607//
1608
1609 if (fizzlein)
1610 {
1611 FizzleFade(screenBuffer, 0, 0, screenWidth, screenHeight, 20, false);
1612 fizzlein = false;
1613
1614 lasttimecount = GetTimeCount(); // don't make a big tic count
1615 }
1616 else
1617 {
1618#ifndef REMDEBUG
1619 if (fpscounter)
1620 {
1621 fontnumber = 0;
1622 SETFONTCOLOR(7,127);
1623 PrintX=4; PrintY=1;
1624 VWB_Bar(0,0,50,10,bordercol);
1625 US_PrintSigned(fps);
1626 US_Print(" fps");
1627 }
1628#endif
1629 SDL_BlitSurface(screenBuffer, NULL, screen, NULL);
1630 SDL_Flip(screen);
1631 }
1632
1633#ifndef REMDEBUG
1634 if (fpscounter)
1635 {
1636 fps_frames++;
1637 fps_time+=tics;
1638
1639 if(fps_time>35)
1640 {
1641 fps_time-=35;
1642 fps=fps_frames<<1;
1643 fps_frames=0;
1644 }
1645 }
1646#endif
1647}