1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // RT_DRAW.C
21 
22 #include "profile.h"
23 #include "rt_def.h"
24 #include <string.h>
25 
26 #ifdef DOS
27 #include <dos.h>
28 #include <conio.h>
29 #endif
30 
31 #include "watcom.h"
32 #include "sprites.h"
33 #include "rt_actor.h"
34 #include "rt_stat.h"
35 #include "rt_draw.h"
36 #include "_rt_draw.h"
37 #include "rt_dr_a.h"
38 #include "rt_fc_a.h"
39 #include "rt_scale.h"
40 #include "rt_floor.h"
41 #include "rt_main.h"
42 #include "rt_playr.h"
43 #include "rt_door.h"
44 #include "rt_ted.h"
45 #include "isr.h"
46 #include "rt_util.h"
47 #include "engine.h"
48 #include "z_zone.h"
49 #include "w_wad.h"
50 #include "lumpy.h"
51 #include "rt_menu.h"
52 #include "rt_game.h"
53 #include "rt_vid.h"
54 #include "rt_view.h"
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include "rt_cfg.h"
58 #include "rt_str.h"
59 #include "develop.h"
60 #include "rt_sound.h"
61 #include "rt_msg.h"
62 #include "modexlib.h"
63 #include "rt_rand.h"
64 #include "rt_net.h"
65 #include "rt_sc_a.h"
66 //MED
67 #include "memcheck.h"
68 
69 /*
70 =============================================================================
71 
72 Global Variables                                                                                                                                 GLOBAL VARIABLES
73 
74 =============================================================================
75 */
76 
77 int whereami=-1;
78 
79 byte * shadingtable;
80 
81 word   tilemap[MAPSIZE][MAPSIZE]; // wall values only
82 byte   spotvis[MAPSIZE][MAPSIZE];
83 byte   mapseen[MAPSIZE][MAPSIZE];
84 unsigned long * lights;
85 
86 int         wstart;
87 
88 
89 const int dirangle8[9] = {0,FINEANGLES/8,2*FINEANGLES/8,3*FINEANGLES/8,4*FINEANGLES/8,
90                      5*FINEANGLES/8,6*FINEANGLES/8,7*FINEANGLES/8,8*FINEANGLES/8};
91 
92 const int dirangle16[16] = {0,FINEANGLES/16,2*FINEANGLES/16,3*FINEANGLES/16,
93 							  4*FINEANGLES/16,5*FINEANGLES/16,6*FINEANGLES/16,
94 							  7*FINEANGLES/16,8*FINEANGLES/16,9*FINEANGLES/16,
95 							  10*FINEANGLES/16,11*FINEANGLES/16,12*FINEANGLES/16,
96 							  13*FINEANGLES/16,14*FINEANGLES/16,15*FINEANGLES/16};
97 
98 //
99 // math tables
100 //
101 
102 short   tantable[FINEANGLES];
103 long    sintable[FINEANGLES+FINEANGLEQUAD+1],
104 		  *costable = sintable+(FINEANGLES/4);
105 
106 //
107 // refresh variables
108 //
109 
110 fixed   viewx,viewy;                                                     // the focal point
111 int     viewangle;
112 int     c_startx, c_starty;
113 fixed   viewsin,viewcos;
114 int     tics;
115 
116 //
117 // ray tracing variables
118 //
119 
120 long    xintercept,yintercept;
121 
122 int doublestep=0;
123 int hp_startfrac;
124 int hp_srcstep;
125 
126 int levelheight;
127 
128 int actortime=0;
129 int drawtime=0;
130 
131 visobj_t vislist[MAXVISIBLE],*visptr,*visstep,*farthest;
132 
133 int firstcoloffset=0;
134 
135 /*
136 ==================
137 =
138 = Local Variables
139 =
140 ==================
141 */
142 static int nonbobpheight;
143 
144 static visobj_t * sortedvislist[MAXVISIBLE];
145 
146 static const fixed mindist = 0x1000;
147 
148 static int walltime=0;
149 
150 static int weaponbobx, weaponboby;
151 
152 static int      pretics[3];
153 static int      preindex;
154 static int      netlump;
155 static int      gmasklump;
156 
157 static const int weaponshape[NUMWEAPGRAPHICS] =
158      {
159 #if (SHAREWARE == 0)
160 
161       W_KNIFE,
162 #endif
163 
164       W_MALEPISTOL1,
165 		W_MRIGHTPISTOL1,
166 		W_MP40,
167 		W_BAZOOKA,
168 		W_HEATSEEKER,
169       W_DRUNK,
170       W_FIREBOMB,
171       W_FIREWALL,
172 		W_GODHAND,
173 
174 
175 #if (SHAREWARE == 0)
176 		W_SPLIT,
177 		W_KES,
178 		W_BAT,
179       W_DOG,
180 		W_FEMALEPISTOL1,
181 		W_BMALEPISTOL1
182 #endif
183 		};
184 
185 void SetColorLightLevel (int x, int y, visobj_t * sprite, int dir, int color, int fullbright);
186 void DrawRotatedScreen(int cx, int cy, byte *destscreen, int angle, int scale, int masked);
187 void InterpolateMaskedWall (visobj_t * plane);
188 void InterpolateDoor (visobj_t * plane);
189 void InterpolateWall (visobj_t * plane);
190 
191 /*
192 ==================
193 =
194 = BuildTables
195 =
196 ==================
197 */
198 
BuildTables(void)199 void BuildTables (void)
200 {
201   byte * table;
202   byte * ptr;
203   long  length;
204   int   i;
205 
206 //
207 // load in tables file
208 //
209 
210    table=W_CacheLumpName("tables",PU_STATIC, CvtNull, 1);
211    ptr=table;
212 
213 //
214 // get size of first table
215 //
216 
217    memcpy(&length,ptr,sizeof(int));
218    SwapIntelLong(&length);
219 
220 //
221 // skip first table
222 //
223 
224    ptr+=(length+1)*sizeof(int);
225 
226 //
227 // get size of sin/cos table
228 //
229 
230    memcpy(&length,ptr,sizeof(int));
231    SwapIntelLong(&length);
232    ptr+=sizeof(int);
233 
234 //
235 // get sin/cos table
236 //
237    memcpy(&sintable[0],ptr,length*sizeof(long));
238    SwapIntelLongArray(&sintable[0], length);
239    ptr+=(length)*sizeof(int);
240 
241 //
242 // get size of tangent table
243 //
244 
245    memcpy(&length,ptr,sizeof(int));
246    SwapIntelLong(&length);
247    ptr+=sizeof(int);
248 
249 //
250 // get tangent table
251 //
252    memcpy(tantable,ptr,length*sizeof(short));
253    SwapIntelShortArray(tantable, length);
254    ptr+=(length)*sizeof(short);
255 
256 //
257 // get size of gamma table
258 //
259 
260    memcpy(&length,ptr,sizeof(int));
261    SwapIntelLong(&length);
262    ptr+=sizeof(int);
263 
264 //
265 // get gamma table
266 //
267    memcpy(&gammatable[0],ptr,length*sizeof(byte));
268    table=W_CacheLumpName("tables",PU_CACHE, CvtNull, 1);
269 
270    costable = (fixed *)&(sintable[FINEANGLES/4]);
271 
272    wstart=W_GetNumForName("WALLSTRT");
273 #if (SHAREWARE==0)
274    netlump=W_GetNumForName("net1");
275 #endif
276    gmasklump=W_GetNumForName("p_gmask");
277 
278    preindex=0;
279    pretics[0]=0x10000;
280    pretics[2]=0x10000;
281    pretics[1]=0x10000;
282 
283    for(i=0;i<ANGLES;i++)
284     {angletodir[i] = (i + (ANGLES/16))/(ANGLES/8);
285      if (angletodir[i] == 8)
286 		angletodir[i] = 0;
287 	 }
288 
289    // Check out VENDOR.DOC file
290    CheckVendor();
291 
292    if (!quiet)
293       printf("RT_DRAW: Tables Initialized\n");
294 }
295 
296 
297 /*
298 ========================
299 =
300 = TransformObject
301 =
302 ========================
303 */
304 
TransformObject(int x,int y,int * dispx,int * dispheight)305 boolean TransformObject (int x, int y, int *dispx, int *dispheight)
306 {
307 
308   fixed gx,gy,gxt,gyt,nx,ny;
309 
310 
311 //
312 // translate point to view centered coordinates
313 //
314   gx = x-viewx;
315   gy = y-viewy;
316 
317 //
318 // calculate newx
319 //
320   gxt = FixedMul(gx,viewcos);
321   gyt = FixedMul(gy,viewsin);
322   nx = gxt-gyt;
323 
324   if (nx<MINZ)
325      return false;
326 
327   // the midpoint could put parts of the shape
328   // into an adjacent wall
329   //
330   // calculate newy
331   //
332   gxt = FixedMul(gx,viewsin);
333   gyt = FixedMul(gy,viewcos);
334   ny = gyt+gxt;
335 
336 
337 //
338 // calculate perspective ratio
339 //
340 
341   *dispx = centerx + ny*scale/nx;            // DEBUG: use assembly divide
342 
343   *dispheight = heightnumerator/nx;
344 
345   return true;
346 }
347 
348 
349 /*
350 ========================
351 =
352 = TransformPoint
353 =
354 ========================
355 */
356 
TransformPoint(int x,int y,int * screenx,int * height,int * texture,int vertical)357 void TransformPoint (int x, int y, int * screenx, int * height, int * texture, int vertical)
358 {
359 
360   fixed gxt,gyt,nx,ny;
361   fixed gxtt,gytt;
362   int gx,gy;
363   int vx,vy;
364   int svs,svc;
365 
366 
367 //
368 // translate point to view centered coordinates
369 //
370   gx = x-viewx;
371   gy = y-viewy;
372 
373 //
374 // calculate newx
375 //
376   gxt = FixedMul(gx,viewcos);
377   gyt = FixedMul(gy,viewsin);
378   nx =gxt-gyt;
379 
380   if (nx<10)
381      nx=10;
382 
383 
384 //
385 // calculate newy
386 //
387   gxtt = FixedMul(gx,viewsin);
388   gytt = FixedMul(gy,viewcos);
389   ny = gytt+gxtt;
390 
391 // too close, don't overflow the divid'
392 
393 
394   *screenx = centerx + ((ny*scale)/nx);            // DEBUG: use assembly divide
395 
396   *height = heightnumerator/nx;
397 
398 
399   if (*screenx<0)
400      {
401      svc=(-centerx)*viewcos;
402      svs=(-centerx)*viewsin;
403      vx=(scale*viewcos)+svs;
404      vy=(-scale*viewsin)+svc;
405      if (vertical)
406         {
407         if ((viewcos-viewsin)==0)
408            {
409            *height=20000<<HEIGHTFRACTION;
410            return;
411            }
412         gy=FixedScale(gx,vy,vx);
413         y=gy+viewy;
414         gyt = FixedMul(gy,viewsin);
415 		  nx =gxt-gyt;
416         if (nx<10)
417            nx=10;
418         *screenx = 0;
419         *height = heightnumerator/nx;
420 		  }
421      else
422         {
423         if ((-viewsin-viewcos)==0)
424            {
425            *height=20000<<HEIGHTFRACTION;
426            return;
427            }
428         gx=FixedScale(gy,vx,vy);
429         x=gx+viewx;
430         gxt = FixedMul(gx,viewcos);
431         nx =gxt-gyt;
432         if (nx<10)
433            nx=10;
434         *screenx = 0;
435         *height = heightnumerator/nx;
436         }
437 	  }
438   else if (*screenx>=viewwidth)
439      {
440      svc=(centerx)*viewcos;
441      svs=(centerx)*viewsin;
442      vx=(scale*viewcos)+svs;
443      vy=(-scale*viewsin)+svc;
444      if (vertical)
445         {
446         if ((viewcos+viewsin)==0)
447            {
448            *height=20000<<HEIGHTFRACTION;
449            return;
450            }
451         gy=FixedScale(gx,vy,vx);
452         y=gy+viewy;
453         gyt = FixedMul(gy,viewsin);
454         nx =gxt-gyt;
455         if (nx<10)
456 			  nx=10;
457         *screenx = viewwidth-1;
458         *height = heightnumerator/nx;
459         }
460      else
461         {
462         if ((-viewsin+viewcos)==0)
463            {
464            *height=20000<<HEIGHTFRACTION;
465            return;
466            }
467         gx=FixedScale(gy,vx,vy);
468         x=gx+viewx;
469 		  gxt = FixedMul(gx,viewcos);
470         nx =gxt-gyt;
471         if (nx<10)
472            nx=10;
473         *screenx = viewwidth-1;
474         *height = heightnumerator/nx;
475         }
476      }
477   if (vertical)
478      *texture=(y-*texture)&0xffff;
479   else
480      *texture=(x-*texture)&0xffff;
481 }
482 
483 /*
484 ========================
485 =
486 = TransformSimplePoint
487 =
488 ========================
489 */
490 
TransformSimplePoint(int x,int y,int * screenx,int * height,int * texture,int vertical)491 boolean TransformSimplePoint (int x, int y, int * screenx, int * height, int * texture, int vertical)
492 {
493 
494   fixed gxt,gyt,nx,ny;
495   fixed gxtt,gytt;
496   int gx,gy;
497 
498 
499 //
500 // translate point to view centered coordinates
501 //
502   gx = x-viewx;
503   gy = y-viewy;
504 
505 //
506 // calculate newx
507 //
508   gxt = FixedMul(gx,viewcos);
509   gyt = FixedMul(gy,viewsin);
510   nx =gxt-gyt;
511 
512   if (nx<MINZ)
513      return false;
514 
515 
516 //
517 // calculate newy
518 //
519   gxtt = FixedMul(gx,viewsin);
520   gytt = FixedMul(gy,viewcos);
521   ny = gytt+gxtt;
522 
523 // too close, don't overflow the divid'
524 
525 
526   *screenx = centerx + ((ny*scale)/nx);            // DEBUG: use assembly divide
527 
528   *height = heightnumerator/nx;
529 
530   if (vertical)
531      *texture=(y-*texture)&0xffff;
532   else
533      *texture=(x-*texture)&0xffff;
534 
535   return true;
536 }
537 
538 
539 /*
540 ========================
541 =
542 = TransformPlane
543 =
544 ========================
545 */
546 
TransformPlane(int x1,int y1,int x2,int y2,visobj_t * plane)547 boolean TransformPlane (int x1, int y1, int x2, int y2, visobj_t * plane)
548 {
549   boolean result2;
550   boolean result1;
551   boolean vertical;
552   int txstart,txend;
553 
554   vertical=((x2-x1)==0);
555   plane->viewx=vertical;
556   txstart=plane->texturestart;
557   txend=plane->textureend;
558   result1=TransformSimplePoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
559   result2=TransformSimplePoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
560   if (result1==true)
561      {
562      if (plane->x1>=viewwidth)
563         return false;
564      if (result2==false)
565         {
566         plane->textureend=txend;
567         TransformPoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
568         }
569 	  }
570   else
571      {
572      if (result2==false)
573         return false;
574      else
575         {
576         if (plane->x2<0)
577            return false;
578         plane->texturestart=txstart;
579 		  TransformPoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
580         }
581      }
582   if (plane->x1<0)
583      {
584      plane->texturestart=txstart;
585      TransformPoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
586      }
587   if (plane->x2>=viewwidth)
588      {
589      plane->textureend=txend;
590      TransformPoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
591      }
592 
593   plane->viewheight=(plane->h1+plane->h2)>>1;
594 
595   if ((plane->viewheight>=(2000<<HEIGHTFRACTION)) || (plane->x1>=viewwidth-1) || (plane->x2<=0))
596      return false;
597 
598   return true;
599 }
600 
601 //==========================================================================
602 
603 /*
604 ====================
605 =
606 = CalcHeight
607 =
608 = Calculates the height of xintercept,yintercept from viewx,viewy
609 =
610 ====================
611 */
612 
CalcHeight(void)613 int       CalcHeight (void)
614 {
615         fixed  gxt,gyt,nx;
616    long            gx,gy;
617 
618    whereami=0;
619 
620    gx = xintercept-viewx;
621    gxt = FixedMul(gx,viewcos);
622 
623    gy = yintercept-viewy;
624    gyt = FixedMul(gy,viewsin);
625 
626    nx = gxt-gyt;
627 
628 	if (nx<mindist)
629 		nx=mindist; // don't let divide overflo'
630 
631 	return (heightnumerator/nx);
632 }
633 
634 
635 
636 #if 0
637 //==========================================================================
638 
639 //******************************************************************************
640 //
641 // NextPlaneptr
642 //
643 //******************************************************************************
644 
645 void NextPlaneptr ( void )
646 {
647    if (planeptr < &planelist[MAXPLANES-1]) // don't let it overflo'
648   		planeptr++;
649 }
650 
651 //******************************************************************************
652 //
653 // RestPlaneptr
654 //
655 //******************************************************************************
656 
657 void ResetPlaneptr ( void )
658 {
659    planeptr = &planelist[0];
660 }
661 
662 //******************************************************************************
663 //
664 // NextVisptr
665 //
666 //******************************************************************************
667 
668 void NextVisptr ( void )
669 {
670    if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
671   		visptr++;
672 }
673 
674 //******************************************************************************
675 //
676 // ResetVisptr
677 //
678 //******************************************************************************
679 
680 void ResetVisptr ( void )
681 {
682    visptr = &vislist[0];
683 }
684 
685 #endif
686 
687 //==========================================================================
688 
689 
690 
691 /*
692 =====================
693 =
694 = StatRotate
695 =
696 =====================
697 */
698 
StatRotate(statobj_t * temp)699 int  StatRotate (statobj_t *temp)
700 {
701 	int    angle;
702 	int    dx,dy;
703 
704    whereami=2;
705 
706 	dx = temp->x - player->x;
707 	dy = player->y - temp->y;
708 	angle = atan2_appx(dx,dy);
709 
710 	angle = angle-VANG180-dirangle8[temp->count];
711 	angle+=ANGLES/16;
712 	while (angle>=ANGLES)
713 		angle-=ANGLES;
714 	while (angle<0)
715 		angle+=ANGLES;
716 
717 	return angle/(ANGLES/8);
718 
719 }
720 
721 
722 
723 
724 /*
725 =====================
726 =
727 = CalcRotate
728 =
729 =====================
730 */
731 
CalcRotate(objtype * ob)732 int   CalcRotate (objtype *ob)
733 {
734 	int    angle,viewangle;
735 	int    dx,dy;
736 	int    rotation;
737 
738    whereami=1;
739 
740 	// this isn't exactly correct, as it should vary by a trig value'
741 	// but it is close enough with only eight rotations
742 	/*
743 	if (ob->obclass == b_robobossobj)
744 		viewangle = player->angle;
745 	else
746 		viewangle = player->angle + (centerx - ob->viewx)/8;*/
747 	dx = ob->x - player->x;
748 	dy = player->y - ob->y;
749 	viewangle = atan2_appx(dx,dy);
750 
751 	if ((ob->obclass >= p_bazookaobj) || (ob->obclass == missileobj))
752 	  {angle = viewangle - ob->angle;
753 		#if (0)
754 		 Debug("\nviewangle: %d, angle: %d",viewangle,angle);
755 		#endif
756 	  }
757 	else if ((ob->obclass > wallopobj) && (ob->obclass != b_darksnakeobj))
758 		angle =  (viewangle-ANG180)- ob->angle;
759 	else if (ob->state->rotate == 16)
760 		angle =  (viewangle-ANG180)- dirangle16[ob->dir];
761 	else
762 		angle =  (viewangle-ANG180)- dirangle8[ob->dir];
763 
764 	if (ob->state->rotate == true)
765 	  angle += ANGLES/16;
766 	else if (ob->state->rotate == 16)
767 	  angle += ANGLES/32;
768 
769 	while (angle>=ANGLES)
770 		angle-=ANGLES;
771 	while (angle<0)
772 		angle+=ANGLES;
773 
774 	if (ob->state->rotate == 2)        // 2 rotation pain frame
775 		{rotation = 4*(angle/(ANG180));
776 		 return rotation;
777 		}
778 
779 	if (ob->state->rotate == 16)
780 	  {rotation = angle/(ANGLES/16);
781 		#if (0)
782 		 Debug("\nrotation: %d", rotation);
783 		#endif
784 		return rotation;
785 	  }
786 	rotation = angle/(ANGLES/8);
787 	return rotation;
788 
789 }
790 
791 
792 
793 #if 0
794 /*
795 =====================
796 =
797 = DrawMaskedWalls
798 =
799 =====================
800 */
801 
802 void DrawMaskedWalls (void)
803 {
804 
805 
806   int   i,numvisible;
807   int   gx,gy;
808   unsigned short int  *tilespot;
809   byte   *visspot;
810   boolean result;
811   statobj_t *statptr;
812   objtype   *obj;
813   maskedwallobj_t* tmwall;
814 
815 	whereami=6;
816 
817 //
818 // place maskwall objects
819 //
820   for(tmwall=FIRSTMASKEDWALL;tmwall;tmwall=tmwall->next)
821 	  {
822 	  if (spotvis[tmwall->tilex][tmwall->tiley])
823 		  {
824 		  mapseen[tmwall->tilex][tmwall->tiley]=1;
825 		  if (tmwall->vertical)
826 			  {
827 			  gx=(tmwall->tilex<<16)+0x8000;
828 			  gy=(tmwall->tiley<<16);
829 			  visptr->texturestart=0;
830 			  visptr->textureend=0;
831 			  if (viewx<gx)
832 				  result=TransformPlane(gx,gy,gx,gy+0xffff,visptr);
833 			  else
834 				  result=TransformPlane(gx,gy+0xffff,gx,gy,visptr);
835 			  visptr->shapenum=tmwall->bottomtexture;
836 			  visptr->altshapenum=tmwall->midtexture;
837 			  visptr->viewx=tmwall->toptexture;
838 			  visptr->shapesize=2;
839 			  }
840 		  else
841 			  {
842 			  gx=(tmwall->tilex<<16);
843 			  gy=(tmwall->tiley<<16)+0x8000;
844 			  visptr->texturestart=0;
845 			  visptr->textureend=0;
846 			  if (viewy<gy)
847 				  result=TransformPlane(gx+0xffff,gy,gx,gy,visptr);
848 			  else
849 				  result=TransformPlane(gx,gy,gx+0xffff,gy,visptr);
850 			  visptr->shapenum=tmwall->bottomtexture;
851 			  visptr->altshapenum=tmwall->midtexture;
852 			  visptr->viewx=tmwall->toptexture;
853 			  visptr->shapesize=2;
854 			  }
855 		  if ((tmwall->flags&MW_TOPFLIPPING) &&
856             (nonbobpheight>64)
857 			  )
858 			  {
859 			  visptr->viewx++;
860 			  }
861 		  else if ((tmwall->flags&MW_BOTTOMFLIPPING) &&
862                  (nonbobpheight>maxheight-32)
863 					 )
864 			  {
865 			  visptr->shapenum++;
866 			  }
867 		  if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
868 			  visptr++;
869 		  }
870 	  }
871 }
872 #endif
873 
874 /*
875 ======================
876 =
877 = SortScaleds
878 = Sort the scaleds using a HEAPSORT
879 =
880 ======================
881 */
882 
883 #define SGN(x)          ((x>0) ? (1) : ((x==0) ? (0) : (-1)))
884 
885 /*--------------------------------------------------------------------------*/
CompareHeights(s1p,s2p)886 int CompareHeights(s1p,s2p) visobj_t **s1p,**s2p;
887 {
888    whereami=3;
889    return SGN((*s1p)->viewheight-(*s2p)->viewheight);
890 }
891 
SwitchPointers(s1p,s2p)892 void SwitchPointers(s1p,s2p) visobj_t **s1p,**s2p;
893 {
894    visobj_t * temp;
895 
896    whereami=4;
897    temp=*s1p;
898    *s1p=*s2p;
899    *s2p=temp;
900 }
901 
902 
SortVisibleList(int numvisible,visobj_t * vlist)903 void SortVisibleList( int numvisible, visobj_t * vlist )
904 {
905    int i;
906 
907    whereami=5;
908    for (i=0;i<numvisible;i++)
909       sortedvislist[i]=&(vlist[i]);
910    hsort((char *)&(sortedvislist[0]),numvisible,sizeof(visobj_t *),&CompareHeights,&SwitchPointers);
911 }
912 
913 /*
914 =====================
915 =
916 = DrawScaleds
917 =
918 = Draws all objects that are visible
919 =
920 =====================
921 */
922 
923 #define HF_1 (24)
924 #define HF_2 (72)
925 
DrawScaleds(void)926 void DrawScaleds (void)
927 {
928 
929 
930   int   i,numvisible;
931   int   gx,gy;
932   unsigned short int  *tilespot;
933   byte   *visspot;
934   boolean result;
935   statobj_t *statptr;
936   objtype   *obj;
937   maskedwallobj_t* tmwall;
938 
939 	whereami=6;
940 
941 //
942 // place maskwall objects
943 //
944   for(tmwall=FIRSTMASKEDWALL;tmwall;tmwall=tmwall->next)
945 	  {
946 	  if (spotvis[tmwall->tilex][tmwall->tiley])
947 		  {
948 		  mapseen[tmwall->tilex][tmwall->tiley]=1;
949 		  if (tmwall->vertical)
950 			  {
951 			  gx=(tmwall->tilex<<16)+0x8000;
952 			  gy=(tmwall->tiley<<16);
953 			  visptr->texturestart=0;
954 			  visptr->textureend=0;
955 			  if (viewx<gx)
956 				  result=TransformPlane(gx,gy,gx,gy+0xffff,visptr);
957 			  else
958 				  result=TransformPlane(gx,gy+0xffff,gx,gy,visptr);
959 			  visptr->shapenum=tmwall->bottomtexture;
960 			  visptr->altshapenum=tmwall->midtexture;
961 			  visptr->viewx=tmwall->toptexture;
962 			  visptr->shapesize=2;
963 			  }
964 		  else
965 			  {
966 			  gx=(tmwall->tilex<<16);
967 			  gy=(tmwall->tiley<<16)+0x8000;
968 			  visptr->texturestart=0;
969 			  visptr->textureend=0;
970 			  if (viewy<gy)
971 				  result=TransformPlane(gx+0xffff,gy,gx,gy,visptr);
972 			  else
973 				  result=TransformPlane(gx,gy,gx+0xffff,gy,visptr);
974 			  visptr->shapenum=tmwall->bottomtexture;
975 			  visptr->altshapenum=tmwall->midtexture;
976 			  visptr->viewx=tmwall->toptexture;
977 			  visptr->shapesize=2;
978 			  }
979 		  if ((tmwall->flags&MW_TOPFLIPPING) &&
980             (nonbobpheight>64)
981 			  )
982 			  {
983 			  visptr->viewx++;
984 			  }
985 		  else if ((tmwall->flags&MW_BOTTOMFLIPPING) &&
986                  (nonbobpheight>maxheight-32)
987 					 )
988 			  {
989 			  visptr->shapenum++;
990 			  }
991 		  if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
992 			  visptr++;
993 		  }
994 	  }
995 //
996 // place static objects
997 //
998   UpdateClientControls();
999   for (statptr = firstactivestat ; statptr; statptr=statptr->nextactive)
1000   {  //redraw:
1001 			 if((visptr->shapenum = statptr->shapenum) == NOTHING)
1002 				  continue;
1003 
1004           visptr->shapenum += shapestart;
1005 			 if ((visptr->shapenum <= shapestart) ||
1006 				  (visptr->shapenum >= shapestop))
1007 			  Error("actor shapenum %d out of range (%d-%d)",visptr->shapenum,shapestart,shapestop);
1008 
1009           visspot = statptr->visspot;
1010 			 if (!((*(visspot-0)) ||
1011 					 (*(visspot-1)) ||
1012 					 (*(visspot+1)) ||
1013 					 (*(visspot-129)) ||
1014 					 (*(visspot-128)) ||
1015 					 (*(visspot-127)) ||
1016 					 (*(visspot+129)) ||
1017 					 (*(visspot+128)) ||
1018 					 (*(visspot+127))))
1019 					 {statptr->flags &= ~FL_VISIBLE;
1020 					  continue;     // not visible
1021 					 }
1022 
1023 			 result = TransformObject (statptr->x,statptr->y,&(visptr->viewx),&(visptr->viewheight));
1024 
1025 			 if ((result==false) || (visptr->viewheight< (1<<(HEIGHTFRACTION+2))))
1026 				 continue;                         // to close to the object
1027 			 statptr->flags |= FL_SEEN;
1028 
1029 			 statptr->flags |= FL_VISIBLE;
1030 
1031 			 if (statptr->flags & FL_ROTATING)
1032 				 visptr->shapenum += StatRotate(statptr);
1033 
1034 			 if (statptr->flags&FL_TRANSLUCENT)
1035 				 {
1036 				 visptr->shapesize=1;
1037 				 if (statptr->flags&FL_FADING)
1038 					 visptr->h2=transparentlevel;
1039 				 else
1040 					 visptr->h2=FIXEDTRANSLEVEL;
1041              SetSpriteLightLevel(statptr->x,statptr->y,visptr,0,(statptr->flags&FL_FULLLIGHT));
1042 				 }
1043 			 else if (statptr->flags&FL_SOLIDCOLOR)
1044 				 {
1045 				 visptr->shapesize=4;
1046 				 visptr->h2=statptr->hitpoints;
1047 				 }
1048 			 else if (statptr->flags&FL_COLORED)
1049 				 {
1050 				 visptr->shapesize=0;
1051 #if (DEVELOPMENT == 1)
1052 				 if ((statptr->hitpoints>=0) &&
1053 					 (statptr->hitpoints<MAXPLAYERCOLORS))
1054 					 {
1055 #endif
1056 					 SetColorLightLevel(statptr->x,statptr->y,visptr,
1057                                    0,statptr->hitpoints,
1058                                    (statptr->flags&FL_FULLLIGHT));
1059 #if (DEVELOPMENT == 1)
1060 					 }
1061 				 else
1062                 {
1063                 Error("Illegal color map for sprite type %d\n",statptr->itemnumber);
1064 					 }
1065 #endif
1066 				 }
1067           else
1068 				 {
1069 				 visptr->shapesize=0;
1070              SetSpriteLightLevel(statptr->x,statptr->y,visptr,0,(statptr->flags&FL_FULLLIGHT));
1071 				 }
1072 
1073 			 visptr->h1=pheight-statptr->z;
1074 
1075 			 if ((statptr->itemnumber != (unsigned int)-1) &&
1076 				  (statptr->flags&FL_HEIGHTFLIPPABLE)
1077 				 )
1078 				 {
1079 				 if (statptr->itemnumber==stat_disk)
1080 					 {
1081 					 int value;
1082                 value=nonbobpheight-statptr->z-32;
1083 					 if ((value<=HF_2) && (value>HF_1))
1084 						 {
1085 						 visptr->shapenum++;
1086 						 }
1087 					 else if ((value<=HF_1) && (value>=-HF_1))
1088 						 {
1089 						 visptr->shapenum+=2;
1090 						 }
1091 					 else if ((value<-HF_1) && (value>=-HF_2))
1092 						 {
1093 						 visptr->shapenum+=3;
1094 						 }
1095 					 else if (value<-HF_2)
1096 						 {
1097 						 visptr->shapenum+=4;
1098 						 }
1099 					 }
1100              else if ((nonbobpheight-statptr->z)<-16)
1101 					 {
1102 					 visptr->shapenum++;
1103 					 }
1104 				 }
1105 
1106 			 if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
1107 				visptr++;
1108 
1109 
1110   }
1111 //
1112 // place active objects
1113 //
1114   UpdateClientControls();
1115   for (obj = firstactive;obj;obj=obj->nextactive)
1116 	  {
1117 	  if (obj==player)
1118 		  continue;
1119 
1120 	  if ((visptr->shapenum = obj->shapenum) == NOTHING)
1121 		  continue;                         // no shape
1122 
1123 	  visptr->shapenum += shapestart;
1124      if ((visptr->shapenum <= shapestart) ||
1125 				  (visptr->shapenum >= shapestop))
1126 		  Error("actor shapenum %d out of range (%d-%d)",visptr->shapenum,shapestart,shapestop);
1127 	  visspot = &spotvis[obj->tilex][obj->tiley];
1128 	  tilespot = &tilemap[obj->tilex][obj->tiley];
1129 
1130 	  //
1131 	  // could be in any of the nine surrounding tiles
1132 	  //
1133 	  if (*visspot
1134 		  || ( *(visspot-1))
1135 		  || ( *(visspot+1))
1136 		  || ( *(visspot-129))
1137 		  || ( *(visspot-128))
1138 		  || ( *(visspot-127))
1139 		  || ( *(visspot+129))
1140 		  || ( *(visspot+128))
1141 		  || ( *(visspot+127)) )
1142 		  {
1143 
1144 //        result = TransformObject (obj->drawx, obj->drawy,&(visptr->viewx),&(visptr->viewheight));
1145         result = TransformObject (obj->x, obj->y,&(visptr->viewx),&(visptr->viewheight));
1146         if ((result==false) || (visptr->viewheight< (1<<(HEIGHTFRACTION+2))))
1147 			  continue;                         // to close to the object
1148 		  if (obj->state->rotate)
1149 			  visptr->shapenum += CalcRotate (obj);
1150 
1151         visptr->shapesize=0;
1152 
1153 		  if (player->flags&FL_SHROOMS)
1154 			  {
1155 			  visptr->shapesize=4;
1156 			  visptr->h2=(GetTicCount()&0xff);
1157 			  }
1158 		  if (obj->obclass==playerobj)
1159 			  {
1160 			  if (obj->flags&FL_GODMODE)
1161 				  {
1162 				  visptr->shapesize=4;
1163 				  visptr->h2=240+(GetTicCount()&0x7);
1164 				  }
1165 			  else if (obj->flags & FL_COLORED)
1166 				  {
1167 				  playertype *pstate;
1168 
1169 				  M_LINKSTATE(obj,pstate);
1170 #if (DEVELOPMENT == 1)
1171 				  if ((pstate->uniformcolor>=0) &&
1172 					  (pstate->uniformcolor<MAXPLAYERCOLORS))
1173 					  {
1174 #endif
1175 					  SetColorLightLevel(obj->x,obj->y,visptr,
1176                                     obj->dir,pstate->uniformcolor,
1177                                     (obj->flags&FL_FULLLIGHT) );
1178 #if (DEVELOPMENT == 1)
1179 					  }
1180 				  else
1181 					  {
1182 					  Error("Illegal color map for players\n");
1183 					  }
1184 #endif
1185 				  }
1186 			  else
1187               SetSpriteLightLevel(obj->x,obj->y,visptr,obj->dir,(obj->flags&FL_FULLLIGHT));
1188 
1189 			  }
1190 		  else
1191 			  {
1192 			  if ((obj->obclass >= b_darianobj) && (obj->obclass <= b_robobossobj) &&
1193 				  MISCVARS->redindex)
1194               {
1195 				  visptr->colormap=redmap+((MISCVARS->redindex-1)<<8);
1196               }
1197            else
1198               {
1199               SetSpriteLightLevel(obj->x,obj->y,visptr,obj->dir,(obj->flags&FL_FULLLIGHT));
1200               }
1201            }
1202 
1203 		  visptr->h1= pheight - obj->z;
1204 
1205         if (obj->obclass==diskobj)
1206            {
1207            int value;
1208            value=nonbobpheight-obj->z-32;
1209            if ((value<=HF_2) && (value>HF_1))
1210               {
1211               visptr->shapenum++;
1212               }
1213            else if ((value<=HF_1) && (value>=-HF_1))
1214               {
1215               visptr->shapenum+=2;
1216               }
1217            else if ((value<-HF_1) && (value>=-HF_2))
1218               {
1219               visptr->shapenum+=3;
1220               }
1221            else if (value<-HF_2)
1222               {
1223               visptr->shapenum+=4;
1224               }
1225            }
1226         else if ( (obj->obclass==pillarobj) &&
1227                   ((nonbobpheight-obj->z)<-16)
1228                 )
1229            {
1230            visptr->shapenum++;
1231            }
1232 
1233 		  if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
1234 			  visptr++;
1235 		  obj->flags |= FL_SEEN;
1236 		  obj->flags |= FL_VISIBLE;
1237 		  }
1238 	  else
1239 		  obj->flags &= ~FL_VISIBLE;
1240 	  }
1241 //
1242 // draw from back to front
1243 //
1244 	numvisible = visptr-&vislist[0];
1245 	if (!numvisible)
1246 		return;                                     // no visible objects
1247 	SortVisibleList( numvisible, &vislist[0] );
1248    UpdateClientControls();
1249    for (i = 0; i<numvisible; i++)
1250 		{
1251       //
1252       // draw farthest
1253       //
1254 
1255       if (sortedvislist[i]->shapesize==4) {
1256 
1257         ScaleSolidShape(sortedvislist[i]);
1258 
1259       } else if (sortedvislist[i]->shapesize==3) {
1260 
1261          InterpolateDoor (sortedvislist[i]);
1262 
1263       } else if (sortedvislist[i]->shapesize==2) {
1264 
1265          InterpolateMaskedWall (sortedvislist[i]);
1266 
1267       } else if (sortedvislist[i]->shapesize==1) {
1268 
1269          ScaleTransparentShape(sortedvislist[i]);
1270 
1271       } else {
1272 
1273          ScaleShape(sortedvislist[i]);
1274 
1275       }
1276 
1277       }
1278 }
1279 
1280 //==========================================================================
1281 
1282 
1283 
1284 
1285 
1286 /*
1287 ==============
1288 =
1289 = DrawPlayerWeapon
1290 =
1291 = Draw the player's hand'
1292 =
1293 ==============
1294 */
1295 
DrawPlayerWeapon(void)1296 void DrawPlayerWeapon (void)
1297 {
1298  int shapenum,index;
1299  int xdisp=0;
1300  int ydisp=0;
1301  int female,black;
1302  int altshape=0;
1303 
1304    whereami=7;
1305 
1306  SoftError("\n attackframe: %d, weaponframe: %d, weapondowntics: %d"
1307            " weaponuptics: %d",locplayerstate->attackframe,
1308            locplayerstate->weaponframe,locplayerstate->weapondowntics,
1309            locplayerstate->weaponuptics);
1310 
1311  if ((locplayerstate->NETCAPTURED == 1) && (!locplayerstate->HASKNIFE))
1312   return;
1313 
1314  if (locplayerstate->weapon != -1)
1315   {female = ((locplayerstate->player == 1) || (locplayerstate->player == 3));
1316    black = (locplayerstate->player == 2);
1317 
1318 	if (((locplayerstate->NETCAPTURED >= 1) || (locplayerstate->NETCAPTURED == -2)) && (locplayerstate->HASKNIFE == 1)) // if raising or lowering
1319 		 {index = 0;
1320 		  shapenum = gunsstart + weaponshape[index] + locplayerstate->weaponframe;
1321 		 }
1322 	else if  (locplayerstate->weapon != wp_twopistol)
1323 		 {if (locplayerstate->weapon==wp_pistol)
1324 			{if (female)
1325 			  index = NUMWEAPGRAPHICS-2;
1326 			 else if (black)
1327 			  index = NUMWEAPGRAPHICS-1;
1328 			 else
1329 #if (SHAREWARE == 0)
1330 			  index = 1;
1331 #else
1332            index = 0;
1333 #endif
1334 			}
1335 		  else
1336 #if (SHAREWARE == 0)
1337 
1338           index = locplayerstate->weapon + 1;
1339 #else
1340           index = locplayerstate->weapon;
1341 #endif
1342 
1343         if ((index<0) || (index>=NUMWEAPGRAPHICS))
1344            Error ("Weapon shapenum out of range\n");
1345 		  shapenum = gunsstart + weaponshape[index] + locplayerstate->weaponframe;
1346 
1347 #if (SHAREWARE == 0)
1348         if ((shapenum < W_GetNumForName("KNIFE1")) ||
1349             (shapenum > W_GetNumForName("DOGPAW4"))
1350            )
1351 #else
1352         if ((shapenum < W_GetNumForName("MPIST11")) ||
1353             (shapenum > W_GetNumForName("GODHAND8"))
1354            )
1355 #endif
1356            Error("\n illegal weapon shapenum %d, index %d, weaponframe %d",
1357                   shapenum,index,locplayerstate->weaponframe);
1358 		 }
1359 
1360 	else
1361     {
1362 #if (SHAREWARE == 0)
1363      if (female)
1364 		 {altshape = W_FLEFTPISTOL1;
1365 		  shapenum = W_FRIGHTPISTOL1;
1366 		 }
1367 	  else if (black)
1368 		 {altshape = W_BMLEFTPISTOL1;
1369 		  shapenum = W_BMRIGHTPISTOL1;
1370 		 }
1371 	  else
1372 #endif
1373 		{altshape = W_MLEFTPISTOL1;
1374 		 shapenum = W_MRIGHTPISTOL1;
1375 		}
1376 
1377 	  altshape += gunsstart;
1378 	  shapenum += gunsstart;
1379 	  if (locplayerstate->weaponframe > 2)
1380 			altshape += (locplayerstate->weaponframe - 3);
1381 	  else
1382 			shapenum += locplayerstate->weaponframe;
1383 	 }
1384 
1385 	if (!(locplayerstate->NETCAPTURED) ||
1386 		  (locplayerstate->NETCAPTURED == -1) ||
1387 		  (locplayerstate->HASKNIFE == 0))
1388 	 {switch (locplayerstate->weapon)
1389 		{
1390 
1391 		 case wp_godhand:
1392 			break;
1393 
1394 		 case wp_mp40:
1395 			 break;
1396 
1397 		 case wp_firewall:
1398 			ydisp = 10;
1399          break;
1400 
1401 		 case wp_bazooka:
1402          break;
1403 
1404 		 case wp_heatseeker:
1405 			ydisp = 20;
1406 			break;
1407 
1408 		 case wp_pistol:
1409 			break;
1410 
1411 		 case wp_twopistol:
1412 			xdisp = 80;
1413 			break;
1414 
1415        case wp_drunk:
1416 			ydisp = 10;
1417          break;
1418 
1419        case wp_firebomb:
1420 			break;
1421 
1422 
1423 
1424 #if (SHAREWARE == 0)
1425 
1426        case wp_kes:
1427 			break;
1428 
1429        case wp_bat:
1430          xdisp = 20;
1431 			break;
1432 
1433        case wp_split:
1434 			ydisp = 20;
1435 			break;
1436 
1437 
1438 		 case wp_dog:
1439 			break;
1440 
1441 
1442 #endif
1443 
1444 		 default:
1445          Error("Illegal weapon value = %ld\n",locplayerstate->weapon);
1446          break;
1447 		}
1448 	 }
1449   else
1450 	  xdisp = 60;
1451 
1452 
1453 
1454 
1455   if (altshape)
1456      {
1457      int temp;
1458      int delta;
1459 
1460      temp = weaponscale;
1461      delta = FixedMul((weaponbobx<<9),weaponscale);
1462      weaponscale += delta;
1463      ScaleWeapon(xdisp - weaponbobx,ydisp + weaponboby + locplayerstate->weaponheight,shapenum);
1464      weaponscale -= delta;
1465 	  ScaleWeapon(weaponbobx - 80,ydisp + weaponboby + locplayerstate->weaponheight,altshape);
1466      weaponscale = temp;
1467      }
1468   else
1469      {
1470      int temp;
1471      int delta;
1472 
1473      temp = weaponscale;
1474      delta = FixedMul((weaponbobx<<9),weaponscale);
1475      weaponscale -= delta;
1476      ScaleWeapon(xdisp + weaponbobx,ydisp + weaponboby + locplayerstate->weaponheight,shapenum);
1477      weaponscale = temp;
1478      }
1479   }
1480 }
1481 
AdaptDetail(void)1482 void AdaptDetail ( void )
1483 {
1484 #if PROFILE
1485    return;
1486 #else
1487 
1488    whereami=8;
1489    if ((preindex<0) || (preindex>2))
1490       Error("preindex out of range\n");
1491    pretics[preindex]=(pretics[0]+pretics[1]+pretics[2]+(tics<<16)+0x8000)>>2;
1492    if (pretics[preindex]>GOLOWER)
1493       {
1494       pretics[0]=GOHIGHER;
1495       pretics[1]=GOHIGHER;
1496       pretics[2]=GOHIGHER;
1497       doublestep++;
1498       if (doublestep>2) doublestep=2;
1499       }
1500    else if (pretics[preindex]<GOHIGHER)
1501 		{
1502       if (doublestep>0)
1503          doublestep--;
1504       }
1505    preindex++;
1506    if (preindex>2)
1507       preindex=0;
1508 #endif
1509 }
1510 
1511 
1512 
1513 /*
1514 =====================
1515 =
1516 = CalcTics
1517 =
1518 =====================
1519 */
1520 
CalcTics(void)1521 void CalcTics (void)
1522 {
1523 
1524 #if PROFILE
1525    tics=PROFILETICS;
1526    GetTicCount()+=PROFILETICS;
1527    oldtime=GetTicCount();
1528    return;
1529 #else
1530 #if (DEVELOPMENT == 1)
1531    int i;
1532 #endif
1533    volatile int tc;
1534 
1535    whereami=9;
1536 //   SoftError("InCalcTics\n");
1537 //   SoftError("CT GetTicCount()=%ld\n",GetTicCount());
1538 //   SoftError("CT oldtime=%ld\n",oldtime);
1539 
1540 //
1541 // calculate tics since last refresh for adaptive timing
1542 //
1543 
1544    tc=GetTicCount();
1545 	while (tc==oldtime) { tc=GetTicCount(); } /* endwhile */
1546    tics=tc-oldtime;
1547 
1548 //   SoftError("CT GetTicCount()=%ld\n",GetTicCount());
1549 //   if (tics>MAXTICS)
1550 //      {
1551 //      tc-=(tics-MAXTICS);
1552 //      GetTicCount() = tc;
1553 //     tics = MAXTICS;
1554 //      }
1555 
1556    if (demoplayback || demorecord)
1557       {
1558       if (tics>MAXTICS)
1559          {
1560          tc=oldtime+MAXTICS;
1561          tics=MAXTICS;
1562          ISR_SetTime(tc);
1563          }
1564       }
1565    oldtime=tc;
1566 #if (DEVELOPMENT == 1)
1567    if (graphicsmode==true)
1568       {
1569       int drawntics;
1570 
1571       VGAWRITEMAP(1);
1572       drawntics=tics;
1573       if (drawntics>MAXDRAWNTICS)
1574          drawntics=MAXDRAWNTICS;
1575       for (i=0;i<drawntics;i++)
1576          *((byte *)displayofs+screenofs+(SCREENBWIDE*3)+i)=egacolor[15];
1577       }
1578 /*
1579       if (drawtime>MAXDRAWNTICS)
1580          drawtime=MAXDRAWNTICS;
1581       for (i=0;i<drawtime;i++)
1582          *((byte *)displayofs+screenofs+(SCREENBWIDE*5)+i)=egacolor[2];
1583       if (walltime>MAXDRAWNTICS)
1584          walltime=MAXDRAWNTICS;
1585       for (i=0;i<walltime;i++)
1586          *((byte *)displayofs+screenofs+(SCREENBWIDE*7)+i)=egacolor[14];
1587       if (actortime>MAXDRAWNTICS)
1588          actortime=MAXDRAWNTICS;
1589       for (i=0;i<actortime;i++)
1590          *((byte *)displayofs+screenofs+(SCREENBWIDE*9)+i)=egacolor[4];
1591       }
1592 */
1593 #endif
1594 #endif
1595 
1596 }
1597 
1598 /*
1599 ==========================
1600 =
1601 = SetSpriteLightLevel
1602 =
1603 ==========================
1604 */
1605 
SetSpriteLightLevel(int x,int y,visobj_t * sprite,int dir,int fullbright)1606 void SetSpriteLightLevel (int x, int y, visobj_t * sprite, int dir, int fullbright)
1607 {
1608    int i;
1609    int lv;
1610    int intercept;
1611 
1612    whereami=10;
1613 
1614 	if (MISCVARS->GASON==1)
1615 		{
1616 		sprite->colormap=greenmap+(MISCVARS->gasindex<<8);
1617 		return;
1618       }
1619 
1620    if (fulllight || fullbright)
1621       {
1622       sprite->colormap=colormap+(1<<12);
1623       return;
1624       }
1625 
1626    if (fog)
1627       {
1628       i=(sprite->viewheight>>normalshade)+minshade;
1629       if (i>maxshade) i=maxshade;
1630       sprite->colormap=colormap+(i<<8);
1631       }
1632    else
1633       {
1634       if (lightsource)
1635          {
1636     	   if (dir==east || dir==west)
1637             intercept=(x>>11)&0x1c;
1638          else
1639             intercept=(y>>11)&0x1c;
1640 
1641          lv=(((LightSourceAt(x>>16,y>>16)>>intercept)&0xf)>>1);
1642          i=maxshade-(sprite->viewheight>>normalshade)-lv;
1643          if (i<minshade) i=minshade;
1644          sprite->colormap=colormap+(i<<8);
1645          }
1646       else
1647          {
1648          i=maxshade-(sprite->viewheight>>normalshade);
1649          if (i<minshade) i=minshade;
1650          sprite->colormap=colormap+(i<<8);
1651          }
1652       }
1653 }
1654 
1655 /*
1656 ==========================
1657 =
1658 = SetColorLightLevel
1659 =
1660 ==========================
1661 */
1662 
SetColorLightLevel(int x,int y,visobj_t * sprite,int dir,int color,int fullbright)1663 void SetColorLightLevel (int x, int y, visobj_t * sprite, int dir, int color, int fullbright)
1664 {
1665    int i;
1666    int lv;
1667    int intercept;
1668    int height;
1669    byte * map;
1670 
1671 
1672    whereami=11;
1673    height=sprite->viewheight<<1;
1674    map=playermaps[color];
1675 	if (MISCVARS->GASON==1)
1676 		{
1677 		sprite->colormap=greenmap+(MISCVARS->gasindex<<8);
1678 		return;
1679       }
1680 
1681    if ((fulllight) || (fullbright))
1682       {
1683       sprite->colormap=map+(1<<12);
1684       return;
1685       }
1686 
1687    if (fog)
1688       {
1689       i=(height>>normalshade)+minshade;
1690       if (i>maxshade) i=maxshade;
1691       sprite->colormap=map+(i<<8);
1692       }
1693    else
1694       {
1695       if (lightsource)
1696          {
1697     	   if (dir==east || dir==west)
1698             intercept=(x>>11)&0x1c;
1699          else
1700             intercept=(y>>11)&0x1c;
1701 
1702          lv=(((LightSourceAt(x>>16,y>>16)>>intercept)&0xf)>>1);
1703          i=maxshade-(height>>normalshade)-lv;
1704          if (i<minshade) i=minshade;
1705          sprite->colormap=map+(i<<8);
1706          }
1707       else
1708          {
1709          i=maxshade-(height>>normalshade);
1710          if (i<minshade) i=minshade;
1711          sprite->colormap=map+(i<<8);
1712          }
1713       }
1714 }
1715 
1716 /*
1717 ==========================
1718 =
1719 = SetWallLightLevel
1720 =
1721 ==========================
1722 */
1723 
SetWallLightLevel(wallcast_t * post)1724 void SetWallLightLevel (wallcast_t * post)
1725 {
1726    int la;
1727    int lv;
1728    int i;
1729 
1730    whereami=12;
1731 	if (MISCVARS->GASON==1)
1732 		{
1733 		shadingtable=greenmap+(MISCVARS->gasindex<<8);
1734 		return;
1735 		}
1736 
1737    switch (post->posttype)
1738       {
1739       case 0:
1740          la=0;
1741          break;
1742       case 1:
1743          la=4;
1744          break;
1745       case 2:
1746          la=(4-gamestate.difficulty);
1747          break;
1748       case 3:
1749          la=3+(4-gamestate.difficulty);
1750          break;
1751       }
1752 
1753    if (lightsource)
1754       {
1755       int x,y;
1756       int intercept;
1757 
1758       x=post->offset>>7;
1759       y=post->offset&0x7f;
1760       intercept=(post->texture>>11)&0x1c;
1761       lv=(((LightSourceAt(x,y)>>intercept)&0xf)>>1);
1762       }
1763    else
1764       lv=0;
1765    if (fulllight)
1766       {
1767       if (fog)
1768          {
1769          i =16+minshade-lv+la;
1770          if (i>maxshade+la) i=maxshade+la;
1771          shadingtable=colormap+(i<<8);
1772          }
1773       else
1774          {
1775          i =maxshade-16-lv+la;
1776          if (i>=maxshade) i=maxshade;
1777          if (i<minshade+la) i=minshade+la;
1778          shadingtable=colormap+(i<<8);
1779          }
1780       return;
1781       }
1782    if (fog)
1783       {
1784       i =(post->wallheight>>normalshade)+minshade-lv+la;
1785       if (i>maxshade+la) i=maxshade+la;
1786       shadingtable=colormap+(i<<8);
1787       }
1788    else
1789       {
1790       i =maxshade-(post->wallheight>>normalshade)-lv+la;
1791       if (i>=maxshade) i=maxshade;
1792       if (i<minshade+la) i=minshade+la;
1793       shadingtable=colormap+(i<<8);
1794       }
1795 }
1796 
1797 
1798 
1799 /*
1800 ====================
1801 =
1802 = DrawWallPost
1803 =
1804 ====================
1805 */
1806 
DrawWallPost(wallcast_t * post,byte * buf)1807 void DrawWallPost ( wallcast_t * post, byte * buf)
1808 {
1809    int ht;
1810    int topscreen;
1811    int bottomscreen;
1812    byte * src;
1813    byte * src2;
1814 
1815    whereami=42;
1816    if (post->lump)
1817       src=W_CacheLumpNum(post->lump,PU_CACHE, CvtNull, 1);
1818 	if (post->alttile!=0)
1819       {
1820       if (post->alttile==-1)
1821          {
1822          ht=maxheight+32;
1823          dc_invscale   = post->wallheight<<(10-HEIGHTFRACTION);
1824          dc_texturemid = (pheight<<SFRACBITS)+(SFRACUNIT>>1);
1825          topscreen     = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
1826          bottomscreen  = topscreen + (dc_invscale*ht);
1827          dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
1828          if (dc_yh < 0)
1829             {
1830             post->floorclip=-1;
1831             post->ceilingclip=0;
1832             }
1833          else if (dc_yh >= viewheight)
1834             {
1835             post->floorclip=viewheight-1;
1836             post->ceilingclip=viewheight;
1837             }
1838          else
1839             {
1840             post->floorclip=dc_yh-1;
1841             post->ceilingclip=dc_yh;
1842             }
1843          return;
1844          }
1845       else
1846          {
1847          ht=nominalheight;
1848          src2=W_CacheLumpNum(post->alttile,PU_CACHE, CvtNull, 1);
1849          }
1850       }
1851    else
1852       {
1853       ht=maxheight+32;
1854       src2=src;
1855       }
1856 
1857    dc_invscale   = post->wallheight<<(10-HEIGHTFRACTION);
1858    dc_texturemid = (pheight<<SFRACBITS)+(SFRACUNIT>>1);
1859 	topscreen     = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
1860    bottomscreen  = topscreen + (dc_invscale*ht);
1861    dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
1862    dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
1863 
1864    if (dc_yl >= viewheight)
1865       {
1866       post->ceilingclip=viewheight;
1867       post->floorclip=viewheight-1;
1868       return;
1869       }
1870    else if (dc_yl < 0)
1871       dc_yl = 0;
1872 
1873    dc_iscale     = (64<<(16+HEIGHTFRACTION))/post->wallheight;
1874 
1875    if (dc_yh < 0)
1876       {
1877       post->floorclip=-1;
1878       post->ceilingclip=0;
1879       goto bottomcheck;
1880       }
1881    else if (dc_yh > viewheight)
1882       dc_yh = viewheight;
1883 
1884    post->ceilingclip=dc_yl;
1885    post->floorclip=dc_yh-1;
1886    dc_source=src2+((post->texture>>4)&0xfc0);
1887    R_DrawWallColumn (buf);
1888 
1889 bottomcheck:
1890 
1891    if (ht!=nominalheight)
1892       return;
1893 
1894    dc_texturemid-=(nominalheight<<SFRACBITS);
1895    topscreen     = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
1896    bottomscreen  = topscreen + (dc_invscale<<6);
1897    dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
1898    dc_yh = ((bottomscreen-1)>>SFRACBITS);
1899 
1900 	if (dc_yl >= viewheight)
1901       return;
1902    else if (dc_yl < 0)
1903       dc_yl = 0;
1904    if (dc_yh < 0)
1905       return;
1906    else if (dc_yh > viewheight)
1907       dc_yh = viewheight;
1908    post->floorclip=dc_yh-1;
1909    dc_source=src+((post->texture>>4)&0xfc0);
1910    R_DrawWallColumn (buf);
1911 }
1912 
1913 /*
1914 ====================
1915 =
1916 = DrawWalls
1917 =
1918 ====================
1919 */
1920 
DrawWalls(void)1921 void   DrawWalls (void)
1922 {
1923    char * buf;
1924    int plane;
1925    wallcast_t * post;
1926 
1927    whereami=13;
1928 
1929    plane = 0;
1930 
1931    if (doublestep>1)
1932       {
1933 #ifdef DOS
1934       for (plane=0;plane<4;plane+=2)
1935 #endif
1936          {
1937          VGAMAPMASK((1<<plane)+(1<<(plane+1)));
1938          buf=(byte *)(bufferofs);
1939 #ifdef DOS
1940          for (post=&posts[plane];post<&posts[viewwidth];post+=4,buf++)
1941 #else
1942          for (post=&posts[plane];post<&posts[viewwidth];post+=2,buf+=2)
1943 #endif
1944             {
1945             SetWallLightLevel(post);
1946             DrawWallPost(post,buf);
1947 #ifndef DOS
1948             DrawWallPost(post,buf+1);
1949 #endif
1950             (post+1)->ceilingclip=post->ceilingclip;
1951             (post+1)->floorclip=post->floorclip;
1952             }
1953          }
1954 		}
1955    else
1956       {
1957 #ifdef DOS
1958       for (plane=0;plane<4;plane++)
1959 #endif
1960          {
1961          VGAWRITEMAP(plane);
1962          buf=(byte *)(bufferofs);
1963 #ifdef DOS
1964          for (post=&posts[plane];post<&posts[viewwidth];post+=4,buf++)
1965 #else
1966          for (post=&posts[plane];post<&posts[viewwidth];post++,buf++)
1967 #endif
1968             {
1969             SetWallLightLevel(post);
1970             DrawWallPost(post,buf);
1971             }
1972          }
1973       }
1974 }
1975 
1976 
1977 /*
1978 ====================
1979 =
1980 = TransformDoors
1981 =
1982 ====================
1983 */
1984 
TransformDoors(void)1985 void TransformDoors( void )
1986 {
1987    int i;
1988    int numvisible;
1989    boolean result;
1990    int gx,gy;
1991    visobj_t visdoorlist[MAXVISIBLEDOORS],*doorptr;
1992 
1993    whereami=14;
1994    doorptr=&visdoorlist[0];
1995 //
1996 // place door objects
1997 //
1998 
1999   for (i = 0;i<doornum;i++)
2000 	  {
2001 	  if (spotvis[doorobjlist[i]->tilex][doorobjlist[i]->tiley])
2002 		  {
2003         mapseen[doorobjlist[i]->tilex][doorobjlist[i]->tiley]=1;
2004         doorptr->texturestart=0;
2005         doorptr->textureend=0;
2006         if (doorobjlist[i]->vertical)
2007            {
2008            gx=(doorobjlist[i]->tilex<<16)+0x8000;
2009            gy=(doorobjlist[i]->tiley<<16);
2010            if (viewx<gx)
2011               result=TransformPlane(gx,gy,gx,gy+0xffff,doorptr);
2012            else
2013               result=TransformPlane(gx,gy+0xffff,gx,gy,doorptr);
2014            }
2015         else
2016            {
2017            gx=(doorobjlist[i]->tilex<<16);
2018            gy=(doorobjlist[i]->tiley<<16)+0x8000;
2019            if (viewy<gy)
2020               result=TransformPlane(gx+0xffff,gy,gx,gy,doorptr);
2021            else
2022               result=TransformPlane(gx,gy,gx+0xffff,gy,doorptr);
2023            }
2024         if (result==true)
2025            {
2026            doorptr->viewx=0;
2027            doorptr->shapenum=doorobjlist[i]->texture;
2028            doorptr->altshapenum=doorobjlist[i]->alttexture;
2029            if (doorobjlist[i]->texture==doorobjlist[i]->basetexture)
2030               {
2031               doorptr->shapesize=(doorobjlist[i]->tilex<<7)+doorobjlist[i]->tiley;
2032               if (doorptr < &visdoorlist[MAXVISIBLEDOORS-1]) // don't let it overflo'
2033                  doorptr++;
2034               }
2035            else
2036               {
2037               doorptr->shapesize=3;
2038               memcpy(visptr,doorptr,sizeof(visobj_t));
2039               if (visptr < &vislist[MAXVISIBLE-1])
2040                  visptr++;
2041               }
2042            }
2043 		  }
2044      }
2045 //
2046 // draw from back to front
2047 //
2048    numvisible = doorptr-&visdoorlist[0];
2049    if (!numvisible)
2050       return;
2051    SortVisibleList( numvisible, &visdoorlist[0] );
2052    for (i = 0; i<numvisible; i++)
2053       {
2054       //
2055       // draw farthest
2056       //
2057       InterpolateWall (sortedvislist[i]);
2058       }
2059 }
2060 
2061 
2062 /*
2063 ====================
2064 =
2065 = TransformPushWalls
2066 =
2067 ====================
2068 */
2069 
TransformPushWalls(void)2070 void TransformPushWalls( void )
2071 {
2072   int   i;
2073   int   gx,gy;
2074   byte   *visspot;
2075   visobj_t *savedptr;
2076   int numvisible;
2077   boolean result;
2078 
2079    whereami=15;
2080   savedptr=visptr;
2081   //
2082   // place pwall objects
2083   //
2084   for (i = 0;i<pwallnum;i++)
2085 	  {
2086      if ((pwallobjlist[i]->action==pw_pushed) || (pwallobjlist[i]->action==pw_npushed))
2087         continue;
2088 	  visspot = &spotvis[pwallobjlist[i]->x>>16][pwallobjlist[i]->y>>16];
2089 	  if (*visspot
2090 		  || ( *(visspot-1))
2091 		  || ( *(visspot+1))
2092 		  || ( *(visspot-128))
2093 		  || ( *(visspot+128)))
2094         {
2095         gx=pwallobjlist[i]->x;
2096         gy=pwallobjlist[i]->y;
2097         mapseen[gx>>16][gy>>16]=1;
2098         if (viewx<gx)
2099            {
2100            if (viewy<gy)
2101               {
2102               visptr->texturestart=(gx-0x8000)&0xffff;
2103               visptr->textureend=visptr->texturestart;
2104               result=TransformPlane(gx+0x7fff,gy-0x8000,gx-0x8000,gy-0x8000,visptr);
2105               visptr->texturestart^=0xffff;
2106               visptr->textureend^=0xffff;
2107               visptr->shapenum=pwallobjlist[i]->texture;
2108               visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
2109               visptr->viewx+=2;
2110               if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
2111                  visptr++;
2112               visptr->texturestart=(gy-0x8000)&0xffff;
2113               visptr->textureend=visptr->texturestart;//-0xffff;
2114               result=TransformPlane(gx-0x8000,gy-0x8000,gx-0x8000,gy+0x7fff,visptr);
2115               }
2116            else
2117               {
2118               visptr->texturestart=(gy-0x8000)&0xffff;
2119               visptr->textureend=visptr->texturestart;//-0xffff;
2120               result=TransformPlane(gx-0x8000,gy-0x8000,gx-0x8000,gy+0x7fff,visptr);
2121               visptr->shapenum=pwallobjlist[i]->texture;
2122               visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
2123               visptr->viewx+=2;
2124               if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
2125                  visptr++;
2126 				  visptr->texturestart=(gx-0x8000)&0xffff;
2127               visptr->textureend=visptr->texturestart;//-0xffff;
2128               result=TransformPlane(gx-0x8000,gy+0x7fff,gx+0x7fff,gy+0x7fff,visptr);
2129               }
2130            }
2131         else
2132            {
2133            if (viewy<gy)
2134               {
2135               visptr->texturestart=(gy-0x8000)&0xffff;
2136               visptr->textureend=visptr->texturestart;
2137               result=TransformPlane(gx+0x7fff,gy+0x7fff,gx+0x7fff,gy-0x8000,visptr);
2138               visptr->texturestart^=0xffff;
2139               visptr->textureend^=0xffff;
2140               visptr->shapenum=pwallobjlist[i]->texture;
2141               visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
2142               visptr->viewx+=2;
2143               if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
2144                  visptr++;
2145               visptr->texturestart=(gx-0x8000)&0xffff;
2146               visptr->textureend=visptr->texturestart;
2147               result=TransformPlane(gx+0x7fff,gy-0x8000,gx-0x8000,gy-0x8000,visptr);
2148               visptr->texturestart^=0xffff;
2149               visptr->textureend^=0xffff;
2150               }
2151            else
2152               {
2153               visptr->texturestart=(gx-0x8000)&0xffff;
2154               visptr->textureend=visptr->texturestart;//-0xffff;
2155               result=TransformPlane(gx-0x8000,gy+0x7fff,gx+0x7fff,gy+0x7fff,visptr);
2156               visptr->shapenum=pwallobjlist[i]->texture;
2157               visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
2158               visptr->viewx+=2;
2159               if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
2160                  visptr++;
2161               visptr->texturestart=(gy-0x8000)&0xffff;
2162               visptr->textureend=visptr->texturestart;
2163               result=TransformPlane(gx+0x7fff,gy+0x7fff,gx+0x7fff,gy-0x8000,visptr);
2164               visptr->texturestart^=0xffff;
2165               visptr->textureend^=0xffff;
2166               }
2167 			  }
2168         visptr->viewx+=2;
2169         visptr->shapenum=pwallobjlist[i]->texture;
2170         visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
2171         if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
2172            visptr++;
2173         }
2174      }
2175 
2176 
2177 //
2178 // draw from back to front
2179 //
2180    numvisible = visptr-savedptr;
2181    if (!numvisible)
2182       return;
2183    SortVisibleList( numvisible, savedptr );
2184    for (i = 0; i<numvisible; i++)
2185       {
2186       //
2187       // draw farthest
2188       //
2189       if (sortedvislist[i]->shapenum & 0x1000)
2190          sortedvislist[i]->shapenum=animwalls[sortedvislist[i]->shapenum&0x3ff].texture;
2191       sortedvislist[i]->altshapenum=0;
2192       InterpolateWall (sortedvislist[i]);
2193       }
2194    visptr=savedptr;
2195 }
2196 
2197 /*
2198 ====================
2199 =
2200 = WallRefresh
2201 =
2202 ====================
2203 */
2204 
WallRefresh(void)2205 void WallRefresh (void)
2206 {
2207    volatile int dtime;
2208 	int mag;
2209    int yzangle;
2210 
2211    whereami=16;
2212    firstcoloffset=(firstcoloffset+(tics<<8))&65535;
2213 
2214    dtime=GetFastTics();
2215    if (missobj)
2216       {
2217       viewangle=missobj->angle;
2218 		viewx=missobj->x-costable[viewangle];
2219 		viewy=missobj->y+sintable[viewangle];
2220       pheight = missobj->z + 32;
2221       nonbobpheight=pheight;
2222       spotvis[missobj->tilex][missobj->tiley]=1;
2223 		yzangle=missobj->yzangle;
2224       }
2225    else
2226       {
2227       if (player->flags&FL_SHROOMS)
2228          {
2229          viewangle = (player->angle + FixedMulShift(FINEANGLES,sintable[(GetTicCount()<<5)&(FINEANGLES-1)],(16+4)))&(FINEANGLES-1);
2230          ChangeFocalWidth(FixedMulShift(40,sintable[(GetTicCount()<<5)&(FINEANGLES-1)],16));
2231          }
2232       else
2233          viewangle = player->angle;
2234       if ((viewangle<0) && (viewangle>=FINEANGLES))
2235          Error ("View angle out of range = %ld\n",viewangle);
2236       viewx = player->x;
2237       viewy = player->y;
2238       pheight = player->z + locplayerstate->playerheight + locplayerstate->heightoffset;
2239       nonbobpheight=pheight;
2240       if (
2241            (
2242              (player->z == nominalheight) ||
2243              (IsPlatform(player->tilex,player->tiley)) ||
2244              (DiskAt(player->tilex,player->tiley))
2245            ) &&
2246            (!(player->flags & FL_DOGMODE)) &&
2247            (BobbinOn==true) &&
2248            (GamePaused==false)
2249          )
2250 			{
2251          int mag;
2252 
2253          mag=(player->speed>MAXBOB ? MAXBOB : player->speed);
2254 
2255          pheight+=FixedMulShift(mag,sintable[(GetTicCount()<<7)&2047],28);
2256 
2257          weaponbobx=FixedMulShift(mag,costable[((GetTicCount()<<5))&(FINEANGLES-1)],27);
2258          weaponboby=FixedMulShift(mag,sintable[((GetTicCount()<<5))&((FINEANGLES/2)-1)],26);
2259 			}
2260       else
2261          {
2262          weaponbobx=0;
2263          weaponboby=0;
2264          }
2265       yzangle=player->yzangle;
2266       spotvis[player->tilex][player->tiley]=1;
2267       }
2268 
2269 	if (yzangle > ANG180)
2270       pheight -= (sintable[yzangle&2047] >> 14);
2271 	else
2272       pheight += (sintable[yzangle&2047] >> 14);
2273 
2274    viewx -= (FixedMul(sintable[yzangle&2047],costable[viewangle&2047])>>1);
2275    viewy += (FixedMul(sintable[yzangle&2047],sintable[viewangle&2047])>>1);
2276 
2277 // Set YZ angle
2278 
2279    centery=viewheight>>1;
2280 
2281 	if (yzangle>ANG180)
2282 		centery-=FixedMul(FINEANGLES-yzangle,yzangleconverter);
2283 	else
2284 		centery+=FixedMul(yzangle,yzangleconverter);
2285 
2286    centeryfrac=(centery<<16);
2287 
2288 	if (pheight < 1)
2289 	   pheight = 1;
2290 	else if (pheight > maxheight+30)
2291 		pheight = maxheight+30;
2292 
2293    if (nonbobpheight < 1)
2294       nonbobpheight = 1;
2295    else if (nonbobpheight > maxheight+30)
2296       nonbobpheight = maxheight+30;
2297 
2298    // Set light level of touchplates etc.
2299 
2300    mag=7+((3-gamestate.difficulty)<<2);
2301 
2302    transparentlevel=FixedMul(mag,sintable[(GetTicCount()<<5)&(FINEANGLES-1)])+mag;
2303 
2304    viewsin = sintable[viewangle];
2305    viewcos = costable[viewangle];
2306    c_startx=(scale*viewcos)-(centerx*viewsin);
2307    c_starty=(-scale*viewsin)-(centerx*viewcos);
2308    Refresh ();
2309    UpdateClientControls();
2310    TransformPushWalls();
2311    TransformDoors();
2312    UpdateClientControls();
2313    DrawWalls();
2314    UpdateClientControls();
2315    walltime=GetFastTics()-dtime;
2316 
2317 }
2318 
2319 
2320 /*
2321 ====================
2322 =
2323 = GetRainBoundingBox
2324 =
2325 ====================
2326 */
2327 
GetRainBoundingBox(int * xmin,int * xmax,int * ymin,int * ymax)2328 void GetRainBoundingBox (int * xmin, int * xmax, int * ymin, int * ymax)
2329 {
2330    wallcast_t * post;
2331    int x,y;
2332 
2333    // zero out all boundaries by default
2334 
2335    *xmax=0;
2336    *ymax=0;
2337    *xmin=127<<16;
2338    *ymin=127<<16;
2339 
2340    // check player's x and y
2341 
2342    if (viewx<(*xmin))
2343       (*xmin)=viewx;
2344    else if (viewx>(*xmax))
2345       (*xmax)=viewx;
2346 
2347    if (viewy<(*ymin))
2348       (*ymin)=viewy;
2349    else if (viewy>(*ymax))
2350       (*ymax)=viewy;
2351 
2352    for (post=&posts[0];post<&posts[viewwidth];post+=(viewwidth>>2))
2353       {
2354       x=(post->offset>>7)<<16;
2355       y=(post->offset&0x7f)<<16;
2356 
2357       if (x<(*xmin))
2358          (*xmin)=x;
2359       else if (x>(*xmax))
2360          (*xmax)=x;
2361 
2362       if (y<(*ymin))
2363          (*ymin)=y;
2364       else if (y>(*ymax))
2365          (*ymax)=y;
2366       }
2367 }
2368 
2369 /*
2370 ========================
2371 =
2372 = InterpolateWall
2373 =
2374 ========================
2375 */
2376 
InterpolateWall(visobj_t * plane)2377 void InterpolateWall (visobj_t * plane)
2378 {
2379    int d1,d2;
2380    int top;
2381    int topinc;
2382    int bot;
2383    int botinc;
2384    int i;
2385    int texture;
2386    int dh;
2387    int dx;
2388    int height;
2389    byte * buf;
2390 
2391    whereami=17;
2392    dx=(plane->x2-plane->x1+1);
2393    if (plane->h1<=0 || plane->h2<=0 || dx==0)
2394       return;
2395    d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
2396    d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
2397    dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
2398    top=0;
2399    topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
2400    bot=d2*dx;
2401    botinc=d1-d2;
2402    height=plane->h1<<DHEIGHTFRACTION;
2403    buf=(byte *)bufferofs;
2404    if (plane->x1>=viewwidth)
2405       return;
2406    for (i=plane->x1;i<=plane->x2;i++)
2407       {
2408       if ((i>=0 && i<viewwidth)&&(posts[i].wallheight<=(height>>DHEIGHTFRACTION)))
2409          {
2410          if (bot)
2411             {
2412             texture=((top/bot)+(plane->texturestart>>4))&0xfc0;
2413             posts[i].texture=texture<<4;
2414             posts[i].lump=plane->shapenum;
2415 				posts[i].alttile=plane->altshapenum;
2416             posts[i].posttype=plane->viewx;
2417             posts[i].offset=plane->shapesize;
2418             posts[i].wallheight=height>>DHEIGHTFRACTION;
2419             }
2420          }
2421       top+=topinc;
2422       bot+=botinc;
2423       height+=dh;
2424       }
2425 }
2426 
2427 
2428 /*
2429 ========================
2430 =
2431 = InterpolateDoor
2432 =
2433 ========================
2434 */
2435 
InterpolateDoor(visobj_t * plane)2436 void InterpolateDoor (visobj_t * plane)
2437 {
2438    int d1,d2;
2439    int top;
2440    int topinc;
2441    int bot;
2442    int botinc;
2443    int i;
2444    int texture;
2445    int dh;
2446    int dx;
2447    int height;
2448    int bottomscreen;
2449    byte * shape;
2450    byte * shape2;
2451    byte * buf;
2452    patch_t *p;
2453    int pl;
2454 
2455    whereami=18;
2456    dx=(plane->x2-plane->x1+1);
2457    if (plane->h1<=0 || plane->h2<=0 || dx==0)
2458       return;
2459    shape=W_CacheLumpNum(plane->shapenum,PU_CACHE, Cvt_patch_t, 1);
2460 	shape2=W_CacheLumpNum(plane->altshapenum,PU_CACHE, Cvt_patch_t, 1);
2461    p=(patch_t *)shape;
2462    d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
2463    d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
2464    dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
2465    topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
2466    botinc=d1-d2;
2467    if (plane->x1>=viewwidth)
2468       return;
2469 #ifdef DOS
2470    for (pl=0;pl<4;pl++)
2471 #endif
2472       {
2473 #ifdef DOS
2474       top=topinc*pl;
2475       bot=(d2*dx)+(pl*botinc);
2476       height=(plane->h1<<DHEIGHTFRACTION)+(dh*pl);
2477       buf=(byte *)bufferofs+((pl+plane->x1)>>2);
2478       VGAWRITEMAP((plane->x1+pl)&3);
2479 
2480       for (i=plane->x1+pl;i<=plane->x2;i+=4,buf++)
2481 #else
2482       top=0;
2483       bot=(d2*dx);
2484       height=(plane->h1<<DHEIGHTFRACTION);
2485       buf=(byte *)bufferofs+(plane->x1);
2486 
2487       for (i=plane->x1;i<=plane->x2;i++,buf++)
2488 #endif
2489          {
2490          if ((i>=0 && i<viewwidth) && (bot!=0) && (posts[i].wallheight<=(height>>DHEIGHTFRACTION)) )
2491             {
2492             dc_invscale=height>>(HEIGHTFRACTION+DHEIGHTFRACTION-10);
2493             dc_iscale = 0xffffffffu/(unsigned)dc_invscale;
2494             dc_texturemid=((pheight-nominalheight+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
2495             sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
2496 
2497             texture=((top/bot)+(plane->texturestart>>4))>>6;
2498             SetLightLevel(height>>DHEIGHTFRACTION);
2499             ScaleMaskedPost (p->collumnofs[texture]+shape,buf);
2500 
2501             if (levelheight>1)
2502                {
2503                sprtopoffset-=(dc_invscale<<6)*(levelheight-1);
2504                bottomscreen =sprtopoffset + (dc_invscale*nominalheight);
2505                dc_yl = (sprtopoffset+SFRACUNIT-1)>>SFRACBITS;
2506                dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
2507                if (dc_yl >= viewheight)
2508                   continue;
2509                else if (dc_yl < 0)
2510 						dc_yl = 0;
2511                if (dc_yh > viewheight)
2512                   dc_yh = viewheight;
2513 
2514                dc_source=shape2+((texture<<6)&0xfc0);
2515                R_DrawWallColumn (buf);
2516                }
2517             }
2518 
2519 #ifdef DOS
2520          top+=topinc<<2;
2521          bot+=botinc<<2;
2522          height+=dh<<2;
2523 #else
2524          top+=topinc;
2525          bot+=botinc;
2526          height+=dh;
2527 #endif
2528          }
2529       }
2530 }
2531 
2532 
2533 /*
2534 ========================
2535 =
2536 = InterpolateMaskedWall
2537 =
2538 ========================
2539 */
2540 
InterpolateMaskedWall(visobj_t * plane)2541 void InterpolateMaskedWall (visobj_t * plane)
2542 {
2543    int d1,d2;
2544    int top;
2545    int topinc;
2546    int bot;
2547    int botinc;
2548    int i;
2549    int j;
2550    int texture;
2551    int dh;
2552    int dx;
2553    int height;
2554    byte * shape;
2555    byte * shape2;
2556    byte * shape3;
2557    byte * buf;
2558 	transpatch_t *p;
2559    patch_t *p2;
2560    patch_t *p3;
2561    int pl;
2562    boolean drawbottom,drawmiddle,drawtop;
2563    int topoffset;
2564 
2565    whereami=19;
2566    dx=(plane->x2-plane->x1+1);
2567    if (plane->h1<=0 || plane->h2<=0 || dx==0)
2568       return;
2569    if (plane->altshapenum>=0)
2570       {
2571       drawmiddle=true;
2572       shape2=W_CacheLumpNum(plane->altshapenum,PU_CACHE, Cvt_patch_t, 1);
2573       p2=(patch_t *)shape2;
2574       topoffset=p2->topoffset;
2575       }
2576    else
2577       {
2578       drawmiddle=false;
2579       }
2580    if (plane->viewx>=0)
2581       {
2582       drawtop=true;
2583       shape3=W_CacheLumpNum(plane->viewx,PU_CACHE, Cvt_patch_t, 1);
2584       p3=(patch_t *)shape3;
2585       topoffset=p3->topoffset;
2586       }
2587    else
2588       {
2589       drawtop=false;
2590       }
2591    if (plane->shapenum>=0)
2592       {
2593       drawbottom=true;
2594       shape=W_CacheLumpNum(plane->shapenum,PU_CACHE, Cvt_transpatch_t, 1);
2595       p = (transpatch_t *)shape;
2596       topoffset=p->topoffset;
2597       }
2598    else
2599       {
2600       drawbottom=false;
2601       }
2602 
2603    d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
2604    d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
2605    dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
2606    topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
2607    botinc=d1-d2;
2608    if (plane->x1>=viewwidth)
2609       return;
2610 #ifdef DOS
2611    for (pl=0;pl<4;pl++)
2612 #endif
2613       {
2614 #ifdef DOS
2615       int planenum;
2616 
2617       top=topinc*pl;
2618       bot=(d2*dx)+(pl*botinc);
2619       height=(plane->h1<<DHEIGHTFRACTION)+(dh*pl);
2620       buf=(byte *)bufferofs+((pl+plane->x1)>>2);
2621       planenum=((plane->x1+pl)&3);
2622       VGAWRITEMAP(planenum);
2623       VGAREADMAP(planenum);
2624       for (i=plane->x1+pl;i<=plane->x2;i+=4,buf++)
2625 #else
2626       top=0;
2627       bot=(d2*dx);
2628       height=(plane->h1<<DHEIGHTFRACTION);
2629       buf=(byte *)bufferofs+(plane->x1);
2630       for (i=plane->x1;i<=plane->x2;i++,buf++)
2631 #endif
2632          {
2633          if ((i>=0 && i<viewwidth) && (bot!=0) && (posts[i].wallheight<=(height>>DHEIGHTFRACTION)) )
2634             {
2635             dc_invscale=height>>(HEIGHTFRACTION+DHEIGHTFRACTION-10);
2636             dc_iscale = 0xffffffffu/(unsigned)dc_invscale;
2637             dc_texturemid=((pheight-nominalheight+topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
2638             sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
2639 
2640             texture=((top/bot)+(plane->texturestart>>4))>>6;
2641             SetLightLevel(height>>DHEIGHTFRACTION);
2642             if (drawbottom==true)
2643                ScaleTransparentPost (p->collumnofs[texture]+shape,buf,(p->translevel+8));
2644 				for (j=0;j<levelheight-2;j++)
2645                {
2646                sprtopoffset-=(dc_invscale<<6);
2647                dc_texturemid+=(1<<22);
2648                if (drawmiddle==true)
2649                   ScaleMaskedPost (p2->collumnofs[texture]+shape2,buf);
2650                }
2651             if (levelheight>1)
2652                {
2653                sprtopoffset-=(dc_invscale<<6);
2654                dc_texturemid+=(1<<22);
2655                if (drawtop==true)
2656                   ScaleMaskedPost (p3->collumnofs[texture]+shape3,buf);
2657                }
2658             }
2659 #ifdef DOS
2660          top+=topinc<<2;
2661          bot+=botinc<<2;
2662          height+=dh<<2;
2663 #else
2664          top+=topinc;
2665          bot+=botinc;
2666          height+=dh;
2667 #endif
2668          }
2669       }
2670 }
2671 
2672 /*
2673 ========================
2674 =
2675 = DrawPlayerLocation
2676 =
2677 ========================
2678 */
2679 #define PLX  (320-24)
2680 #define PLY  16
DrawPlayerLocation(void)2681 void DrawPlayerLocation ( void )
2682 {
2683    int i;
2684    char buf[30];
2685 
2686    CurrentFont=tinyfont;
2687 
2688    whereami=20;
2689    VGAMAPMASK(15);
2690    for (i=0;i<18;i++)
2691 #ifdef DOS
2692       memset((byte *)bufferofs+(ylookup[i+PLY])+(PLX>>2),0,6);
2693 #else
2694       memset((byte *)bufferofs+(ylookup[i+PLY])+PLX,0,6);
2695 #endif
2696    px=PLX;
2697 	py=PLY;
2698 	VW_DrawPropString(strupr(itoa(player->x,&buf[0],16)));
2699 	px=PLX;
2700 	py=PLY+6;
2701 	VW_DrawPropString(strupr(itoa(player->y,&buf[0],16)));
2702 	px=PLX;
2703 	py=PLY+12;
2704 	VW_DrawPropString(strupr(itoa(player->angle,&buf[0],16)));
2705 }
2706 
2707 
2708 
2709 /*
2710 ========================
2711 =
2712 = ThreeDRefresh
2713 =
2714 ========================
2715 */
2716 
2717 
2718 int playerview=0;
ThreeDRefresh(void)2719 void      ThreeDRefresh (void)
2720 {
2721    objtype * tempptr;
2722 
2723    whereami=21;
2724    tempptr=player;
2725 #if (DEVELOPMENT == 1)
2726    if (Keyboard[sc_9])
2727       {
2728       while (Keyboard[sc_9])
2729          {
2730          IN_UpdateKeyboard();
2731          }
2732       playerview++;
2733       if (playerview>numplayers)
2734          playerview=1;
2735       }
2736    if (playerview!=0)
2737       {
2738       player=PLAYER[playerview-1];
2739       }
2740 #endif
2741 
2742 //
2743 // Erase old messages
2744 //
2745 
2746   RestoreMessageBackground();
2747 
2748   bufferofs += screenofs;
2749 
2750   RefreshClear();
2751 
2752   UpdateClientControls ();
2753 
2754 //
2755 // follow the walls from there to the right, drawwing as we go
2756 //
2757 
2758 	visptr = &vislist[0];
2759 	WallRefresh ();
2760 
2761    UpdateClientControls ();
2762 
2763 	if (fandc)
2764 		DrawPlanes();
2765 
2766    UpdateClientControls ();
2767 
2768 //
2769 // draw all the scaled images
2770 //
2771     DrawScaleds();                                         // draw scaled stuff
2772 
2773    UpdateClientControls ();
2774 
2775 	if (!missobj)
2776 		{
2777 		if (locplayerstate->NETCAPTURED && (locplayerstate->NETCAPTURED != -2))
2778 			{
2779 			int value;
2780 
2781 			if (locplayerstate->NETCAPTURED < 0)
2782 			  value = -locplayerstate->NETCAPTURED;
2783 			else
2784 			  value = locplayerstate->NETCAPTURED;
2785 			DrawScreenSizedSprite(netlump+value-1);
2786 			}
2787 		DrawPlayerWeapon ();    // draw player's hand'
2788 
2789 		if (SCREENEYE)
2790 		  DrawScreenSprite(SCREENEYE->targettilex,SCREENEYE->targettiley,SCREENEYE->state->condition + GIBEYE1 + shapestart);
2791       UpdateClientControls ();
2792 
2793 	   if (player->flags&FL_GASMASK)
2794 		   DrawScreenSizedSprite(gmasklump);
2795 
2796 
2797       if ( SHOW_PLAYER_STATS() )
2798          {
2799          DrawStats ();
2800          }
2801 
2802       DoBorderShifts ();
2803 
2804       UpdateClientControls ();
2805       }
2806 
2807    bufferofs -= screenofs;
2808    DrawMessages();
2809    bufferofs += screenofs;
2810 
2811    if ( ((GamePaused==true) && (!Keyboard[sc_LShift])) ||
2812         (controlupdatestarted==0)
2813       )
2814       DrawPause ();
2815 
2816 //
2817 // show screen and time last cycle
2818 //
2819    if ((fizzlein==true) && (modemgame==false))
2820    {
2821       if (newlevel==true)
2822          ShutdownClientControls();
2823       bufferofs-=screenofs;
2824       DrawPlayScreen (true);
2825       RotateBuffer(0,FINEANGLES,FINEANGLES*8,FINEANGLES,(VBLCOUNTER*3)/4);
2826       bufferofs+=screenofs;
2827       fizzlein = false;
2828       StartupClientControls();
2829    }
2830 
2831    bufferofs -= screenofs;
2832 
2833    UpdateClientControls ();
2834 
2835    if (HUD == true)
2836       DrawPlayerLocation();
2837 
2838    FlipPage();
2839    gamestate.frame++;
2840 
2841    player=tempptr;
2842 }
2843 
2844 
2845 //******************************************************************************
2846 //
2847 // FlipPage
2848 //
2849 //******************************************************************************
2850 
FlipPage(void)2851 void FlipPage ( void )
2852 {
2853 #ifdef DOS
2854    unsigned displaytemp;
2855 
2856    whereami=22;
2857    displayofs = bufferofs;
2858 
2859    displaytemp = displayofs;
2860    if ( ( SHAKETICS != 0xFFFF ) && ( !inmenu ) && ( !GamePaused ) &&
2861       ( !fizzlein ) )
2862       {
2863       ScreenShake ();
2864       }
2865 
2866 
2867 //   _disable();
2868    OUTP(CRTC_INDEX,CRTC_STARTHIGH);
2869    OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
2870 
2871 
2872    if (SHAKETICS != 0xFFFF)
2873    {
2874       if (SHAKETICS > 0)
2875       {
2876          OUTP (CRTC_INDEX, CRTC_STARTLOW);
2877          OUTP (CRTC_DATA, (displayofs&0x000000FF));
2878          displayofs = displaytemp;
2879       }
2880       else
2881       {
2882          displayofs = displaytemp;
2883          OUTP(CRTC_INDEX,CRTC_STARTHIGH);
2884          OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
2885          OUTP (CRTC_INDEX, CRTC_STARTLOW);
2886          OUTP (CRTC_DATA, (displayofs&0x000000FF));
2887          SHAKETICS = 0xFFFF;
2888       }
2889    }
2890 //   _enable();
2891 
2892    bufferofs += screensize;
2893    if (bufferofs > page3start)
2894       bufferofs = page1start;
2895 #else
2896 
2897    whereami=22;
2898 
2899    if ( ( SHAKETICS != 0xFFFF ) && ( !inmenu ) && ( !GamePaused ) &&
2900       ( !fizzlein ) )
2901       {
2902       ScreenShake ();
2903       }
2904 
2905       /* TODO some shake thing */
2906 
2907       /* just call the one in modexlib.c */
2908       XFlipPage();
2909 
2910 #endif
2911 }
2912 
2913 
2914 //******************************************************************************
2915 //
2916 // TurnShakeOff
2917 //
2918 //******************************************************************************
TurnShakeOff(void)2919 void TurnShakeOff
2920    (
2921    void
2922    )
2923 
2924    {
2925 //   _disable();
2926    OUTP (CRTC_INDEX, CRTC_STARTHIGH );
2927    OUTP (CRTC_DATA, ( ( displayofs & 0x0000ffff ) >> 8 ) );
2928    OUTP (CRTC_INDEX, CRTC_STARTLOW);
2929    OUTP (CRTC_DATA, (displayofs&0x000000FF));
2930 //   _enable();
2931    }
2932 
2933 //******************************************************************************
2934 //
2935 // DrawScaledScreen
2936 //
2937 //******************************************************************************
2938 
DrawScaledScreen(int x,int y,int step,byte * src)2939 void DrawScaledScreen(int x, int y, int step, byte * src)
2940 {
2941     int     xfrac;
2942     int     yfrac;
2943     int     plane;
2944     int     i,j;
2945     byte    * p;
2946     byte    * buf;
2947     int     xsize;
2948     int     ysize;
2949 
2950     xsize=(320<<16)/step;
2951     if (xsize>320) xsize=320;
2952     ysize=(200<<16)/step;
2953     if (ysize>200) ysize=200;
2954 
2955 #ifdef DOS
2956     for (plane=x;plane<x+4;plane++)
2957 #endif
2958        {
2959        yfrac=0;
2960 #ifdef DOS
2961        VGAWRITEMAP(plane&3);
2962 #endif
2963        for (j=y;j<y+ysize;j++)
2964           {
2965           p=src+(320*(yfrac>>16));
2966 #ifdef DOS
2967           buf=(byte *)bufferofs+ylookup[j]+(plane>>2);
2968 #else
2969           buf=(byte *)bufferofs+ylookup[j]+x;
2970 #endif
2971 #ifdef DOS
2972           xfrac=(plane-x)*step;
2973 #else
2974           xfrac=0;
2975 #endif
2976           yfrac+=step;
2977 #ifdef DOS
2978           for (i=plane;i<x+xsize;i+=4)
2979 #else
2980           for (i=x;i<x+xsize;i++)
2981 #endif
2982              {
2983              *buf=*(p+(xfrac>>16));
2984              buf++;
2985 #ifdef DOS
2986              xfrac+=(step<<2);
2987 #else
2988              xfrac+=step;
2989 #endif
2990              }
2991           }
2992        }
2993 }
2994 
2995 
2996 //******************************************************************************
2997 //
2998 // DoLoadGameSequence
2999 //
3000 //******************************************************************************
3001 
DoLoadGameSequence(void)3002 void DoLoadGameSequence ( void )
3003 {
3004    int x;
3005    int y;
3006    int dx;
3007    int dy;
3008    int s;
3009    int ds;
3010    int time;
3011    int i;
3012    byte * destscreen;
3013 
3014    fizzlein=false;
3015    x=(18+SaveGamePicX)<<16;
3016    y=(30+SaveGamePicY)<<16;
3017    time=VBLCOUNTER;
3018    s=0x2000000;
3019    dx=(-x)/time;
3020    dy=(-y)/time;
3021    ds=-((s-0x1000000)/time);
3022 
3023    destscreen=SafeMalloc(64000);
3024 
3025    SetupScreen(false);
3026    ThreeDRefresh();
3027    FlipPage();
3028    FlipPage();
3029 
3030    VL_CopyPlanarPageToMemory ( (byte *)bufferofs,  destscreen );
3031    VL_CopyDisplayToHidden ();
3032 
3033    CalcTics();
3034    for (i=0;i<time;i+=tics)
3035       {
3036       CalcTics();
3037       DrawScaledScreen((x>>16),(y>>16),(s>>8),destscreen);
3038       FlipPage();
3039       x+=(dx*tics);
3040       if (x<0) x=0;
3041       y+=(dy*tics);
3042       if (y<0) y=0;
3043       s+=(ds*tics);
3044       }
3045    DrawScaledScreen(0,0,0x10000,destscreen);
3046    FlipPage();
3047    VL_CopyDisplayToHidden ();
3048    SafeFree(destscreen);
3049    CalcTics();
3050    CalcTics();
3051 }
3052 
3053 //******************************************************************************
3054 //
3055 // StartupRotateBuffer
3056 //
3057 //******************************************************************************
3058 byte * RotatedImage;
3059 boolean RotateBufferStarted = false;
StartupRotateBuffer(int masked)3060 void StartupRotateBuffer ( int masked)
3061 {
3062    int i,a,b;
3063 
3064    if (RotateBufferStarted == true)
3065       return;
3066 
3067    RotateBufferStarted = true;
3068 
3069    RotatedImage=SafeMalloc(131072);
3070    if (masked==0)
3071       memset(RotatedImage,0,131072);
3072    else
3073       memset(RotatedImage,0xff,131072);
3074 #ifdef DOS
3075    for (i=0;i<4;i++)
3076 #endif
3077       {
3078       VGAREADMAP(i);
3079       for (a=0;a<200;a++)
3080 #ifdef DOS
3081          for (b=0;b<80;b++)
3082             *(RotatedImage+99+i+((a+28)<<9)+(b<<2))=*((byte *)bufferofs+(a*linewidth)+b);
3083 #else
3084          for (b=0;b<320;b++)
3085             *(RotatedImage+99+((a+28)<<9)+b)=*((byte *)bufferofs+(a*linewidth)+b);
3086 #endif
3087       }
3088 }
3089 
3090 //******************************************************************************
3091 //
3092 // ShutdownRotateBuffer
3093 //
3094 //******************************************************************************
3095 
ShutdownRotateBuffer(void)3096 void ShutdownRotateBuffer ( void )
3097 {
3098    if (RotateBufferStarted == false)
3099       return;
3100 
3101    RotateBufferStarted = false;
3102    SafeFree(RotatedImage);
3103 }
3104 
3105 //******************************************************************************
3106 //
3107 // ScaleAndRotateBuffer
3108 //
3109 //******************************************************************************
3110 
ScaleAndRotateBuffer(int startangle,int endangle,int startscale,int endscale,int time)3111 void ScaleAndRotateBuffer (int startangle, int endangle, int startscale, int endscale, int time)
3112 {
3113    int anglestep;
3114    int scalestep;
3115    int angle;
3116    int scale;
3117    int i;
3118 
3119    anglestep=((endangle-startangle)<<16)/time;
3120    scalestep=((endscale-startscale)<<6)/time;
3121 
3122    angle=(startangle<<16);
3123    scale=(startscale<<6);
3124 
3125    CalcTics();
3126    CalcTics();
3127    for (i=0;i<time;i+=tics)
3128       {
3129       DrawRotatedScreen(160,100, (byte *)bufferofs,(angle>>16)&(FINEANGLES-1),scale>>6,0);
3130       FlipPage();
3131       scale+=(scalestep*tics);
3132       angle+=(anglestep*tics);
3133       CalcTics();
3134       }
3135    DrawRotatedScreen(160,100, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
3136    FlipPage();
3137    DrawRotatedScreen(160,100, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
3138    FlipPage();
3139    DrawRotatedScreen(160,100, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
3140    CalcTics();
3141    CalcTics();
3142 }
3143 
3144 //******************************************************************************
3145 //
3146 // RotateBuffer
3147 //
3148 //******************************************************************************
3149 
RotateBuffer(int startangle,int endangle,int startscale,int endscale,int time)3150 void RotateBuffer (int startangle, int endangle, int startscale, int endscale, int time)
3151 {
3152    int savetics;
3153 
3154    //save off fastcounter
3155 
3156    savetics=GetFastTics();
3157 
3158    StartupRotateBuffer (0);
3159 
3160    ScaleAndRotateBuffer (startangle, endangle, startscale, endscale, time);
3161 
3162    ShutdownRotateBuffer ();
3163 
3164    // restore fast counter
3165    SetFastTics(savetics);
3166 }
3167 
3168 
3169 //******************************************************************************
3170 //
3171 // DrawRotatedScreen
3172 //
3173 //******************************************************************************
3174 
DrawRotatedScreen(int cx,int cy,byte * destscreen,int angle,int scale,int masked)3175 void DrawRotatedScreen(int cx, int cy, byte *destscreen, int angle, int scale, int masked)
3176 {
3177    int     c, s;
3178    int     xst, xct;
3179    int     y;
3180    int     plane;
3181    byte    * screen;
3182 
3183    c = FixedMulShift(scale,costable[angle],11);
3184    s = FixedMulShift(scale,sintable[angle],11);
3185    xst = (((-cx)*s)+(128<<16))-(cy*c);
3186    xct = (((-cx)*c)+(256<<16)+(1<<18)-(1<<16))+(cy*s);
3187 #ifdef DOS
3188    mr_xstep=s<<2;
3189    mr_ystep=c<<2;
3190 #else
3191    mr_xstep=s;
3192    mr_ystep=c;
3193 #endif
3194    screen=destscreen;
3195 
3196    if (masked==0)
3197       {
3198 #ifdef DOS
3199       for (plane=0;plane<4;plane++,xst+=s,xct+=c)
3200 #endif
3201          {
3202          mr_yfrac=xct;
3203          mr_xfrac=xst;
3204          VGAWRITEMAP(plane);
3205          for (y=0; y<200; y++,mr_xfrac+=c,mr_yfrac-=s)
3206 #ifdef DOS
3207             DrawRotRow(((320-plane)>>2)+1,screen+ylookup[y]+(plane>>2),RotatedImage);
3208 #else
3209             DrawRotRow(320,screen+ylookup[y],RotatedImage);
3210 #endif
3211          }
3212       }
3213    else
3214       {
3215 #ifdef DOS
3216       for (plane=0;plane<4;plane++,xst+=s,xct+=c)
3217 #endif
3218          {
3219          mr_yfrac=xct;
3220          mr_xfrac=xst;
3221          VGAWRITEMAP(plane);
3222          for (y=0; y<200; y++,mr_xfrac+=c,mr_yfrac-=s)
3223 #ifdef DOS
3224             DrawMaskedRotRow(((320-plane)>>2)+1,screen+ylookup[y]+(plane>>2),RotatedImage);
3225 #else
3226             DrawMaskedRotRow(320,screen+ylookup[y],RotatedImage);
3227 #endif
3228          }
3229       }
3230 }
3231 
3232 
3233 //******************************************************************************
3234 //
3235 // DrawScaledPost
3236 //
3237 //******************************************************************************
3238 
DrawScaledPost(int height,byte * src,int offset,int x)3239 void DrawScaledPost ( int height, byte * src, int offset, int x)
3240 {
3241    patch_t *p;
3242 
3243    p=(patch_t *)src;
3244    dc_invscale=(height<<16)/p->origsize;
3245    dc_iscale=(p->origsize<<16)/height;
3246    dc_texturemid=(((p->origsize>>1)+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
3247    sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
3248    shadingtable=colormap+(1<<12);
3249    VGAWRITEMAP(x&3);
3250 #ifdef DOS
3251    ScaleMaskedPost(((p->collumnofs[offset])+src), (byte *)bufferofs+(x>>2));
3252 #else
3253    ScaleMaskedPost(((p->collumnofs[offset])+src), (byte *)bufferofs+x);
3254 #endif
3255 }
3256 
3257 
3258 
ApogeeTitle(void)3259 void ApogeeTitle (void)
3260 {
3261    byte pal[768];
3262    int   angle;
3263    int   scale;
3264    int   x,y;
3265    int   danglex;
3266    int   anglex;
3267    int   dy,dangle,dscale;
3268    int   time;
3269 
3270    CalcTics();
3271    CalcTics();
3272    IN_ClearKeysDown();
3273    viewwidth=320;
3274    viewheight=200;
3275    memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE, CvtNull, 1),768);
3276    shadingtable=colormap+(1<<12);
3277    VL_NormalizePalette(&pal[0]);
3278    SwitchPalette(&pal[0],35);
3279 //   DrawWorld();
3280 //   RotateBuffer(0,FINEANGLES*6,FINEANGLES*48,FINEANGLES,(VBLCOUNTER*2));
3281 //   DoLaserShoot("apogee");
3282 //   DoZIntro();
3283 
3284    VL_ClearBuffer (bufferofs, 255);
3285    DrawNormalSprite (0, 0, W_GetNumForName("ap_titl"));
3286 
3287    StartupRotateBuffer (1);
3288 
3289    //save off fastcounter
3290 
3291 #define APOGEEXANGLE 913
3292 #define APOGEEXMAG   180
3293 #define APOGEESTARTY 0
3294 #define APOGEEENDY   100
3295 
3296 #define APOGEESCALESTART (FINEANGLES<<4)
3297 #define APOGEESCALEEND (FINEANGLES)
3298 #define APOGEESONGTIME (124-1)
3299 
3300    time = APOGEESONGTIME;
3301 
3302    anglex=0;
3303    danglex=(APOGEEXANGLE<<16)/time;
3304 
3305    y=APOGEESTARTY<<16;
3306    dy=((APOGEEENDY-APOGEESTARTY)<<16)/time;
3307 
3308    dscale=((APOGEESCALEEND-APOGEESCALESTART)<<16)/time;
3309    scale=APOGEESCALESTART<<16;
3310 
3311    angle=0;
3312    dangle=(FINEANGLES<<17)/time;
3313 
3314    MU_StartSong(song_apogee);
3315 
3316    CalcTics();
3317 
3318    while (time>=0)
3319       {
3320       VL_DrawPostPic (W_GetNumForName("ap_wrld"));
3321       IN_PumpEvents();
3322 
3323       x=100+FixedMul(APOGEEXMAG,sintable[anglex>>16]);
3324 
3325       DrawRotatedScreen(x,y>>16,(byte *)bufferofs,(angle>>16)&(FINEANGLES-1),scale>>16,1);
3326       FlipPage();
3327       CalcTics();
3328       angle+=dangle*tics;
3329       scale+=dscale*tics;
3330       y+=dy*tics;
3331       anglex+=danglex*tics;
3332       time-=tics;
3333       if ((LastScan) || IN_GetMouseButtons())
3334          goto apogeeexit;
3335       }
3336    CalcTics();
3337    CalcTics();
3338    VL_DrawPostPic (W_GetNumForName("ap_wrld"));
3339    DrawRotatedScreen(x,y>>16,(byte *)bufferofs,0,APOGEESCALEEND,1);
3340    FlipPage();
3341 
3342    while (MU_SongPlaying())
3343       {
3344       IN_PumpEvents();
3345       if ((LastScan) || IN_GetMouseButtons())
3346          goto apogeeexit;
3347       }
3348 
3349 apogeeexit:
3350    ShutdownRotateBuffer ();
3351 }
3352 
3353 #if (SHAREWARE==0)
3354 
DopefishTitle(void)3355 void DopefishTitle (void)
3356 {
3357    int shapenum;
3358    int height;
3359 
3360    shapenum=W_GetNumForName("scthead1");
3361    CalcTics();
3362    CalcTics();
3363    IN_ClearKeysDown();
3364    MU_StartSong( song_secretmenu);
3365    viewwidth=320;
3366    viewheight=200;
3367    SwitchPalette(origpal,35);
3368    oldtime=GetTicCount();
3369    FlipPage();
3370    for (height=1;height<200;height+=(tics<<2))
3371       {
3372       DrawPositionedScaledSprite (160, 100, shapenum, height, 0);
3373       FlipPage();
3374       CalcTics();
3375       if ((LastScan) || IN_GetMouseButtons())
3376          break;
3377       }
3378    SD_Play ( SD_DOPEFISHSND );
3379    oldtime=GetTicCount();
3380    for (height=0;height<FINEANGLES<<1;height+=(tics<<5))
3381       {
3382       DrawPositionedScaledSprite (160+FixedMul(60,costable[height&(FINEANGLES-1)]), 100+FixedMul(60,sintable[height&(FINEANGLES-1)]), shapenum, 200, 0);
3383       FlipPage();
3384       VL_CopyPlanarPage ( (byte *) displayofs, (byte *) bufferofs );
3385       CalcTics();
3386       if ((LastScan) || IN_GetMouseButtons())
3387          break;
3388       }
3389    SD_Play ( SD_DOPEFISHSND );
3390    FlipPage();
3391 }
3392 
3393 #endif
3394 
3395 //******************************************************************************
3396 //
3397 // RotationFun
3398 //
3399 //******************************************************************************
3400 
RotationFun(void)3401 void RotationFun ( void )
3402 {
3403    int   angle;
3404    int   scale;
3405    int   x,y;
3406    word  buttons;
3407 
3408    //save off fastcounter
3409 
3410 
3411    angle=0;
3412    scale=FINEANGLES;
3413 
3414    StartupRotateBuffer (0);
3415 
3416    CalcTics();
3417    CalcTics();
3418    while (!Keyboard[sc_Escape])
3419       {
3420       IN_UpdateKeyboard ();
3421       DrawRotatedScreen(160,100,(byte *)bufferofs,angle,scale,0);
3422       FlipPage();
3423       CalcTics();
3424       INL_GetMouseDelta(&x, &y);
3425       buttons=IN_GetMouseButtons ();
3426       angle=(angle-x)&(FINEANGLES-1);
3427       if (buttons & (1 << 0))
3428          {
3429          if (scale>0)
3430             scale-=30;
3431          }
3432       else if (buttons & (1 << 1))
3433          {
3434          scale+=30;
3435          }
3436       }
3437    CalcTics();
3438    CalcTics();
3439    Keyboard[sc_Escape]=0;
3440 
3441    ShutdownRotateBuffer ();
3442 }
3443 
3444 boolean ScreenSaverStarted=false;
3445 screensaver_t * ScreenSaver;
3446 #define PAUSETIME  (70)
3447 
3448 //******************************************************************************
3449 //
3450 // SetupScreenSaverPhase
3451 //
3452 //******************************************************************************
SetupScreenSaverPhase(void)3453 void SetupScreenSaverPhase ( void )
3454 {
3455    if (ScreenSaverStarted==false)
3456       return;
3457 
3458    if (ScreenSaver->phase==0)
3459       {
3460       ScreenSaver->x=160;
3461       ScreenSaver->y=100;
3462       ScreenSaver->angle=0;
3463       ScreenSaver->scale=FINEANGLES;
3464       ScreenSaver->dangle=FINEANGLES/VBLCOUNTER;
3465       ScreenSaver->dx=0;
3466       ScreenSaver->dy=0;
3467       ScreenSaver->dscale=((FINEANGLES<<2)-(FINEANGLES))/VBLCOUNTER;
3468       ScreenSaver->time=VBLCOUNTER;
3469       }
3470    else if (ScreenSaver->phase==1)
3471       {
3472       ScreenSaver->x=160;
3473       ScreenSaver->y=100;
3474       ScreenSaver->angle=0;
3475       ScreenSaver->scale=FINEANGLES<<2;
3476       ScreenSaver->dangle=FINEANGLES/VBLCOUNTER;
3477       ScreenSaver->dx=RandomNumber("StartupScreen",0)>>5;
3478       ScreenSaver->dy=RandomNumber("StartupScreen",0)>>5;
3479       ScreenSaver->dscale=0;
3480       ScreenSaver->time=-1;
3481       }
3482 }
3483 
3484 //******************************************************************************
3485 //
3486 // StartupScreenSaver
3487 //
3488 //******************************************************************************
StartupScreenSaver(void)3489 void StartupScreenSaver ( void )
3490 {
3491    if (ScreenSaverStarted==true)
3492       return;
3493 
3494    ScreenSaverStarted=true;
3495 
3496    StartupRotateBuffer (0);
3497 
3498    ScreenSaver=(screensaver_t *)SafeMalloc(sizeof(screensaver_t));
3499    ScreenSaver->phase=0;
3500    ScreenSaver->pausetime=PAUSETIME;
3501    ScreenSaver->pausex=120;
3502    ScreenSaver->pausey=84;
3503    SetupScreenSaverPhase();
3504 }
3505 
3506 //******************************************************************************
3507 //
3508 // ShutdownScreenSaver
3509 //
3510 //******************************************************************************
ShutdownScreenSaver(void)3511 void ShutdownScreenSaver ( void )
3512 {
3513    if (ScreenSaverStarted==false)
3514       return;
3515 
3516    ScreenSaverStarted=false;
3517 
3518    ShutdownRotateBuffer ();
3519    SafeFree(ScreenSaver);
3520 }
3521 
3522 //******************************************************************************
3523 //
3524 // UpdateScreenSaver
3525 //
3526 //******************************************************************************
3527 
3528 #define SPINSIZE  40
3529 #define MAXSPEED  8
UpdateScreenSaver(void)3530 void UpdateScreenSaver ( void )
3531 {
3532    if (ScreenSaver->time!=-1)
3533       {
3534       ScreenSaver->time-=tics;
3535       if (ScreenSaver->time<0)
3536          {
3537          ScreenSaver->phase++;
3538          SetupScreenSaverPhase();
3539          }
3540       }
3541    ScreenSaver->x+=ScreenSaver->dx*tics;
3542    ScreenSaver->y+=ScreenSaver->dy*tics;
3543    ScreenSaver->angle=(ScreenSaver->angle+(ScreenSaver->dangle*tics))&(FINEANGLES-1);
3544    ScreenSaver->scale+=ScreenSaver->dscale*tics;
3545    if (ScreenSaver->x<SPINSIZE)
3546       {
3547       ScreenSaver->x=SPINSIZE;
3548       ScreenSaver->dx=abs(ScreenSaver->dx);
3549       ScreenSaver->dy+=(RandomNumber("Rotate",0)>>6)-2;
3550       }
3551    else if (ScreenSaver->x>320-SPINSIZE)
3552       {
3553       ScreenSaver->x=320-SPINSIZE;
3554       ScreenSaver->dx=-(abs(ScreenSaver->dx));
3555       ScreenSaver->dy+=(RandomNumber("Rotate",0)>>6)-2;
3556       }
3557    if (ScreenSaver->y<SPINSIZE)
3558       {
3559       ScreenSaver->y=SPINSIZE;
3560       ScreenSaver->dy=abs(ScreenSaver->dy);
3561       ScreenSaver->dx+=(RandomNumber("Rotate",0)>>6)-2;
3562       }
3563    else if (ScreenSaver->y>200-SPINSIZE)
3564       {
3565       ScreenSaver->y=200-SPINSIZE;
3566       ScreenSaver->dy=-(abs(ScreenSaver->dy));
3567       ScreenSaver->dx+=(RandomNumber("Rotate",0)>>6)-2;
3568       }
3569 
3570    if (abs(ScreenSaver->dx)>MAXSPEED)
3571       ScreenSaver->dx=SGN(ScreenSaver->dx)*MAXSPEED;
3572 
3573    if (abs(ScreenSaver->dy)>MAXSPEED)
3574       ScreenSaver->dy=SGN(ScreenSaver->dy)*MAXSPEED;
3575 
3576    DrawRotatedScreen(ScreenSaver->x,ScreenSaver->y, (byte *)bufferofs,ScreenSaver->angle,ScreenSaver->scale,0);
3577 
3578    ScreenSaver->pausetime-=tics;
3579    if (ScreenSaver->pausetime<=0)
3580       {
3581       ScreenSaver->pausetime=PAUSETIME;
3582       ScreenSaver->pausex=RandomNumber ("pausex",0)%240;
3583       ScreenSaver->pausey=RandomNumber ("pausey",0)%168;
3584       }
3585    DrawPauseXY (ScreenSaver->pausex, ScreenSaver->pausey);
3586 
3587    FlipPage();
3588 }
3589 #if 0
3590 
3591 //******************************************************************************
3592 //
3593 // DoLaserShoot
3594 //
3595 //******************************************************************************
3596 void DoLaserShoot (char * name)
3597 {
3598 
3599    int sourcex;
3600    int lastx;
3601    int sourceheight;
3602    int destheight;
3603    int sourcestep;
3604    int xstep;
3605    int hstep;
3606    int midx;
3607    int startx;
3608    int dx;
3609    int f;
3610    int s;
3611    int height;
3612    int x;
3613    int sx;
3614    int size;
3615    patch_t *p;
3616    byte * shape;
3617 
3618    DrawWorld();
3619    midx=160;
3620    shape=W_CacheLumpName(name,PU_CACHE);
3621    p=(patch_t *)shape;
3622    size=p->origsize;
3623 
3624    startx=midx-(size>>1)-(p->leftoffset);
3625 
3626    sourcex=0;
3627    lastx=startx+p->width;
3628    sourcestep=(320*65536)/p->width;
3629    sourceheight=p->origsize<<3;
3630    destheight=p->origsize;
3631    CalcTics();
3632    CalcTics();
3633 
3634 
3635    for (x=startx;x<lastx;x+=tics,sourcex+=(sourcestep*tics))
3636       {
3637       for (f=startx;f<=x;f++)
3638          DrawScaledPost(destheight,shape,f-startx,f);
3639       height=sourceheight<<16;
3640       if (x<=midx)
3641          {
3642          dx=x-(sourcex>>16);
3643          xstep=1;
3644          }
3645       else
3646          {
3647          dx=(sourcex>>16)-x;
3648          xstep=-1;
3649          }
3650       sx=sourcex>>16;
3651       if (dx)
3652          hstep=((-destheight+sourceheight)<<16)/dx;
3653       else
3654          hstep=0;
3655       for (s=0;s<dx;s++,height-=hstep,sx+=xstep)
3656          DrawScaledPost(height>>16,shape,x-startx,sx);
3657       FlipPage();
3658       CalcTics();
3659       DrawWorld();
3660          break;
3661       }
3662 
3663    // Write out one more time so that the rest of the screen is clear
3664 
3665    for (f=startx;f<lastx;f++)
3666       DrawScaledPost(destheight,shape,f-startx,f);
3667    FlipPage();
3668 }
3669 
3670 //******************************************************************************
3671 //
3672 // DoIntro
3673 //
3674 //******************************************************************************
3675 
3676 #define MAXMAG (80)
3677 #define OSCTIME (5*VBLCOUNTER)
3678 #define OSCXSHIFT (4)
3679 #define OSCTSHIFT (4)
3680 
3681 void DoIntro (void)
3682 {
3683    byte * shape;
3684    byte * origshape;
3685    int mag;
3686    int currentmag;
3687    int magstep;
3688    int time;
3689    int x;
3690    int t;
3691 
3692    shadingtable=colormap+(1<<12);
3693 
3694    origshape=W_CacheLumpName("ap_wrld",PU_CACHE);
3695 
3696    mag=MAXMAG<<16;
3697    magstep = (MAXMAG<<16)/OSCTIME;
3698    time = OSCTIME;
3699    t=0;
3700 
3701    CalcTics();
3702 
3703    while (time>0)
3704       {
3705       int yoffset;
3706       int ylow;
3707       int yhigh;
3708       int offset;
3709       int postheight;
3710       byte * src;
3711 
3712       shape=origshape;
3713       VL_ClearBuffer (bufferofs, 0);
3714       currentmag=mag>>16;
3715       for (x=0;x<320;x++,shape+=200)
3716          {
3717          VGAWRITEMAP(x&3);
3718          src=shape;
3719          offset=(t+(x<<OSCXSHIFT))&(FINEANGLES-1);
3720          yoffset=FixedMul(currentmag,sintable[offset]);
3721          ylow=yoffset;
3722          if (ylow<0)
3723             {
3724             src-=ylow;
3725             ylow=0;
3726             }
3727          if (ylow>199)
3728             ylow=199;
3729          yhigh=yoffset+200;
3730          if (yhigh>199)
3731             {
3732             yhigh=199;
3733             }
3734          if (yhigh<0)
3735             yhigh=0;
3736          postheight=yhigh-ylow+1;
3737          if (postheight>0)
3738 #ifdef DOS
3739             DrawSkyPost((byte *)bufferofs + (x>>2) + ylookup[ylow],src,postheight);
3740 #else
3741             DrawSkyPost((byte *)bufferofs + x + ylookup[ylow],src,postheight);
3742 #endif
3743          }
3744       FlipPage();
3745       CalcTics();
3746       mag  -= (magstep * tics);
3747       time -= tics;
3748       t    += (tics<<OSCTSHIFT);
3749       if (mag<0) mag = 0;
3750       }
3751 }
3752 
3753 
3754 //******************************************************************************
3755 //
3756 // DoZIntro
3757 //
3758 //******************************************************************************
3759 
3760 #define ZMAXMAG (199)
3761 #define ZOSCTIME (3*VBLCOUNTER)
3762 #define ZOSCXSHIFT (2)
3763 #define ZOSCXSTEP ( (FINEANGLES<<(ZOSCXSHIFT+16))/320 )
3764 #define ZOSCTSHIFT (2)
3765 
3766 void DoZIntro (void)
3767 {
3768    byte * shape;
3769    int mag;
3770    int currentmag;
3771    int magstep;
3772    int time;
3773    int x;
3774    int t;
3775 
3776    SetViewSize (MAXVIEWSIZES-1);
3777 
3778    shadingtable=colormap+(1<<12);
3779 
3780    shape=W_CacheLumpName("ap_wrld",PU_CACHE);
3781 
3782    mag=ZMAXMAG<<16;
3783    magstep = (ZMAXMAG<<16)/ZOSCTIME;
3784    time = ZOSCTIME;
3785    t=0;
3786 
3787    CalcTics();
3788 
3789 
3790    while (time>0)
3791       {
3792       int zoffset;
3793       int hoffset;
3794       int offset;
3795       int srcoffset;
3796       int bottomscreen;
3797       int src;
3798 //      int i;
3799 
3800 
3801       VL_ClearBuffer (bufferofs, 0);
3802       currentmag=mag>>16;
3803 
3804       srcoffset=0;
3805       for (x=0;x<320;)
3806          {
3807          VGAWRITEMAP(x&3);
3808 
3809          offset=(t+(FixedMul(x,ZOSCXSTEP)))&(FINEANGLES-1);
3810          zoffset=FixedMul(currentmag,sintable[offset]);
3811 //         hoffset=FixedMulShift(currentmag,sintable[offset],17);
3812          hoffset=0;
3813          dc_texturemid=((100+hoffset)<<SFRACBITS)+(SFRACUNIT>>1);
3814 
3815          dc_invscale=((200+zoffset)<<16)/200;
3816          dc_iscale=0xffffffffu/(unsigned)dc_invscale;
3817 
3818          srcoffset+=dc_invscale;
3819          sprtopoffset=centeryfrac -  FixedMul(dc_texturemid,dc_invscale);
3820          bottomscreen = sprtopoffset + (dc_invscale*200);
3821          dc_yl = (sprtopoffset+SFRACUNIT-1)>>SFRACBITS;
3822          dc_yh = ((bottomscreen-1)>>SFRACBITS);
3823          if (dc_yh >= viewheight)
3824             dc_yh = viewheight-1;
3825          if (dc_yl < 0)
3826             dc_yl = 0;
3827          if (dc_yl <= dc_yh)
3828             {
3829             src=srcoffset>>16;
3830             if (src>319)
3831                src=319;
3832             if (src<0)
3833                src=0;
3834             dc_source=shape+(src * 200);
3835 //            if (RandomNumber("hello",0)<128)
3836 #ifdef DOS
3837             R_DrawColumn ((byte *)bufferofs+(x>>2));
3838 #else
3839             R_DrawColumn ((byte *)bufferofs+x);
3840 #endif
3841             }
3842 //         srcoffset+=0x10000;
3843          x++;
3844          if ((LastScan) || IN_GetMouseButtons())
3845             return;
3846          }
3847       FlipPage();
3848       CalcTics();
3849       mag  -= (magstep * tics);
3850 //      mag  += FixedMulShift((magstep * tics),sintable[time&(FINEANGLES-1)],19);
3851       time -= tics;
3852       t    += (tics<<ZOSCTSHIFT);
3853       if (mag<0) mag = 0;
3854       }
3855 }
3856 #endif
3857 
3858 
3859 
3860 // Old Stuff
3861 
3862 /*
3863    int y1;
3864    int y2;
3865 
3866    if (post->alttile!=0)
3867       {
3868       ht=nominalheight;
3869       src2=W_CacheLumpNum(1+post->alttile,PU_CACHE);
3870 //      src2+=8;
3871       }
3872    else
3873       {
3874       ht=maxheight;
3875       src2=src;
3876       }
3877    hp_srcstep=(64<<(16+HEIGHTFRACTION))/post->wallheight;
3878    y1 = (((centery<<HFRACTION)-(post->wallheight*pheight)+(1<<(HFRACTION-1))));
3879    y2 = (((post->wallheight*ht)+y1)>>HFRACTION);
3880 
3881    if ((y1>>HFRACTION)>=viewheight)
3882       {
3883       post->ceilingclip=viewheight-1;
3884       post->floorclip=viewheight-1;
3885       return;
3886       }
3887    else if (y1<0)
3888       {
3889       hp_startfrac=FixedMulShift(-y1,hp_srcstep,HFRACTION);
3890       y1=0;
3891       post->ceilingclip=0;
3892       }
3893    else
3894       {
3895       hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,HFRACTION);
3896       y1>>=HFRACTION;
3897       post->ceilingclip=y1;
3898       }
3899    if (y2<0)
3900       {
3901       post->floorclip=0;
3902       post->ceilingclip=0;
3903       }
3904    else if (y2>viewheight)
3905       {
3906       DrawHeightPost(viewheight-y1, src2+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
3907       post->floorclip=viewheight-1;
3908       }
3909    else
3910       {
3911       DrawHeightPost(y2-y1, src2+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
3912       post->floorclip=y2-1;
3913       }
3914 
3915    if (ht==maxheight)
3916       return;
3917 
3918    y1 = (((centery<<HFRACTION)-(post->wallheight*(pheight-ht))+(1<<(HFRACTION-1))));
3919    y2 = (((post->wallheight<<6)+y1)>>HFRACTION);
3920 
3921    if ((y1>>HFRACTION)>=viewheight)
3922       return;
3923    else if (y1<0)
3924       {
3925       hp_startfrac=FixedMulShift(-y1,hp_srcstep,HFRACTION);
3926       y1=0;
3927       }
3928    else
3929       {
3930       hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,HFRACTION);
3931       y1>>=HFRACTION;
3932       }
3933    if (y2<0)
3934       return;
3935    else if (y2>viewheight)
3936       {
3937       DrawHeightPost(viewheight-y1, src+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
3938       post->floorclip=viewheight-1;
3939       }
3940    else
3941       {
3942       DrawHeightPost(y2-y1, src+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
3943       post->floorclip=y2-1;
3944       }
3945 }
3946 */
3947 
3948 
3949 
3950 
3951 
3952 
3953 //******************************************************************************
3954 //
3955 // DrawBackground
3956 //
3957 //******************************************************************************
3958 
DrawBackground(byte * bkgnd)3959 void DrawBackground ( byte * bkgnd )
3960 {
3961    int plane;
3962    int size;
3963 
3964    size=linewidth*200;
3965 
3966 #ifdef DOS
3967    for (plane=0;plane<4;plane++)
3968 #endif
3969       {
3970       VGAWRITEMAP(plane);
3971       memcpy((byte *)bufferofs,bkgnd,size);
3972       bkgnd+=size;
3973       }
3974 }
3975 
3976 
3977 //******************************************************************************
3978 //
3979 // PrepareBackground
3980 //
3981 //******************************************************************************
3982 
PrepareBackground(byte * bkgnd)3983 void PrepareBackground ( byte * bkgnd )
3984 {
3985    int plane;
3986    int size;
3987 
3988    size=linewidth*200;
3989 
3990 #ifdef DOS
3991    for (plane=0;plane<4;plane++)
3992 #endif
3993       {
3994       VGAREADMAP(plane);
3995       memcpy(bkgnd,(byte *)bufferofs,size);
3996       bkgnd+=size;
3997       }
3998 }
3999 
4000 //******************************************************************************
4001 //
4002 // WarpString
4003 //
4004 //******************************************************************************
4005 
WarpString(int x,int y,int endx,int endy,int time,byte * back,char * str)4006 void WarpString (
4007                   int x, int y, int endx, int endy,
4008                   int time, byte * back, char * str
4009                 )
4010 {
4011    int dx;
4012    int dy;
4013    int cx;
4014    int cy;
4015    int starttime;
4016 
4017 
4018    LastScan = 0;
4019 
4020 
4021    dx=((endx-x)<<16)/time;
4022    dy=((endy-y)<<16)/time;
4023    cx=x<<16;
4024    cy=y<<16;
4025    starttime=time;
4026 
4027    CalcTics();
4028 
4029    while (time>0)
4030       {
4031 
4032       DrawBackground ( back );
4033       US_ClippedPrint (cx>>16, cy>>16, str);
4034       FlipPage();
4035 
4036       CalcTics();
4037       cx+=dx*tics;
4038       cy+=dy*tics;
4039       time-=tics;
4040       if (LastScan != 0)
4041          break;
4042       }
4043 
4044   // DrawBackground ( back );
4045   // US_ClippedPrint (endx, endy, str);
4046   // FlipPage();
4047 
4048 }
4049 
4050 
4051 #if (SHAREWARE==1)
4052 //******************************************************************************
4053 //
4054 // DoEndCinematic
4055 //
4056 //******************************************************************************
4057 
4058 //******************************************************************************
4059 //
4060 // WarpSprite
4061 //
4062 //******************************************************************************
4063 
WarpSprite(int x,int y,int endx,int endy,int time,byte * back,int shape)4064 void WarpSprite (
4065                   int x, int y, int endx, int endy,
4066                   int time, byte * back, int shape
4067                 )
4068 {
4069    int dx;
4070    int dy;
4071    int cx;
4072    int cy;
4073    int starttime;
4074 
4075    LastScan = 0;
4076 
4077    dx=((endx-x)<<16)/time;
4078    dy=((endy-y)<<16)/time;
4079    cx=x<<16;
4080    cy=y<<16;
4081    starttime=time;
4082 
4083    CalcTics();
4084 
4085    while (time>0)
4086       {
4087       DrawBackground ( back );
4088       DrawUnScaledSprite (cx>>16, cy>>16, shape, 16);
4089       FlipPage();
4090       CalcTics();
4091       cx+=dx*tics;
4092       cy+=dy*tics;
4093       time-=tics;
4094       if (LastScan != 0)
4095          break;
4096       }
4097 }
4098 
4099 
4100 char *EndCinematicPicNames[5] =
4101          {
4102          "lwgshoo2",
4103          "hg2shoo2",
4104          "ankshoo1",
4105          "ligrise4",
4106          "tritoss5",
4107 
4108          };
4109 
4110 #define NUMENDMESSAGES 24
4111 
4112 
4113 char *EndCinematicText[NUMENDMESSAGES] =
4114   {
4115   "You've won the battle, Cassatt.\n"
4116   "But when the Oscuridos return,\n"
4117   "will you be ready as they wage\n"
4118   "their Dark War?",
4119 
4120   "Armed with only a pistol and 30\n"
4121   "bucks, you must stop the minions of\n"
4122   "El Oscuro before they kill millions\n"
4123   "of innocent people.",
4124 
4125   "But for now, hey, enjoy the medal\n"
4126   "you received and take a vacation.\n"
4127   "You've earned it. Maybe on \n"
4128   "San Nicolas Island . . ." ,
4129 
4130   "Thanks for playing. If you liked\n"
4131   "\"The HUNT Begins\", check Ordering\n"
4132   "Info for information about \n"
4133   "continuing your adventure.",
4134 
4135   "Okay, you can stop reading now.",
4136 
4137   "Press a key. That's all there is.\n"
4138   "Thanks.",
4139 
4140   "Are you lazy, or illiterate?\n"
4141   "PRESS A KEY.",
4142 
4143   "Look, this is pointless. You\n"
4144   "are done. Push off.",
4145 
4146   "Okay, show's over.  Nothing\n"
4147   "more to see here.",
4148 
4149   "Wow, you must like this fine\n"
4150   "background screen.",
4151 
4152   "For waiting this long, you get . . .\n"
4153   "nothing!  Go away!",
4154 
4155   "I mean, I like you as a friend,\n"
4156   "but . . .",
4157 
4158   "\"Bob\"",
4159 
4160   "All right, um . . . you found the\n"
4161   "secret message! Congratulations!",
4162 
4163   "Didn't work, huh?  Okay, how about\n"
4164   "this . . .",
4165 
4166   "THE END",
4167 
4168   "Dang. Thought I had you there.",
4169 
4170   "Stop watching.",
4171 
4172   "You know that if you registered,\n"
4173   "there would be a lot more cool\n"
4174   "stuff happening right now.",
4175 
4176   "Episode IV: A New Hope\n",
4177 
4178   "Just think of all the new secret\n"
4179   "messages you could find hidden\n"
4180   "in the registered version!",
4181 
4182   "Someone right now is probably\n"
4183   "enjoying the really exciting\n"
4184   "ending of the registered version.",
4185 
4186   "ROTT was filmed before\n"
4187   "a live audience.",
4188 
4189   "No animals were harmed during the\n"
4190   "creation of this video game, although\n"
4191   "one dog did get its butt spanked\n"
4192   "when it peed on the carpet.\n",
4193 
4194 
4195   };
4196 char NextGameString1[] = "The Developers of Incredible Power";
4197 char NextGameString2[] = "shall return";
4198 
DoEndCinematic(void)4199 void DoEndCinematic ( void )
4200 {
4201    int trilogo;
4202    int group;
4203    int world;
4204    int width;
4205    int height;
4206    int x,y;
4207    int shape;
4208    int time1,time2;
4209    byte * tmp;
4210    byte * sky;
4211    byte * bkgnd;
4212    int i;
4213 
4214    byte pal[768];
4215 
4216 
4217    viewwidth = MAXSCREENWIDTH;
4218    viewheight = MAXSCREENHEIGHT;
4219 
4220    MU_StartSong(song_youwin);
4221 
4222    bkgnd=SafeMalloc(800*linewidth);
4223 
4224    trilogo=W_GetNumForName("trilogo");
4225    world=W_GetNumForName("ap_wrld");
4226    group=W_GetNumForName("mmbk");
4227    VL_DrawPostPic (trilogo);
4228    PrepareBackground ( bkgnd );
4229 
4230    WarpSprite (160, -100, 160, 100, (VBLCOUNTER*3), bkgnd, W_GetNumForName("youwin"));
4231    if (LastScan !=0)
4232       goto fadelogo;
4233 
4234    I_Delay(30);
4235 fadelogo:
4236    MenuFadeOut();
4237    ClearGraphicsScreen();
4238    memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE,CvtNull,1),768);
4239    VL_NormalizePalette(&pal[0]);
4240    SwitchPalette(&pal[0],35);
4241 
4242    VL_DrawPostPic (world);
4243    PrepareBackground ( bkgnd );
4244 
4245    WarpSprite (160, 250, 160, 100, (VBLCOUNTER*3), bkgnd, W_GetNumForName("wrldsafe"));
4246    if (LastScan !=0)
4247       goto fadeworld;
4248 
4249    I_Delay(10);
4250    if (LastScan !=0)
4251       goto fadeworld;
4252 
4253    WarpSprite (160, 100, 160, -50, (VBLCOUNTER*3), bkgnd, W_GetNumForName("wrldsafe"));
4254    if (LastScan !=0)
4255       goto fadeworld;
4256 
4257    I_Delay(20);
4258 
4259 fadeworld:
4260    MenuFadeOut();
4261    ClearGraphicsScreen();
4262    MenuFadeIn();
4263 
4264 
4265    sky=W_CacheLumpNum(W_GetNumForName("SKYSTART")+2,PU_CACHE,CvtNull,1);
4266    tmp=sky;
4267    for (x=0;x<256;x++)
4268       {
4269       VGAWRITEMAP(x&3);
4270       for (y=0;y<200;y++)
4271          {
4272 #ifdef DOS
4273          *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
4274 #else
4275          *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
4276 #endif
4277          }
4278       }
4279    tmp=sky;
4280    for (x=256;x<320;x++)
4281       {
4282       VGAWRITEMAP(x&3);
4283       for (y=0;y<200;y++)
4284          {
4285 #ifdef DOS
4286          *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
4287 #else
4288          *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
4289 #endif
4290          }
4291       }
4292 
4293    for(i=0;i<5;i++)
4294       {
4295       int tx,ty;
4296 
4297       tx = 32 + (i << 6);
4298       ty = 100;
4299       shape = W_GetNumForName(EndCinematicPicNames[i]);
4300       DrawUnScaledSprite (tx, ty, shape,16);
4301       }
4302 
4303    PrepareBackground ( bkgnd );
4304 
4305    //CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_CACHE);
4306    CurrentFont = smallfont;
4307    LastScan = 0;
4308 
4309    for(i=0;i<NUMENDMESSAGES;i++)
4310       {
4311       if (i>3)
4312          I_Delay(50);
4313 
4314       US_MeasureStr (&width, &height, &(EndCinematicText[i][0]));
4315       if (LastScan !=0)
4316          break;
4317 
4318       x=(320-width)>>1;
4319       y=(200-height)>>1;
4320       time1 = (300 - y)*(VBLCOUNTER*4)/300;
4321       time2 = VBLCOUNTER*4-time1;
4322 
4323       WarpString (x, 250, x, y-50,time1, bkgnd, EndCinematicText[i]);
4324       if (LastScan !=0)
4325          break;
4326       I_Delay(40);
4327       if (LastScan !=0)
4328          break;
4329 
4330       if (i<=3)
4331          I_Delay(40);
4332       if (LastScan !=0)
4333          break;
4334 
4335       WarpString (x, y-50, x, -50, time2, bkgnd, EndCinematicText[i]);
4336       if (LastScan !=0)
4337          break;
4338 
4339 
4340       }
4341 
4342    if (LastScan!=0)
4343      goto finalfade;
4344 
4345    sky=W_CacheLumpNum(W_GetNumForName("SKYSTART")+2,PU_CACHE,CvtNull,1);
4346    tmp=sky;
4347    for (x=0;x<256;x++)
4348       {
4349       VGAWRITEMAP(x&3);
4350       for (y=0;y<200;y++)
4351          {
4352 #ifdef DOS
4353          *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
4354 #else
4355          *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
4356 #endif
4357          }
4358       }
4359    tmp=sky;
4360    for (x=256;x<320;x++)
4361       {
4362       VGAWRITEMAP(x&3);
4363       for (y=0;y<200;y++)
4364          {
4365 #ifdef DOS
4366          *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
4367 #else
4368          *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
4369 #endif
4370          }
4371       }
4372 
4373    for(i=0;i<5;i++)
4374       {
4375       int tx,ty;
4376 
4377       tx = 32 + (i << 6);
4378       ty = 100;
4379       shape = W_GetNumForName(EndCinematicPicNames[i]);
4380       DrawUnScaledSprite (tx, ty, shape,16);
4381       }
4382 
4383 
4384    shape = W_GetNumForName("robogrd3");
4385    PrepareBackground ( bkgnd );
4386    WarpSprite (420,100,300,100,VBLCOUNTER*3,bkgnd,shape);
4387    if (LastScan !=0)
4388       goto finalfade;
4389 
4390    PrepareBackground ( bkgnd );
4391    WarpString (200,80,200,80,VBLCOUNTER*3,bkgnd, "Am I late?");
4392    if (LastScan !=0)
4393       goto finalfade;
4394 
4395 
4396    I_Delay(20);
4397 finalfade:
4398 
4399    MenuFadeOut();
4400    VL_ClearVideo (0);
4401    I_Delay(10);
4402 
4403    if (LastScan == 0)
4404       {
4405       US_MeasureStr (&width, &height, NextGameString1);
4406       x=(320-width)>>1;
4407       y=(200-height)>>1;
4408       US_ClippedPrint (x,y-6, NextGameString1);
4409       US_MeasureStr (&width, &height, NextGameString2);
4410       x=(320-width)>>1;
4411       y=(200-height)>>1;
4412       US_ClippedPrint (x,y+6, NextGameString2);
4413       FlipPage();
4414       VL_FadeIn(0,255,origpal,150);
4415       I_Delay(50);
4416       VL_FadeOut(0,255,0,0,0,150);
4417       VL_ClearVideo (0);
4418       I_Delay(10);
4419       }
4420 
4421    SafeFree(bkgnd);
4422 }
4423 #else
4424 
4425 // REGISTERED VERSION ======================================================
4426 
4427 static char    burnCastle1Msg []=
4428         "The monastery burns.\n"
4429         "\n"
4430         "El Oscuro is dead.\n"
4431         "\n"
4432         "The world is safe.\n";
4433 
4434 // If all Snake Eggs not destroyed on final level:
4435 
4436 
4437 static char    notDoneMsg[] =
4438           "Unfortunately not all\n"
4439           "of El Oscuro's larvae\n"
4440           "were destroyed.\n"
4441           "\n"
4442           "Thirty years later,\n"
4443           "a descendant of\n"
4444           "El Oscuro wiped out\n"
4445           "the entire world,\n"
4446           "but nice job anyway.\n";
4447 
4448 static char    tryAgainMsg[] =
4449           "Try Again.\n"
4450           "\n"
4451           "The world will not be\n"
4452           "safe until all of El\n"
4453           "Oscuro's larvae are\n"
4454           "destroyed. Find them.\n";
4455 
4456 // If all snake eggs destroyed:
4457 static char    doneMsg[] =
4458           "You have destroyed\n"
4459           "El Oscuro and all his\n"
4460           "descendants.  Well done!\n";
4461 
4462 // On Triad background, in bigger font.
4463 static char    youWin1Msg[] =
4464         "So, HUNT Members, how\n"
4465         "do you think the\n"
4466         "mission went?\n";
4467 
4468 // Place menu pix of characters here (maybe modem frame too?)
4469 static char    youWin2Msg[] =
4470         "Barrett: Well, I think\n"
4471         "I got shin splints from\n"
4472         "all those jump pads.\n"
4473         "But hey, action-wise,\n"
4474         "I've been in tougher\n"
4475         "bar fights, for crying\n"
4476         "out loud.\n";
4477 
4478 static char    youWin3Msg[] =
4479         "Cassatt: Apart from\n"
4480         "the other HUNT members\n"
4481         "saying I look like\n"
4482         "Richard Mulligan, it\n"
4483         "was quite a success.\n"
4484         "And some of the\n"
4485         "monastery's ironwork\n"
4486         "was very nice.\n";
4487 
4488 static char    youWin4Msg[] =
4489         "Ni: it was quite easy,\n"
4490         "actually.  I just\n"
4491         "pictured the enemy\n"
4492         "having the face of\n"
4493         "my ex-husband, and\n"
4494         "man, I was a force\n"
4495         "of Nature.\n";
4496 
4497 static char    youWin5Msg[] =
4498         "Wendt: I was kind of\n"
4499         "disappointed. I think\n"
4500         "I used the missile\n"
4501         "weapons way too much.\n"
4502         "Next time, bullets\n"
4503         "only.  Nothing sweeter\n"
4504         "than a head shot from\n"
4505         "a hundred feet.\n";
4506 
4507 static char    youWin6Msg[] =
4508         "Freeley: I'm still\n"
4509         "trying to adjust in\n"
4510         "the aftermath.  It's\n"
4511         "kinda tough.  I mean,\n"
4512         "I save the damn world,\n"
4513         "and all people ask\n"
4514         "about is my name.\n"
4515         "Sheesh.\n";
4516 
4517 // On caching screen
4518 
4519 static char     youWin7Msg[] =
4520            "The HUNT is victorious!\n"
4521            "\n"
4522            "         THE END\n";
4523 
4524 
4525 static char     youWin8Msg[] =
4526            "Now go and celebrate!\n"
4527            "\n"
4528            "      THE REAL END";
4529 
4530 #define NUMEXPLOSIONTYPES 4
4531 
4532 typedef struct {
4533   char  name[11];
4534   byte  numframes;
4535 } ExplosionInfoType;
4536 
4537 ExplosionInfoType ExplosionInfo[NUMEXPLOSIONTYPES]=
4538 {
4539   {"EXPLOS1\0",20},
4540   {"EXP1\0",20},
4541   {"GREXP1\0",25},
4542   {"PART1\0",12},
4543 #if 0
4544   {"GUTS1\0",12},
4545   {"ORGAN1\0",12},
4546   {"RIB1\0",12},
4547   {"GPINK1\0",12},
4548   {"GHEAD1\0",12},
4549   {"GARM1\0",12},
4550   {"GLEG1\0",12},
4551   {"GHUM1\0",12},
4552   {"GHIP1\0",12},
4553   {"GLIMB1\0",12},
4554 #endif
4555 };
4556 
4557 
4558 typedef struct {
4559   byte  which;
4560   byte  frame;
4561   byte  x;
4562   byte  y;
4563 } ExplosionType;
4564 
4565 #define MAXTRANSMITTEREXPLOSIONS 30
4566 
4567 static ExplosionType Explosions[MAXTRANSMITTEREXPLOSIONS];
4568 
ResetTransmitterExplosion(ExplosionType * Explosion)4569 void ResetTransmitterExplosion ( ExplosionType * Explosion )
4570 {
4571    Explosion->which=RandomNumber("Explosion",0)%NUMEXPLOSIONTYPES;
4572    Explosion->frame=0;
4573    Explosion->x=(RandomNumber("Explosion",2)>>1)+(160-64);
4574    Explosion->y=(RandomNumber("Explosion",3)>>1);
4575 }
4576 
CacheTransmitterExplosions(void)4577 void CacheTransmitterExplosions ( void )
4578 {
4579    int i,j,num;
4580 
4581    for (i=0;i<NUMEXPLOSIONTYPES;i++)
4582       {
4583       num=W_GetNumForName(ExplosionInfo[i].name);
4584       for (j=0;j<ExplosionInfo[i].numframes;j++)
4585          {
4586          W_CacheLumpNum(num+j, PU_CACHE, Cvt_patch_t, 1);
4587          }
4588       }
4589 }
4590 
SetupTransmitterExplosions(void)4591 void SetupTransmitterExplosions ( void )
4592 {
4593    int i;
4594 
4595    for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
4596       {
4597       ResetTransmitterExplosion(&Explosions[i]);
4598       }
4599 }
UpdateTransmitterExplosions(void)4600 void UpdateTransmitterExplosions ( void )
4601 {
4602    int i;
4603    for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
4604       {
4605       Explosions[i].frame+=tics;
4606       if (Explosions[i].frame>=(ExplosionInfo[Explosions[i].which].numframes<<1))
4607          {
4608          ResetTransmitterExplosion(&Explosions[i]);
4609          SD_Play(SD_EXPLODEFLOORSND+(RandomNumber("Explosion",4)>>7));
4610          }
4611       }
4612 }
4613 
DrawTransmitterExplosions(void)4614 void DrawTransmitterExplosions ( void )
4615 {
4616    int i;
4617    for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
4618       {
4619       DrawUnScaledSprite (
4620                       Explosions[i].x,
4621                       Explosions[i].y,
4622                       (W_GetNumForName(ExplosionInfo[Explosions[i].which].name) +
4623                       (Explosions[i].frame>>1)),
4624                       16
4625                       );
4626       }
4627 }
4628 
DoTransmitterExplosion(void)4629 void DoTransmitterExplosion ( void )
4630 {
4631    byte * back;
4632    int i;
4633 
4634    VL_ClearVideo(0);
4635    back=SafeMalloc(800*linewidth);
4636 
4637    CalcTics();
4638    CalcTics();
4639    DrawNormalSprite(0,0,W_GetNumForName("transmit"));
4640    PrepareBackground ( back );
4641    SetupTransmitterExplosions ();
4642    CacheTransmitterExplosions ();
4643    DrawBackground ( back );
4644    FlipPage();
4645    VL_FadeIn (0, 255, origpal, 30);
4646    SHAKETICS=VBLCOUNTER*15;
4647    for (i=0;i<(VBLCOUNTER*15);i+=tics)
4648       {
4649       DrawBackground ( back );
4650       DrawTransmitterExplosions ();
4651       FlipPage();
4652       CalcTics();
4653       UpdateTransmitterExplosions ();
4654       }
4655    VL_FadeOut (0, 255, 63, 63, 63, 150);
4656    screenfaded=false;
4657    SD_Play(SD_PLAYERTCSND);
4658    SD_Play(SD_PLAYERTBSND);
4659    SD_Play(SD_PLAYERDWSND);
4660    SD_Play(SD_PLAYERLNSND);
4661    SD_Play(SD_PLAYERIPFSND);
4662    VL_FadeOut (0, 255, 0, 0, 0, 30);
4663    TurnShakeOff();
4664 
4665    SafeFree(back);
4666 }
4667 
ShowTransmitter(void)4668 void ShowTransmitter ( void )
4669 {
4670    MenuFadeOut();
4671    DrawNormalSprite(0,0,W_GetNumForName("transmit"));
4672    FlipPage();
4673    VL_FadeIn (0, 255, origpal, 30);
4674    I_Delay(30);
4675    VL_FadeOut (0, 255, 0, 0, 0, 30);
4676 }
4677 
ShowFinalDoor(void)4678 void ShowFinalDoor ( void )
4679 {
4680    byte pal[768];
4681 
4682    MenuFadeOut();
4683 
4684    VL_ClearBuffer (bufferofs, 0);
4685    DrawNormalSprite (0, (200-120)>>1, W_GetNumForName("finldoor"));
4686    FlipPage();
4687    memcpy(&pal[0],W_CacheLumpName("findrpal",PU_CACHE,CvtNull, 1),768);
4688    VL_NormalizePalette(&pal[0]);
4689    SD_Play(SD_OPENDOORSND);
4690    VL_FadeIn (0, 255, pal, 30);
4691    I_Delay(30);
4692    VL_FadeOut (0, 255, 0, 0, 0, 30);
4693 }
4694 
ShowFinalFire(void)4695 void ShowFinalFire ( void )
4696 {
4697    byte pal[768];
4698 
4699    MenuFadeOut();
4700 
4701    VL_ClearBuffer (bufferofs, 0);
4702    DrawNormalSprite (0, (200-120)>>1, W_GetNumForName("finlfire"));
4703    FlipPage();
4704    memcpy(&pal[0],W_CacheLumpName("finfrpal",PU_CACHE,CvtNull, 1),768);
4705    VL_NormalizePalette(&pal[0]);
4706    SD_Play(SD_BAZOOKAFIRESND);
4707    VL_FadeIn (0, 255, pal, 30);
4708    SD_Play(SD_FIREBOMBFIRESND);
4709    I_Delay(2);
4710    SD_Play(SD_HEATSEEKFIRESND);
4711    I_Delay(2);
4712    SD_Play(SD_DRUNKFIRESND);
4713    SD_Play(SD_HEATSEEKFIRESND);
4714    I_Delay(2);
4715    SD_Play(SD_ATKMP40SND);
4716    SD_Play(SD_ATKMP40SND);
4717    I_Delay(2);
4718    SD_Play(SD_HEATSEEKFIRESND);
4719    SD_Play(SD_FIREBOMBFIRESND);
4720    I_Delay(2);
4721    SD_Play(SD_ATKMP40SND);
4722    SD_Play(SD_HEATSEEKFIRESND);
4723    I_Delay(2);
4724    SD_Play(SD_DRUNKFIRESND);
4725    I_Delay(2);
4726    SD_Play(SD_FIREBOMBFIRESND);
4727    I_Delay(2);
4728    SD_Play(SD_HEATSEEKFIRESND);
4729    SD_Play(SD_ATKMP40SND);
4730    I_Delay(2);
4731    SD_Play(SD_DRUNKFIRESND);
4732    SD_Play(SD_HEATSEEKFIRESND);
4733    I_Delay(2);
4734    SD_Play(SD_FIREBOMBFIRESND);
4735    SD_Play(SD_ATKMP40SND);
4736    I_Delay(2);
4737    SD_Play(SD_DRUNKFIRESND);
4738    I_Delay(2);
4739    SD_Play(SD_HEATSEEKFIRESND);
4740    SD_Play(SD_FIREBOMBFIRESND);
4741    I_Delay(2);
4742    SD_Play(SD_ATKMP40SND);
4743    SD_Play(SD_HEATSEEKFIRESND);
4744    I_Delay(2);
4745    SD_Play(SD_DRUNKFIRESND);
4746    SD_Play(SD_FIREBOMBFIRESND);
4747    I_Delay(2);
4748    SD_Play(SD_HEATSEEKFIRESND);
4749    SD_Play(SD_DRUNKFIRESND);
4750    SD_Play(SD_BAZOOKAFIRESND);
4751    I_Delay(4);
4752    VL_FadeOut (0, 255, 0, 0, 0, 30);
4753 }
4754 
ScrollString(int cy,char * string,byte * bkgnd,int scrolltime,int pausetime)4755 void ScrollString ( int cy, char * string, byte * bkgnd, int scrolltime, int pausetime )
4756 {
4757    int x,y;
4758    int width,height;
4759    int time1,time2;
4760 
4761    LastScan=0;
4762    US_MeasureStr (&width, &height, string);
4763 
4764    x=(320-width)>>1;
4765    y=cy-(height>>1);
4766    time1 = ((220 - y)*scrolltime)/(220+height);
4767    time2 = scrolltime-time1;
4768 
4769    WarpString (x, 210, x, y, time1, bkgnd, string);
4770 
4771    if (LastScan !=0)
4772       return;
4773 
4774    I_Delay(pausetime);
4775 
4776    if (LastScan !=0)
4777       return;
4778 
4779    WarpString (x, y, x, -10-height, time2, bkgnd, string);
4780 }
4781 
DoBurningCastle(void)4782 void DoBurningCastle ( void )
4783 {
4784    byte * back;
4785 
4786    LastScan=0;
4787    VL_ClearVideo(0);
4788    back=SafeMalloc(800*linewidth);
4789 
4790    DrawNormalSprite(0,0,W_GetNumForName("finale"));
4791    PrepareBackground ( back );
4792    CurrentFont = smallfont;
4793    FlipPage();
4794    VL_FadeIn (0, 255, origpal, 30);
4795    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1 );
4796    ScrollString ( 150, &burnCastle1Msg[0], back, 4*VBLCOUNTER, 80);
4797    W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
4798    VL_FadeOut (0, 255, 0, 0, 0, 80);
4799    SafeFree(back);
4800 }
4801 
DoFailedScreen(void)4802 void DoFailedScreen ( void )
4803 {
4804    byte * back;
4805 
4806    back=SafeMalloc(800*linewidth);
4807 
4808    VL_DrawPostPic (W_GetNumForName("trilogo"));
4809    PrepareBackground ( back );
4810    CurrentFont = smallfont;
4811    FlipPage();
4812    VL_FadeIn (0, 255, origpal, 30);
4813    ScrollString ( 100, &notDoneMsg[0], back, 4*VBLCOUNTER, 100);
4814    VL_FadeOut (0, 255, 0, 0, 0, 80);
4815    SafeFree(back);
4816 }
4817 
DoTryAgainScreen(void)4818 void DoTryAgainScreen ( void )
4819 {
4820    byte * back;
4821 
4822    back=SafeMalloc(800*linewidth);
4823 
4824    VL_DrawPostPic (W_GetNumForName("trilogo"));
4825    PrepareBackground ( back );
4826    CurrentFont = smallfont;
4827    FlipPage();
4828    VL_FadeIn (0, 255, origpal, 30);
4829    ScrollString ( 100, tryAgainMsg, back, 4*VBLCOUNTER, 80);
4830    VL_FadeOut (0, 255, 0, 0, 0, 80);
4831    SafeFree(back);
4832 }
4833 
ResetWorldExplosion(ExplosionType * Explosion)4834 void ResetWorldExplosion ( ExplosionType * Explosion )
4835 {
4836    Explosion->which=RandomNumber("Explosion",0)%NUMEXPLOSIONTYPES;
4837    Explosion->frame=0;
4838 //   RandomNumber("Explosion",1)%ExplosionInfo[Explosions[i].which].numframes;
4839    Explosion->x=(RandomNumber("Explosion",2))+64;
4840    Explosion->y=(RandomNumber("Explosion",3)%180);
4841 }
4842 
SetupWorldExplosions(void)4843 void SetupWorldExplosions ( void )
4844 {
4845    int i;
4846 
4847    for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
4848       {
4849       ResetWorldExplosion(&Explosions[i]);
4850       }
4851 }
UpdateWorldExplosions(void)4852 void UpdateWorldExplosions ( void )
4853 {
4854    int i;
4855    for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
4856       {
4857       Explosions[i].frame+=tics;
4858       if (Explosions[i].frame>=(ExplosionInfo[Explosions[i].which].numframes<<1))
4859          {
4860          ResetWorldExplosion(&Explosions[i]);
4861          SD_Play(SD_EXPLODEFLOORSND+(RandomNumber("Explosion",4)>>7));
4862          }
4863       }
4864 }
4865 
DestroyEarth(void)4866 void DestroyEarth ( void )
4867 {
4868    byte * back;
4869    int i;
4870 
4871    VL_ClearVideo(0);
4872    back=SafeMalloc(800*linewidth);
4873 
4874    CalcTics();
4875    CalcTics();
4876    DrawNormalSprite(0,0,W_GetNumForName("ourearth"));
4877    PrepareBackground ( back );
4878    SetupWorldExplosions ();
4879    CacheTransmitterExplosions ();
4880    DrawBackground ( back );
4881    FlipPage();
4882    VL_FadeIn (0, 255, origpal, 30);
4883    SHAKETICS=VBLCOUNTER*10;
4884    for (i=0;i<(VBLCOUNTER*10);i+=tics)
4885       {
4886       DrawBackground ( back );
4887       DrawTransmitterExplosions ();
4888       FlipPage();
4889       CalcTics();
4890       UpdateWorldExplosions ();
4891       }
4892    VL_FadeOut (0, 255, 63, 63, 63, 150);
4893    screenfaded=false;
4894    if (gamestate.violence==vl_excessive)
4895       SD_Play(SD_YOUSUCKSND);
4896    VL_FadeOut (0, 255, 0, 0, 0, 50);
4897    TurnShakeOff();
4898 
4899    SafeFree(back);
4900 }
4901 
DestroyedAllEggs(void)4902 boolean DestroyedAllEggs ( void )
4903 {
4904    statobj_t * temp;
4905 
4906    for(temp=FIRSTSTAT;temp;temp=temp->statnext)
4907       {
4908       if (temp->itemnumber==stat_tomlarva)
4909          return false;
4910       }
4911    return true;
4912 }
4913 
DoSanNicolas(void)4914 void DoSanNicolas ( void )
4915 {
4916    byte pal[768];
4917 
4918    LastScan=0;
4919    VL_ClearVideo(0);
4920    DrawNormalSprite(0,16,W_GetNumForName("nicolas"));
4921    DrawNormalSprite(10,200-58,W_GetNumForName("budgcut"));
4922    FlipPage();
4923    memcpy(&pal[0],W_CacheLumpName("nicpal",PU_CACHE, CvtNull, 1),768);
4924    VL_NormalizePalette(&pal[0]);
4925    VL_FadeIn (0, 255, pal, 30);
4926    I_Delay(60);
4927    VL_FadeOut (0, 255, 0, 0, 0, 80);
4928 }
4929 
PlayerQuestionScreen(void)4930 void PlayerQuestionScreen ( void )
4931 {
4932    byte * back;
4933 
4934    back=SafeMalloc(800*linewidth);
4935 
4936    VL_DrawPostPic (W_GetNumForName("trilogo"));
4937    PrepareBackground ( back );
4938    CurrentFont = smallfont;
4939    FlipPage();
4940    VL_FadeIn (0, 255, origpal, 30);
4941    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
4942    ScrollString ( 100, &doneMsg[0], back, 4*VBLCOUNTER, 40);
4943    ScrollString ( 100, &youWin1Msg[0], back, 4*VBLCOUNTER, 50);
4944    VL_DrawPostPic (W_GetNumForName("trilogo"));
4945    DrawXYPic ( 8, 100-24, W_GetNumForName("player2"));
4946    PrepareBackground ( back );
4947    CurrentFont = smallfont;
4948    SD_Play(SD_PLAYERTBSND);
4949    ScrollString ( 100, &youWin2Msg[0], back, 4*VBLCOUNTER, 100);
4950    VL_DrawPostPic (W_GetNumForName("trilogo"));
4951    DrawXYPic ( 8, 100-24, W_GetNumForName("player1"));
4952    PrepareBackground ( back );
4953    SD_Play(SD_PLAYERTCSND);
4954    ScrollString ( 100, &youWin3Msg[0], back, 4*VBLCOUNTER, 100);
4955    VL_DrawPostPic (W_GetNumForName("trilogo"));
4956    DrawXYPic ( 8, 100-24, W_GetNumForName("player4"));
4957    PrepareBackground ( back );
4958    SD_Play(SD_PLAYERLNSND);
4959    ScrollString ( 100, &youWin4Msg[0], back, 4*VBLCOUNTER, 100);
4960    VL_DrawPostPic (W_GetNumForName("trilogo"));
4961    DrawXYPic ( 8, 100-24, W_GetNumForName("player3"));
4962    PrepareBackground ( back );
4963    SD_Play(SD_PLAYERDWSND);
4964    ScrollString ( 100, &youWin5Msg[0], back, 4*VBLCOUNTER, 100);
4965    VL_DrawPostPic (W_GetNumForName("trilogo"));
4966    DrawXYPic ( 8, 100-24, W_GetNumForName("player5"));
4967    PrepareBackground ( back );
4968    SD_Play(SD_PLAYERIPFSND);
4969    ScrollString ( 100, &youWin6Msg[0], back, 4*VBLCOUNTER, 100);
4970    W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
4971    VL_FadeOut (0, 255, 0, 0, 0, 80);
4972    SafeFree(back);
4973 }
4974 
DoYouWin(void)4975 void DoYouWin ( void )
4976 {
4977    pic_t * pic;
4978    byte * back;
4979 
4980    back=SafeMalloc(800*linewidth);
4981    LastScan=0;
4982    VL_ClearVideo(0);
4983    pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
4984    VWB_DrawPic (0, 0, pic);
4985    PrepareBackground ( back );
4986    FlipPage();
4987    VL_FadeIn (0, 255, origpal, 30);
4988    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
4989    ScrollString ( 100, &youWin7Msg[0], back, 4*VBLCOUNTER, 300);
4990    W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
4991    VL_FadeOut (0, 255, 0, 0, 0, 80);
4992    SafeFree(back);
4993 }
4994 
DoFinalEnd(void)4995 void DoFinalEnd ( void )
4996 {
4997    pic_t * pic;
4998    byte * back;
4999 
5000    back=SafeMalloc(800*linewidth);
5001    LastScan=0;
5002    VL_ClearVideo(0);
5003    pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
5004    VWB_DrawPic (0, 0, pic);
5005    DrawNormalSprite(0,0,W_GetNumForName("sombrero"));
5006    DrawNormalSprite(0,0,W_GetNumForName("amflag"));
5007    DrawNormalSprite(0,0,W_GetNumForName("witchhat"));
5008    DrawNormalSprite(0,0,W_GetNumForName("esterhat"));
5009    DrawNormalSprite(0,0,W_GetNumForName("santahat"));
5010    PrepareBackground ( back );
5011    FlipPage();
5012    VL_FadeIn (0, 255, origpal, 30);
5013    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
5014    ScrollString ( 100, &youWin8Msg[0], back, 4*VBLCOUNTER, 100);
5015    W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
5016    VL_FadeOut (0, 255, 0, 0, 0, 80);
5017    SafeFree(back);
5018    VL_ClearVideo(0);
5019 }
5020 
5021 static char     dipMsg[] =
5022            "The Developers of Incredible Power!\n"
5023            "\n"
5024            "Susan  Tom  Jim  Stephen\n"
5025            "Mark  William  Chuck\n";
5026 
5027 static char     creditsMsg[] =
5028            "Rise of the Triad Credits\n";
5029 
5030 static char     credits1Msg[] =
5031            "Programmers\n"
5032            "\n"
5033            "Mark Dochtermann\n"
5034            "William Scarboro\n"
5035            "Jim Dose'\n"
5036            "Nolan Martin\n";
5037 
5038 static char     credits2Msg[] =
5039            "Creative Director\n"
5040            "\n"
5041            "Tom Hall\n";
5042 
5043 static char     credits3Msg[] =
5044            "Artists\n"
5045            "\n"
5046            "Stephen Hornback\n"
5047            "Tim Neveu\n"
5048            "Chuck Jones\n"
5049            "Susan Singer\n"
5050            "James Storey\n"
5051            "Cygnus Multimedia\n";
5052 
5053 static char     credits4Msg[] =
5054            "Level Designers\n"
5055            "\n"
5056            "Tom Hall\n"
5057            "Joseph Selinske\n"
5058            "Marianna Vayntrub\n"
5059            "Joe Siegler\n";
5060 static char     credits5Msg[] =
5061            "Music\n"
5062            "\n"
5063            "Lee Jackson\n"
5064            "Bobby Prince\n";
5065 
5066 static char     credits6Msg[] =
5067            "Robot Models\n"
5068            "\n"
5069            "Gregor Punchatz\n";
5070 
5071 static char     credits7Msg[] =
5072            "Special Thanks\n"
5073            "\n"
5074            "George Broussard\n"
5075            "Scott Miller\n"
5076            "Steven Blackburn\n"
5077            "Apogee Technical Support\n"
5078            "Apogee Support Staff\n"
5079            "John Carmack\n"
5080            "Ken Silverman\n";
5081 
5082 static char     credits8Msg[] =
5083            "The Hand of God\n"
5084            "\n"
5085            "Tim Neveu's Hand\n";
5086 
5087 static char     credits9Msg[] =
5088            "Dog Snout and Paw\n"
5089            "\n"
5090            "Loki\n"
5091            "The Carpet Wetting Maestro\n";
5092 
5093 static char     credits10Msg[] =
5094            "Krist's chair\n"
5095            "\n"
5096            "Stephen Blackburn's Comfy Chair\n"
5097            "Marianna's Paper and Glue\n";
5098 
5099 static char     credits11Msg[] =
5100            "Character Voices\n"
5101            "\n"
5102            "Darian - Mark Dochtermann\n"
5103            "Krist - Joe Siegler\n"
5104            "NME - Sound CD#4005\n"
5105            "Oscuro - Tom Hall\n"
5106            "Low Guard - Steve Quarrella\n"
5107            "High Guard - Steven Blackburn\n"
5108            "Over Patrol - Chuck Jones\n";
5109 
5110 static char     credits12Msg[] =
5111            "Character Voices Continued\n"
5112            "\n"
5113            "Strike Team - Scott Miller\n"
5114            "Lightning Guard - William Scarboro\n"
5115            "Triad Enforcer - George Broussard\n"
5116            "All Monks - Tom Hall\n"
5117            "Taradino - Joe Selinske\n"
5118            "Lorelei - Pau Suet Ying\n"
5119            "Ian Paul - Jim Dose'\n"
5120            "Doug - Lee Jackson\n"
5121            "Thi - Susan Singer\n";
5122 
5123 static char     actorsMsg[] =
5124            "The Actors\n";
5125 
5126 static char     actors1Msg[] =
5127            "Low Guard\n"
5128            "\n"
5129            "Steve Quarrella\n";
5130 
5131 static char     actors2Msg[] =
5132            "High Guard\n"
5133            "\n"
5134            "Steven Blackburn\n";
5135 
5136 static char     actors3Msg[] =
5137            "Over Patrol\n"
5138            "\n"
5139            "Nolan Martin\n";
5140 
5141 static char     actors4Msg[] =
5142            "Strike Team\n"
5143            "\n"
5144            "Scott Miller\n";
5145 
5146 static char     actors5Msg[] =
5147            "Lightning Guard\n"
5148            "\n"
5149            "Kevin Green\n";
5150 
5151 static char     actors6Msg[] =
5152            "Triad Enforcer\n"
5153            "\n"
5154            "George Broussard\n";
5155 
5156 static char     actors7Msg[] =
5157            "Death Monk\n"
5158            "\n"
5159            "Lee Jackson\n";
5160 
5161 static char     actors8Msg[] =
5162            "Deathfire Monk\n"
5163            "\n"
5164            "Allen Blum III\n";
5165 
5166 static char     actors9Msg[] =
5167            "Robot Guard\n"
5168            "\n"
5169            "Himself\n";
5170 
5171 static char     actors10Msg[] =
5172            "General Darian\n"
5173            "\n"
5174            "Steve Maines\n";
5175 
5176 static char     actors11Msg[] =
5177            "Sebastian Krist\n"
5178            "\n"
5179            "Joe Siegler\n";
5180 
5181 static char     actors12Msg[] =
5182            "The NME\n"
5183            "\n"
5184            "Himself\n";
5185 
5186 static char     actors13Msg[] =
5187            "El Oscuro\n"
5188            "\n"
5189            "Tom Hall\n";
5190 
5191 
5192 static char     cut1Msg[] =
5193            "Deathfire Monk\n"
5194            "\n"
5195            "Mark Dochtermann\n";
5196 
5197 
5198 static char     cut2Msg[] =
5199            "Over Patrol\n"
5200            "\n"
5201            "Pat Miller\n";
5202 
5203 
5204 static char     cut3Msg[] =
5205            "Low Guard\n"
5206            "\n"
5207            "Marianna Vayntrub\n";
5208 
5209 
5210 static char     cut4Msg[] =
5211            "Strike Team\n"
5212            "\n"
5213            "Ann Grauerholz\n";
5214 
5215 static char     cut5Msg[] =
5216            "Lightning Guard\n"
5217            "\n"
5218            "William Scarboro\n";
5219 
5220 
5221 static char     cut6Msg[] =
5222            "High Guard\n"
5223            "\n"
5224            "Stephen Hornback\n";
5225 
5226 
5227 
5228 static char     playersCutMsg[] =
5229            "Actors who were\n"
5230            "cut from the game\n";
5231 
DIPCredits(void)5232 void DIPCredits ( void )
5233 {
5234    byte * back;
5235 
5236    back=SafeMalloc(800*linewidth);
5237 
5238    VL_DrawPostPic (W_GetNumForName("trilogo"));
5239    PrepareBackground ( back );
5240    FlipPage();
5241    VL_FadeIn (0, 255, origpal, 30);
5242    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
5243    ScrollString ( 100, &creditsMsg[0], back, 4*VBLCOUNTER, 30);
5244    CurrentFont = smallfont;
5245    ScrollString ( 100, &credits1Msg[0], back, 4*VBLCOUNTER, 50);
5246    ScrollString ( 100, &credits2Msg[0], back, 4*VBLCOUNTER, 50);
5247    ScrollString ( 100, &credits3Msg[0], back, 4*VBLCOUNTER, 50);
5248    ScrollString ( 100, &credits4Msg[0], back, 4*VBLCOUNTER, 50);
5249    ScrollString ( 100, &credits5Msg[0], back, 4*VBLCOUNTER, 50);
5250    ScrollString ( 100, &credits6Msg[0], back, 4*VBLCOUNTER, 50);
5251    ScrollString ( 100, &credits7Msg[0], back, 4*VBLCOUNTER, 50);
5252    ScrollString ( 100, &credits8Msg[0], back, 4*VBLCOUNTER, 50);
5253    ScrollString ( 100, &credits9Msg[0], back, 4*VBLCOUNTER, 50);
5254    ScrollString ( 100, &credits10Msg[0], back, 4*VBLCOUNTER, 50);
5255    ScrollString ( 100, &credits11Msg[0], back, 4*VBLCOUNTER, 80);
5256    ScrollString ( 100, &credits12Msg[0], back, 4*VBLCOUNTER, 80);
5257 
5258    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
5259    ScrollString ( 100, &actorsMsg[0], back, 4*VBLCOUNTER, 50);
5260 
5261    CurrentFont = smallfont;
5262    VL_DrawPostPic (W_GetNumForName("trilogo"));
5263    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("lwgshoo2"));
5264    PrepareBackground ( back );
5265    ScrollString ( 100, &actors1Msg[0], back, 4*VBLCOUNTER, 50);
5266 
5267    VL_DrawPostPic (W_GetNumForName("trilogo"));
5268    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("hg2shoo2"));
5269    PrepareBackground ( back );
5270    ScrollString ( 100, &actors2Msg[0], back, 4*VBLCOUNTER, 50);
5271 
5272    VL_DrawPostPic (W_GetNumForName("trilogo"));
5273    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("obpshoo1"));
5274    PrepareBackground ( back );
5275    ScrollString ( 100, &actors3Msg[0], back, 4*VBLCOUNTER, 50);
5276 
5277    VL_DrawPostPic (W_GetNumForName("trilogo"));
5278    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("ankshoo1"));
5279    PrepareBackground ( back );
5280    ScrollString ( 100, &actors4Msg[0], back, 4*VBLCOUNTER, 50);
5281 
5282    VL_DrawPostPic (W_GetNumForName("trilogo"));
5283    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("ligrise4"));
5284    PrepareBackground ( back );
5285    ScrollString ( 100, &actors5Msg[0], back, 4*VBLCOUNTER, 50);
5286 
5287    VL_DrawPostPic (W_GetNumForName("trilogo"));
5288    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("tritoss5"));
5289    PrepareBackground ( back );
5290    ScrollString ( 100, &actors6Msg[0], back, 4*VBLCOUNTER, 50);
5291 
5292    VL_DrawPostPic (W_GetNumForName("trilogo"));
5293    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("monkdr4"));
5294    PrepareBackground ( back );
5295    ScrollString ( 100, &actors7Msg[0], back, 4*VBLCOUNTER, 50);
5296 
5297    VL_DrawPostPic (W_GetNumForName("trilogo"));
5298    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("allksh4"));
5299    PrepareBackground ( back );
5300    ScrollString ( 100, &actors8Msg[0], back, 4*VBLCOUNTER, 50);
5301 
5302    VL_DrawPostPic (W_GetNumForName("trilogo"));
5303    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("robogrd1"));
5304    PrepareBackground ( back );
5305    ScrollString ( 100, &actors9Msg[0], back, 4*VBLCOUNTER, 50);
5306 
5307    VL_DrawPostPic (W_GetNumForName("trilogo"));
5308    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("darshoo1"));
5309    PrepareBackground ( back );
5310    ScrollString ( 100, &actors10Msg[0], back, 4*VBLCOUNTER, 50);
5311 
5312    VL_DrawPostPic (W_GetNumForName("trilogo"));
5313    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("hdope8"));
5314    PrepareBackground ( back );
5315    ScrollString ( 100, &actors11Msg[0], back, 4*VBLCOUNTER, 50);
5316 
5317    VL_DrawPostPic (W_GetNumForName("trilogo"));
5318    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rbody101"));
5319    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rhead101"));
5320    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rsw01"));
5321    PrepareBackground ( back );
5322    ScrollString ( 100, &actors12Msg[0], back, 4*VBLCOUNTER, 50);
5323 
5324    VL_DrawPostPic (W_GetNumForName("trilogo"));
5325    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("tomfly21"));
5326    PrepareBackground ( back );
5327    ScrollString ( 100, &actors13Msg[0], back, 4*VBLCOUNTER, 50);
5328 
5329    VL_DrawPostPic (W_GetNumForName("trilogo"));
5330    PrepareBackground ( back );
5331    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
5332    ScrollString ( 100, &playersCutMsg[0], back, 4*VBLCOUNTER, 40);
5333 
5334    CurrentFont = smallfont;
5335    VL_DrawPostPic (W_GetNumForName("trilogo"));
5336    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutmark"));
5337    PrepareBackground ( back );
5338    ScrollString ( 100, &cut1Msg[0], back, 4*VBLCOUNTER, 50);
5339 
5340    VL_DrawPostPic (W_GetNumForName("trilogo"));
5341    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutpat"));
5342    PrepareBackground ( back );
5343    ScrollString ( 100, &cut2Msg[0], back, 4*VBLCOUNTER, 50);
5344 
5345    VL_DrawPostPic (W_GetNumForName("trilogo"));
5346    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutmari"));
5347    PrepareBackground ( back );
5348    ScrollString ( 100, &cut3Msg[0], back, 4*VBLCOUNTER, 50);
5349 
5350    VL_DrawPostPic (W_GetNumForName("trilogo"));
5351    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutann"));
5352    PrepareBackground ( back );
5353    ScrollString ( 100, &cut4Msg[0], back, 4*VBLCOUNTER, 50);
5354 
5355    VL_DrawPostPic (W_GetNumForName("trilogo"));
5356    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutwill"));
5357    PrepareBackground ( back );
5358    ScrollString ( 100, &cut5Msg[0], back, 4*VBLCOUNTER, 50);
5359 
5360    VL_DrawPostPic (W_GetNumForName("trilogo"));
5361    DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutstev"));
5362    PrepareBackground ( back );
5363    ScrollString ( 100, &cut6Msg[0], back, 4*VBLCOUNTER, 50);
5364 
5365    VL_FadeOut (0, 255, 0, 0, 0, 80);
5366 
5367    DrawNormalSprite(0,0,W_GetNumForName("grouppic"));
5368    PrepareBackground ( back );
5369    FlipPage();
5370    VL_FadeIn (0, 255, origpal, 30);
5371    ScrollString ( 175, &dipMsg[0], back, 4*VBLCOUNTER, 140);
5372    VL_FadeOut (0, 255, 0, 0, 0, 80);
5373 
5374    W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
5375    SafeFree(back);
5376 }
5377 
DoEndCinematic(void)5378 void DoEndCinematic ( void )
5379 {
5380    viewwidth = MAXSCREENWIDTH;
5381    viewheight = MAXSCREENHEIGHT;
5382    MU_FadeOut ( 1000 );
5383    MU_StopSong ();
5384 
5385    ShowFinalDoor();
5386    ShowTransmitter ();
5387    ShowFinalFire();
5388    DoTransmitterExplosion();
5389    MU_StartSong(song_youwin);
5390    DoBurningCastle ();
5391    DoSanNicolas();
5392    if (DestroyedAllEggs () == true)
5393       {
5394       PlayerQuestionScreen();
5395       DIPCredits();
5396       DoYouWin();
5397       if (LastScan !=0)
5398          {
5399          IN_UpdateKeyboard();
5400          return;
5401          }
5402       DoFinalEnd();
5403       }
5404    else
5405       {
5406       MU_StartSong(song_gameover);
5407       DoFailedScreen();
5408       DestroyEarth();
5409       DoTryAgainScreen ();
5410       playstate=ex_warped;
5411       gamestate.mapon=33;
5412       }
5413    IN_UpdateKeyboard();
5414 }
5415 
DoInBetweenCinematic(int yoffset,int lump,int delay,char * string)5416 void DoInBetweenCinematic (int yoffset, int lump, int delay, char * string )
5417 {
5418    int width,height;
5419    int x,y;
5420 
5421    VL_FadeOut (0, 255, 0, 0, 0, 20);
5422    VL_ClearBuffer (bufferofs, 0);
5423    DrawNormalSprite(0,yoffset,lump);
5424 
5425    CurrentFont=smallfont;
5426    US_MeasureStr (&width, &height, string);
5427    x=(320-width)>>1;
5428    y=190-height;
5429    US_ClippedPrint (x, y, string);
5430    FlipPage();
5431    VL_FadeIn(0,255,origpal,20);
5432    I_Delay (delay);
5433    VL_FadeOut (0, 255, 0, 0, 0, 20);
5434 }
5435 #endif
5436 
5437 
5438 //******************************************************************************
5439 //
5440 // DoCreditScreen
5441 //
5442 //******************************************************************************
5443 
5444 #define NUMFIRSTCREDITMESSAGES 22
5445 #define NUMSECONDCREDITMESSAGES 28
5446 
5447 typedef struct CreditType {
5448   char  text[80];
5449   byte  font;
5450   byte  endy;
5451 } CreditType;
5452 
5453 CreditType FirstCredits[NUMFIRSTCREDITMESSAGES] =
5454   {
5455     {"Rise of the Triad Credits",0,0},
5456     {"COPYRIGHT (c) 1995 Apogee Software Ltd.",1,10},
5457     {"Apogee's Developers of Incredible Power",1,20},
5458     {"Creative Director",0,30},
5459     {"Tom Hall",1,40},
5460     {"Programmers",0,50},
5461     {"Mark Dochtermann  William Scarboro",1,60},
5462     {"Jim Dose'  Nolan Martin",1,66},
5463     {"Artists",0,76},
5464     {"Stephen Hornback  Chuck Jones",1,86},
5465     {"Susan Singer  Tim Neveu",1,92},
5466     {"James Storey  Cygnus Multimedia",1,98},
5467     {"Level Designers",0,108},
5468     {"Joseph Selinske  Tom Hall",1,118},
5469     {"Marianna Vayntrub  Joe Siegler",1,124},
5470     {"Musicians",0,134},
5471     {"Lee Jackson  Robert Prince",1,144},
5472     {"Uniforms",0,154},
5473     {"D.J. Goodwin  Matt McKinney",1,164},
5474     {"Special Thanks",0,174},
5475     {"John Carmack  Ken Silverman  Gregor Punchatz",1,184},
5476   };
5477 
5478 CreditType SecondCredits[NUMSECONDCREDITMESSAGES] =
5479   {
5480     {"Rise of the Triad Credits",0,0},
5481     {"COPYRIGHT (c) 1995 Apogee Software Ltd.",1,10},
5482     {"Executive Producers",0,20},
5483     {"George Broussard  Scott Miller",1,30},
5484     {"Manual Design",0,40},
5485     {"Robert Atkins",1,50},
5486     {"Beta Testers",0,60},
5487     {"Steven Blackburn",1,70},
5488     {"Todd Aubin  Mike Bartelt",1,76},
5489     {"Wayne Benner  Neil Bonner",1,82},
5490     {"Glenn Brensinger  Douglas Brewer",1,88},
5491     {"David Butler  Daniel Creeron",1,94},
5492     {"Scott Darling  Jason Ewasiuk",1,100},
5493     {"Craig Hamilton  Ken Heckbert",1,106},
5494     {"Terry Herrin  Greg Hively",1,112},
5495     {"John Howard  Douglas Howell",1,118},
5496     {"Dennis Kurek  Hank Leukart",1,124},
5497     {"Jim Lietzan  Ken Mayer",1,130},
5498     {"Wayne Millard  Penny Plant",1,136},
5499     {"Brian Prinner  Jeff Rausch",1,142},
5500     {"Kelly Rogers  Neil Rubenking",1,148},
5501     {"Steven Salter  Chris White",1,154},
5502     {"Special Thanks",0,162},
5503     {"Apogee Technical Support  Pau Suet Ying",1,172},
5504     {"Anthony, Zach, Rajan, Miki, Loki",1,178},
5505     {"Nathan, Petro, Tim, Jake, MacKay",1,184},
5506     {"Loyal, Ric, Teller, Amano",1,190},
5507   };
5508 
DrawPreviousCredits(int num,CreditType * Credits)5509 void DrawPreviousCredits ( int num, CreditType * Credits )
5510 {
5511    int width;
5512    int height;
5513    int x,y;
5514    int i;
5515 
5516    for(i=0;i<num;i++)
5517       {
5518       if (Credits[i].font==0)
5519          CurrentFont=smallfont;
5520       else
5521          CurrentFont=tinyfont;
5522       US_MeasureStr (&width, &height, &(Credits[i].text[0]));
5523       x=(320-width)>>1;
5524       y=Credits[i].endy;
5525       US_ClippedPrint (x, y+4, &Credits[i].text[0]);
5526       }
5527 }
5528 
5529 #define CREDITSTARTY 220
5530 //******************************************************************************
5531 //
5532 // WarpCreditString
5533 //
5534 //******************************************************************************
5535 
5536 extern boolean dopefish;
WarpCreditString(int time,byte * back,int num,CreditType * Credits)5537 void WarpCreditString ( int time, byte * back, int num, CreditType * Credits)
5538 {
5539    int dy;
5540    int cy;
5541    int x;
5542    int y;
5543    int width;
5544    int height;
5545    boolean soundplayed;
5546 
5547 
5548    LastScan = 0;
5549 
5550    if (Credits[num].font==0)
5551       CurrentFont=smallfont;
5552    else
5553       CurrentFont=tinyfont;
5554    US_MeasureStr (&width, &height, &(Credits[num].text[0]));
5555 
5556    x=(320-width)>>1;
5557    y=Credits[num].endy;
5558    dy=((y-CREDITSTARTY)<<16)/time;
5559    cy=CREDITSTARTY<<16;
5560 
5561    CalcTics();
5562 
5563    soundplayed=false;
5564 
5565    while (time>0)
5566       {
5567       DrawBackground ( back );
5568       DrawPreviousCredits ( num, Credits );
5569       if (Credits[num].font==0)
5570          CurrentFont=smallfont;
5571       else
5572          CurrentFont=tinyfont;
5573       US_ClippedPrint (x, (cy>>16)+4, &Credits[num].text[0]);
5574       if ( ((cy>>16)<196) && (soundplayed==false))
5575          {
5576          if ((dopefish==true) && (SD_Started==true))
5577             {
5578             int snd;
5579 
5580             do
5581                {
5582                snd=(RandomNumber("DoCredits",0)+RandomNumber("DoCredits",0))%MAXSOUNDS;
5583                }
5584             while (SD_SoundOkay ( snd ) == false);
5585             SD_Play ( snd );
5586             }
5587          else
5588             {
5589 //            SD_Play ( SD_BAZOOKAFIRESND );
5590 #if (SHAREWARE == 0)
5591             SD_Play ( SD_BAZOOKAFIRESND + (RandomNumber("DoCredits",1)%13) );
5592 #else
5593             SD_Play ( SD_BAZOOKAFIRESND + (RandomNumber("DoCredits",1)%6) );
5594 #endif
5595             soundplayed=true;
5596             }
5597          }
5598       FlipPage();
5599       CalcTics();
5600       cy+=dy*tics;
5601       time-=tics;
5602       if (LastScan != 0)
5603          break;
5604       }
5605 }
5606 
DoCreditScreen(void)5607 void DoCreditScreen ( void )
5608 {
5609    int trilogo;
5610    int time;
5611    byte * bkgnd;
5612    font_t * oldfont;
5613    int i;
5614 
5615    viewwidth = MAXSCREENWIDTH;
5616    viewheight = MAXSCREENHEIGHT;
5617 
5618    bkgnd=SafeMalloc(800*linewidth);
5619    trilogo=W_GetNumForName("trilogo");
5620    VL_DrawPostPic (trilogo);
5621    PrepareBackground ( bkgnd );
5622 
5623    oldfont=CurrentFont;
5624 
5625    for(i=0;i<NUMFIRSTCREDITMESSAGES;i++)
5626       {
5627       time = (CREDITSTARTY - FirstCredits[i].endy)*(VBLCOUNTER*1)/CREDITSTARTY;
5628 //      time = VBLCOUNTER;
5629       WarpCreditString ( time, bkgnd, i, FirstCredits );
5630       IN_PumpEvents();
5631 //      SD_Play ( SD_EXPLODESND );
5632       if (LastScan !=0)
5633          break;
5634       }
5635    i=NUMFIRSTCREDITMESSAGES;
5636    DrawBackground ( bkgnd );
5637    DrawPreviousCredits ( i, FirstCredits );
5638    FlipPage();
5639    IN_PumpEvents();
5640 
5641    I_Delay(40);
5642 
5643    for(i=0;i<NUMSECONDCREDITMESSAGES;i++)
5644       {
5645       time = (CREDITSTARTY - SecondCredits[i].endy)*(VBLCOUNTER/2)/CREDITSTARTY;
5646 //      time = VBLCOUNTER;
5647       WarpCreditString ( time, bkgnd, i, SecondCredits );
5648       IN_PumpEvents();
5649 //      SD_Play ( SD_EXPLODESND );
5650       if (LastScan !=0)
5651          break;
5652       }
5653    i=NUMSECONDCREDITMESSAGES;
5654    DrawBackground ( bkgnd );
5655    DrawPreviousCredits ( i, SecondCredits );
5656    FlipPage();
5657    IN_PumpEvents();
5658 
5659    I_Delay(40);
5660    MenuFadeOut();
5661    VL_ClearVideo (0);
5662 
5663    SafeFree(bkgnd);
5664    CurrentFont=oldfont;
5665 }
5666 
5667 
5668 #define NUMSTORYLINES 16
5669 
5670 char * MicroStory[NUMSTORYLINES] =
5671    {
5672    "You are a member of HUNT, the",
5673    "High-Risk United Nations Taskforce.",
5674    "Stranded on an island in the",
5675    "Pacific, you must battle a master",
5676    "of pyrotechnics, hundreds of",
5677    "members of a death cult, and their",
5678    "leader, El Oscuro.",
5679    "\0",
5680    "You must reach the transmitter",
5681    "that is signalling the systematic",
5682    "destruction of Los Angeles.",
5683    "\0",
5684    "If you fail, millions will die",
5685    "and you will be tortured.",
5686    "\0",
5687    "So, you know, don't fail."
5688    };
5689 
DoMicroStoryScreen(void)5690 void DoMicroStoryScreen ( void )
5691 {
5692    pic_t * pic;
5693    int x,y;
5694    int i;
5695 
5696    VL_FadeOut (0, 255, 0, 0, 0, 20);
5697 
5698    pic=(pic_t *)W_CacheLumpName("mmbk",PU_CACHE,Cvt_pic_t,1);
5699    VWB_DrawPic (0, 0, pic);
5700    CheckHolidays();
5701 
5702    x=15;
5703    y=30;
5704 
5705    IFont = ( cfont_t * )W_CacheLumpName( "sifont", PU_CACHE, Cvt_cfont_t, 1);
5706    for(i=0;i<NUMSTORYLINES;i++)
5707       {
5708       DrawIntensityString (x, y, MicroStory[i], 241);
5709       y += 9;
5710       }
5711 
5712    FlipPage();
5713    MenuFadeIn();
5714    I_Delay (280);
5715 
5716    VL_FadeOut (0, 255, 0, 0, 0, 20);
5717 }
5718 
5719 #ifndef DOS
5720 
DrawMenuPost(int height,byte * src,byte * buf)5721 void  DrawMenuPost (int height, byte * src, byte * buf)
5722 {
5723 	int frac = hp_startfrac;
5724 	while (height--) {
5725 		*buf = src[frac >> 16];
5726 
5727 		buf += linewidth;
5728 		frac += hp_srcstep;
5729 	}
5730 }
5731 
DrawMapPost(int height,byte * src,byte * buf)5732 void  DrawMapPost (int height, byte * src, byte * buf)
5733 {
5734 	int frac = 0;
5735 	while (height--) {
5736 		*buf = src[frac >> 16];
5737 
5738 		buf += linewidth;
5739 		frac += hp_srcstep;
5740 	}
5741 }
5742 
DrawRotRow(int count,byte * dest,byte * src)5743 void DrawRotRow(int count, byte * dest, byte * src)
5744 {
5745 	unsigned eax, ecx, edx;
5746 
5747 	ecx = mr_yfrac;
5748 	edx = mr_xfrac;
5749 
5750 	while (count--) {
5751 		eax = edx >> 16;
5752 		if (eax < 256 && (ecx >> 16) < 512) {
5753 			eax = (eax << 9) | ((ecx << 7) >> (32-9));
5754 		} else {
5755 			eax = 0;
5756 		}
5757 
5758 		*dest++ = src[eax];
5759 
5760 		edx += mr_xstep;
5761 		ecx += mr_ystep;
5762 	}
5763 }
5764 
DrawMaskedRotRow(int count,byte * dest,byte * src)5765 void DrawMaskedRotRow(int count, byte * dest, byte * src)
5766 {
5767 	unsigned eax;
5768 	unsigned xfrac, yfrac;
5769 
5770 	xfrac = mr_xfrac;
5771 	yfrac = mr_yfrac;
5772 
5773 	while (count--) {
5774 		eax = xfrac >> 16;
5775 		if (eax < 256 && (yfrac >> 16) < 512) {
5776 			eax = (eax << 9) | ((yfrac << 7) >> (32-9));
5777 		} else {
5778 			eax = 0;
5779 		}
5780 
5781 		if (src[eax] != 0xff) *dest = src[eax];
5782 		dest++;
5783 
5784 		xfrac += mr_xstep;
5785 		yfrac += mr_ystep;
5786 	}
5787 }
5788 
DrawSkyPost(byte * buf,byte * src,int height)5789 void DrawSkyPost (byte * buf, byte * src, int height)
5790 {
5791 	while (height--) {
5792 		*buf = shadingtable[*src];
5793 
5794 		buf += linewidth;
5795 		src++;
5796 	}
5797 }
5798 
5799 #define CEILINGCOLOR 24
5800 #define FLOORCOLOR 32
5801 
RefreshClear(void)5802 void RefreshClear (void)
5803 {
5804 	int start, base;
5805 
5806 	memset(spotvis, 0, sizeof(spotvis));
5807 
5808 	if (fandc) {
5809 		return;
5810 	}
5811 
5812 	start = min(centery, viewheight);
5813 
5814 	if (start > 0) {
5815 		VL_Bar(0, 0, MAXSCREENWIDTH, start, CEILINGCOLOR);
5816 	} else {
5817 		start = 0;
5818 	}
5819 
5820 	base = start;
5821 
5822 	start = min(viewheight-start, viewheight);
5823 	if (start > 0) {
5824 		VL_Bar(0, base, MAXSCREENWIDTH, start, FLOORCOLOR);
5825 	}
5826 }
5827 
5828 #endif
5829 
5830 #if 0
5831 
5832 
5833 
5834 
5835 
5836 
5837 
5838 
5839 
5840 
5841 
5842 
5843 
5844 
5845 
5846 
5847 
5848 
5849 
5850 
5851 
5852 
5853 
5854 
5855 
5856 
5857 
5858 
5859 
5860 
5861 
5862 
5863 
5864 
5865 
5866 
5867 
5868 
5869 
5870 
5871 
5872 
5873 
5874 
5875 
5876 
5877 
5878 typedef struct {
5879   int   x;
5880   int   y;
5881   int   angle;
5882   int   speed;
5883   int   color;
5884   int   endx;
5885   int   endy;
5886   int   plane;
5887   int   time;
5888 } ParticleType;
5889 
5890 #define NUMPARTICLES 300
5891 #define PARTICLETHINKTIME 5
5892 #define Fix(a)        (a &= (FINEANGLES-1))
5893 ParticleType * Particle;
5894 int numparticles;
5895 
5896 //******************************************************************************
5897 //
5898 // InitializeParticles
5899 //
5900 //******************************************************************************
5901 
5902 void InitializeParticles (void)
5903 {
5904    int i;
5905    ParticleType * part;
5906 
5907    Particle=(ParticleType *)SafeMalloc ( sizeof(ParticleType) * numparticles );
5908    memset ( Particle, 0, sizeof(ParticleType) * numparticles );
5909 
5910    for (i=0;i<numparticles;i++)
5911       {
5912       part=&Particle[i];
5913       part->x=((RandomNumber("hello",0)*RandomNumber("hello",0))%viewwidth)<<16;
5914       part->y=((RandomNumber("hello",0)*RandomNumber("hello",0))%viewheight)<<16;
5915 //      part->x=(((RandomNumber("hello",0)*RandomNumber("hello",0))%(viewwidth-40)+20)<<16);
5916 //      part->y=(((RandomNumber("hello",0)*RandomNumber("hello",0))%(viewheight-40)+20)<<16);
5917       part->angle=(RandomNumber("hello",0)*RandomNumber("hello",0))%FINEANGLES;
5918 //      part->speed=(RandomNumber("hello",0)%2)<<16;
5919       part->speed=(1<<16)-1;
5920       part->color=RandomNumber("hello",0);
5921       part->endx=-1;
5922       part->endy=-1;
5923       part->plane=(part->x>>16)&3;
5924       part->time=(RandomNumber("",0)%PARTICLETHINKTIME)+1;
5925 //      part->color=255;
5926       }
5927 }
5928 
5929 //******************************************************************************
5930 //
5931 // ShutdownParticles
5932 //
5933 //******************************************************************************
5934 
5935 void ShutdownParticles (void)
5936 {
5937    SafeFree(Particle);
5938 }
5939 
5940 
5941 void AdjustParticleAngle(int maxadjust, int *currangle,int targetangle)
5942    {
5943    int dangle,i,magangle;
5944 
5945    for(i=0;i<maxadjust;i++)
5946       {
5947       dangle = *currangle - targetangle;
5948 
5949       if (dangle)
5950          {
5951          magangle = abs(dangle);
5952          if (magangle > (ANGLES/2))
5953             {
5954             if (dangle > 0)
5955                (*currangle) ++;
5956             else
5957                (*currangle) --;
5958             }
5959          else
5960             {
5961             if (dangle > 0)
5962                (*currangle) --;
5963             else
5964                (*currangle) ++;
5965             }
5966          Fix(*currangle);
5967          }
5968       }
5969    }
5970 
5971 //******************************************************************************
5972 //
5973 // UpdateParticles
5974 //
5975 //******************************************************************************
5976 
5977 //#define MAXADJUST (FINEANGLES/40)
5978 #define MAXADJUST (FINEANGLES/20)
5979 void UpdateParticles (int type)
5980 {
5981    int i;
5982    int dx,dy;
5983    ParticleType * target;
5984    ParticleType * part;
5985 
5986    if (type==0)
5987       {
5988       for (i=0;i<numparticles-1;i++)
5989          {
5990          int angle;
5991 
5992          part=&Particle[i];
5993 //         target=&Particle[numparticles-1];
5994 //         target=&Particle[i+1];
5995          target=&Particle[(RandomNumber("",0)*RandomNumber("",0))%numparticles];
5996          part->x+=-FixedMul (part->speed, costable[part->angle]);
5997          part->y+= FixedMul (part->speed, sintable[part->angle]);
5998          part->plane=(part->x>>16)&3;
5999 
6000          dx = part->x - target->x;
6001          dy = target->y - part->y;
6002          if (dx && dy)
6003             {
6004             angle = atan2_appx(dx,dy);
6005             AdjustParticleAngle(MAXADJUST,&(part->angle),angle);
6006             }
6007          }
6008       part=&Particle[numparticles-1];
6009       part->x+=-FixedMul (part->speed, costable[part->angle]);
6010       part->y+= FixedMul (part->speed, sintable[part->angle]);
6011       part->plane=(part->x>>16)&3;
6012 
6013       dx=part->x>>16;
6014       dy=part->y>>16;
6015 
6016       if ( (dx<20) || (dx>(viewwidth-20)) )
6017          {
6018          if ( part->angle < (FINEANGLES/2) )
6019             {
6020             part->angle=FINEANGLES/2-part->angle;
6021             Fix(part->angle);
6022             }
6023          else
6024             {
6025             part->angle=FINEANGLES-part->angle;
6026             Fix(part->angle);
6027             }
6028          }
6029       if ( (dy<20) || (dy>(viewheight-20)) )
6030          {
6031          part->angle=FINEANGLES-part->angle;
6032          Fix(part->angle);
6033          }
6034       }
6035    else
6036       {
6037       for (i=0;i<numparticles;i++)
6038          {
6039          int angle;
6040 
6041          part=&Particle[i];
6042          if ((part->x>>16)!=part->endx)
6043             part->x+=-FixedMul (part->speed, costable[part->angle]);
6044          else
6045             part->x=part->endx<<16;
6046          if ((part->y>>16)!=part->endy)
6047             part->y+= FixedMul (part->speed, sintable[part->angle]);
6048          else
6049             part->y=part->endy<<16;
6050          part->plane=(part->x>>16)&3;
6051 
6052          part->time--;
6053          if (part->time==0)
6054             {
6055             part->time=PARTICLETHINKTIME;
6056             dx = part->x - (part->endx<<16);
6057             dy = (part->endy<<16) - part->y;
6058             if (dx && dy)
6059                {
6060                angle = atan2_appx(dx,dy);
6061                AdjustParticleAngle(MAXADJUST,&(part->angle),angle);
6062                }
6063             }
6064          }
6065       }
6066 }
6067 
6068 //******************************************************************************
6069 //
6070 // DrawParticles
6071 //
6072 //******************************************************************************
6073 
6074 void DrawParticles (void)
6075 {
6076    int i;
6077    int dx,dy;
6078    int plane;
6079    ParticleType * part;
6080 
6081    VL_ClearBuffer (bufferofs, 0);
6082 #ifdef DOS
6083    for (plane=0;plane<4;plane++)
6084 #endif
6085       {
6086       VGAWRITEMAP(plane);
6087       for (i=0;i<numparticles;i++)
6088          {
6089          part=&Particle[i];
6090          if (part->plane!=plane)
6091             continue;
6092          dx=part->x>>16;
6093          dy=part->y>>16;
6094          if (dx<0) dx=0;
6095          if (dx>=viewwidth) dx=viewwidth-1;
6096          if (dy<0) dy=0;
6097          if (dy>=viewheight) dy=viewheight-1;
6098 #ifdef DOS
6099          *( (byte *) bufferofs + (dx>>2) + ylookup[dy] ) = part->color;
6100 #else
6101          *( (byte *) bufferofs + dx + ylookup[dy] ) = part->color;
6102 #endif
6103          }
6104       }
6105 }
6106 
6107 void DrawParticleTemplate (void)
6108 {
6109    byte pal[768];
6110 
6111    viewwidth=320;
6112    viewheight=200;
6113    memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE),768);
6114    VL_NormalizePalette(&pal[0]);
6115    SwitchPalette(&pal[0],35);
6116    VL_ClearBuffer (bufferofs, 255);
6117    DrawNormalSprite (0, 0, W_GetNumForName("ap_titl"));
6118 }
6119 
6120 void DrawAlternateParticleTemplate (void)
6121 {
6122    viewwidth=320;
6123    viewheight=200;
6124    VL_ClearBuffer (bufferofs, 255);
6125    DrawNormalSprite (0, 0, W_GetNumForName("LIFE_C1"));
6126 }
6127 
6128 int CountParticles (void)
6129 {
6130    int plane,a,b;
6131    int count;
6132 
6133    count=0;
6134 #ifdef DOS
6135    for (plane=0;plane<4;plane++)
6136 #endif
6137       {
6138       VGAREADMAP(plane);
6139       for (a=0;a<200;a++)
6140          {
6141 #ifdef DOS
6142          for (b=0;b<80;b++)
6143 #else
6144          for (b=0;b<320;b++)
6145 #endif
6146             {
6147             if (*((byte *)bufferofs+(a*linewidth)+b)!=255)
6148                count++;
6149             }
6150          }
6151       }
6152    return count;
6153 }
6154 
6155 void AssignParticles (void)
6156 {
6157    int plane,a,b;
6158    byte pixel;
6159    ParticleType * part;
6160 
6161    part=&Particle[0];
6162 
6163 #ifdef DOS
6164    for (plane=0;plane<4;plane++)
6165 #endif
6166       {
6167       VGAREADMAP(plane);
6168       for (a=0;a<200;a++)
6169          {
6170 #ifdef DOS
6171          for (b=0;b<80;b++)
6172 #else
6173          for (b=0;b<320;b++)
6174 #endif
6175             {
6176             pixel = *((byte *)bufferofs+(a*linewidth)+b);
6177             if (pixel!=255)
6178                {
6179 #ifdef DOS
6180                part->endx=plane+(b<<2);
6181 #else
6182                part->endx=b;
6183 #endif
6184                part->endy=a;
6185                part->color=pixel;
6186                part++;
6187                }
6188             }
6189          }
6190       }
6191 }
6192 
6193 //******************************************************************************
6194 //
6195 // ParticleIntro
6196 //
6197 //******************************************************************************
6198 
6199 void ParticleIntro (void)
6200 {
6201    int i,j;
6202 
6203 
6204    SetViewSize (MAXVIEWSIZES-1);
6205    numparticles=NUMPARTICLES;
6206    DrawAlternateParticleTemplate ();
6207 //   DrawParticleTemplate ();
6208    numparticles=CountParticles ();
6209    InitializeParticles ();
6210    AssignParticles();
6211 //   numparticles>>=1;
6212 
6213    CalcTics();
6214    CalcTics();
6215    LastScan=0;
6216    for (i=0;i<VBLCOUNTER*15;i+=tics)
6217       {
6218       DrawParticles();
6219       FlipPage();
6220       for (j=0;j<tics;j++)
6221          {
6222          UpdateParticles(0);
6223          }
6224       CalcTics();
6225       if ((LastScan) || IN_GetMouseButtons())
6226          break;;
6227       }
6228    LastScan=0;
6229    for (i=0;i<VBLCOUNTER*15;i+=tics)
6230       {
6231       DrawParticles();
6232       FlipPage();
6233       for (j=0;j<tics;j++)
6234          {
6235          UpdateParticles(1);
6236          }
6237       CalcTics();
6238       if ((LastScan) || IN_GetMouseButtons())
6239          break;;
6240       }
6241    ShutdownParticles ();
6242 }
6243 
6244 #endif
6245 
6246