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_BUILD.C
21 
22 #include "rt_def.h"
23 #include <string.h>
24 #include "watcom.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #ifdef DOS
29 #include <dos.h>
30 #include <conio.h>
31 #endif
32 
33 #include "rt_build.h"
34 #include "_rt_buil.h"
35 #include "rt_dr_a.h"
36 #include "rt_draw.h"
37 #include "rt_scale.h"
38 #include "rt_menu.h"
39 #include "rt_main.h"
40 #include "isr.h"
41 #include "rt_util.h"
42 #include "engine.h"
43 #include "lumpy.h"
44 #include "rt_fc_a.h"
45 #include "z_zone.h"
46 #include "w_wad.h"
47 #include "rt_view.h"
48 #include "rt_cfg.h"
49 #include "rt_vid.h"
50 
51 #include "rt_sound.h"
52 #include "modexlib.h"
53 #include "rt_str.h"
54 //MED
55 #include "memcheck.h"
56 
57 byte * intensitytable;
58 
59 
60 // LOCAL VARIABLES
61 
62 static byte * menubuf;
63 static byte * menubuffers[2];
64 static char menutitles[2][40];
65 static int alternatemenubuf=0;
66 static int titleshade=16;
67 static int titleshadedir=1;
68 static int titleyoffset=0;
69 static char titlestring[40]="\0";
70 static int readytoflip;
71 static boolean MenuBufStarted=false;
72 static int mindist=0x2700;
73 static boolean BackgroundDrawn=false;
74 
75 static plane_t planelist[MAXPLANES],*planeptr;
76 
77 static int StringShade=16;
78 
79 extern void (*USL_MeasureString)(const char *, int *, int *, font_t *);
80 
81 static char strbuf[MaxString];
82 
83 //******************************************************************************
84 //
85 // DrawRotPost
86 //
87 //******************************************************************************
88 
DrawRotPost(int height,byte * src,byte * buf,int origheight)89 void DrawRotPost ( int height, byte * src, byte * buf, int origheight)
90 {
91    int y1;
92    int y2;
93 
94    hp_srcstep=(origheight<<18)/height;
95    y1 = (((centery<<8)-(height<<5)+(MENUOFFY<<8)));
96    y2 = (((height<<6)+y1)>>8);
97 
98    if (((y1>>8)>=200) || (y2<0))
99       return;
100    if (y1<0)
101       {
102       hp_startfrac=FixedMulShift(-y1,hp_srcstep,8);
103       y2 = (((height<<6)+y1)>>8);
104       y1=0;
105       }
106    else
107       {
108       hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,8);
109       y1>>=8;
110       }
111    if (y2>200)
112       {
113       DrawMenuPost(200-y1, src, buf+ylookup[y1]);
114       }
115    else
116       {
117       DrawMenuPost(y2-y1, src, buf+ylookup[y1]);
118       }
119 }
120 
121 
122 
123 /*
124 ========================
125 =
126 = GetPoint
127 =
128 ========================
129 */
130 
GetPoint(int x1,int y1,int px,int py,int * screenx,int * height,int angle)131 void GetPoint (int x1, int y1, int px, int py, int * screenx, int * height, int angle)
132 {
133 
134   fixed gxt,gyt,nx,ny;
135   fixed gxtt,gytt;
136   int gx,gy;
137 
138 
139 //
140 // translate point to view centered coordinates
141 //
142   gx = x1-px;
143   gy = y1-py;
144 
145 //
146 // calculate newx
147 //
148   gxt = FixedMul(gx,costable[angle]);
149   gyt = FixedMul(gy,sintable[angle]);
150   nx =gxt-gyt;
151 
152   if (nx<mindist)
153 	  nx=mindist;
154 
155 
156 //
157 // calculate newy
158 //
159   gxtt = FixedMul(gx,sintable[angle]);
160   gytt = FixedMul(gy,costable[angle]);
161   ny = gytt+gxtt;
162 
163 // too close, don't overflow the divid'
164 
165 
166   *screenx = 160 + ((ny*NORMALWIDTHMULTIPLIER)/nx);            // DEBUG: use assembly divide
167 
168   *height = NORMALHEIGHTDIVISOR/nx;
169 
170   if (*screenx<0) *screenx=0;
171 
172 }
173 
174 
175 /*
176 ========================
177 =
178 = InterpolatePlane
179 =
180 ========================
181 */
182 
InterpolatePlane(visobj_t * plane)183 void InterpolatePlane (visobj_t * plane)
184 {
185    int d1,d2;
186    int top;
187    int topinc;
188    int bot;
189    int botinc;
190    int i;
191    int texture;
192    int dh;
193    int dx;
194    int height;
195 
196 
197    dx=(plane->x2-plane->x1+1);
198    if (plane->h1<=0 || plane->h2<=0 || (dx==0))
199       return;
200    d1=65536/plane->h1;
201    d2=65536/plane->h2;
202    dh=((plane->h2-plane->h1)<<8)/dx;
203    top=0;
204    topinc=(d1)*((plane->textureend-plane->texturestart)>>4);
205    bot=d2*dx;
206    botinc=d1-d2;
207    height=(plane->h1<<8);
208    if (plane->x1>=viewwidth)
209       return;
210    for (i=plane->x1;i<=plane->x2;i++)
211       {
212       if ((i>=0 && i<viewwidth)&&(posts[i].wallheight<(height>>8)))
213          {
214          if (bot)
215             {
216             texture=((top/bot)+(plane->texturestart>>4))>>6;
217             posts[i].texture=texture*plane->viewx;
218             posts[i].lump=plane->shapenum;
219             posts[i].wallheight=(height>>8);
220             posts[i].offset=plane->viewx;
221             }
222          }
223       top+=topinc;
224       bot+=botinc;
225       height+=dh;
226       }
227 }
228 
229 //******************************************************************************
230 //
231 // DrawPlanePosts
232 //
233 //******************************************************************************
234 
DrawPlanePosts(void)235 void   DrawPlanePosts (void)
236 {
237    int height;
238    char * buf;
239    byte * shape;
240    int lastwall=-2;
241    int plane;
242    int i;
243 
244    shadingtable=colormap+(16<<8);
245 
246 #ifdef DOS
247    for (plane=0;plane<4;plane++)
248 #endif
249 
250       {
251       VGAWRITEMAP(plane);
252       buf=(byte *)(bufferofs);
253 
254 #ifdef DOS
255       for (i=plane;i<viewwidth;i+=4,buf++)
256 #else
257       for (i=0;i<viewwidth;i++,buf++)
258 #endif
259          {
260          height=(posts[i].wallheight);
261          if (height<=4)
262             continue;
263          if (lastwall!=posts[i].lump)
264             {
265             lastwall=posts[i].lump;
266             if (lastwall==-1)
267                shape=menubuf;
268             else
269                shape=W_CacheLumpNum(lastwall,PU_CACHE, Cvt_patch_t, 1);
270             }
271          DrawRotPost (height,shape+posts[i].texture,buf,posts[i].offset);
272          }
273       }
274 }
275 
276 //******************************************************************************
277 //
278 // NextPlaneptr
279 //
280 //******************************************************************************
281 
NextPlaneptr(void)282 void NextPlaneptr ( void )
283 {
284    if (planeptr < &planelist[MAXPLANES-1]) // don't let it overflo'
285   		planeptr++;
286 }
287 
288 //******************************************************************************
289 //
290 // RestPlaneptr
291 //
292 //******************************************************************************
293 
ResetPlaneptr(void)294 void ResetPlaneptr ( void )
295 {
296    planeptr = &planelist[0];
297 }
298 
299 //******************************************************************************
300 //
301 // NextVisptr
302 //
303 //******************************************************************************
304 
NextVisptr(void)305 void NextVisptr ( void )
306 {
307    if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
308   		visptr++;
309 }
310 
311 //******************************************************************************
312 //
313 // ResetVisptr
314 //
315 //******************************************************************************
316 
ResetVisptr(void)317 void ResetVisptr ( void )
318 {
319    visptr = &vislist[0];
320 }
321 
322 //******************************************************************************
323 //
324 // SetupPlanes
325 //
326 //******************************************************************************
327 
SetupPlanes(void)328 void SetupPlanes ( void )
329 {
330    int i;
331 
332    for (i=0;i<320;i++)
333       posts[i].wallheight=-1;
334 }
335 
336 
337 
338 //******************************************************************************
339 //
340 // CalcPlanes
341 //
342 //******************************************************************************
343 
CalcPlanes(int px,int py,int angle)344 void CalcPlanes ( int px, int py, int angle )
345 {
346    plane_t * pptr;
347 
348    ResetVisptr();
349    for (pptr = &planelist[0]; pptr<planeptr; pptr++)
350       {
351       if (SideOfLine(pptr->x1,pptr->y1,pptr->x2,pptr->y2,px,py)<0)
352          {
353          GetPoint (pptr->x1,pptr->y1,px,py,&visptr->x1,&visptr->h1,angle);
354          GetPoint (pptr->x2,pptr->y2,px,py,&visptr->x2,&visptr->h2,angle);
355          visptr->textureend=0x0;
356          visptr->texturestart=pptr->texturewidth;
357          }
358       else
359          {
360          GetPoint (pptr->x2,pptr->y2,px,py,&visptr->x1,&visptr->h1,angle);
361          GetPoint (pptr->x1,pptr->y1,px,py,&visptr->x2,&visptr->h2,angle);
362          visptr->texturestart=0x0;
363          visptr->textureend=pptr->texturewidth;
364          }
365       visptr->shapenum=pptr->texture;
366       visptr->viewx=pptr->origheight;
367       visptr->viewheight=MAX(visptr->h1,visptr->h2);
368       NextVisptr();
369       }
370 }
371 
372 
373 //******************************************************************************
374 //
375 // DrawTransformedPlanes
376 //
377 //******************************************************************************
378 
DrawTransformedPlanes(void)379 void DrawTransformedPlanes ( void )
380 {
381    int numvisible;
382    int greatest;
383    int height;
384    int i;
385    visobj_t * closest;
386 
387    numvisible = visptr-&vislist[0];
388    if (!numvisible)
389       return;                                     // no visible objects
390    for (i = 0; i<numvisible; i++)
391       {
392       greatest = 0;
393       for (visstep=&vislist[0] ; visstep<visptr ; visstep++)
394          {
395          height = visstep->viewheight;
396          if (height > greatest)
397             {
398             greatest = height;
399             closest = visstep;
400             }
401          }
402       InterpolatePlane(closest);
403       closest->viewheight = 0;
404       }
405 }
406 
407 
408 //******************************************************************************
409 //
410 // ClearMenuBuf
411 //
412 //******************************************************************************
413 
ClearMenuBuf(void)414 void ClearMenuBuf ( void )
415 {
416    byte * shape;
417 
418    if (MenuBufStarted==false)
419       Error("Called ClearMenuBuf without menubuf started\n");
420 
421    shape=W_CacheLumpName(MENUBACKNAME,PU_CACHE, Cvt_patch_t, 1);
422    shape+=8;
423    memcpy (menubuf,shape,TEXTUREW*TEXTUREHEIGHT);
424 }
425 
426 //******************************************************************************
427 //
428 // ShutdownMenuBuf
429 //
430 //******************************************************************************
431 
ShutdownMenuBuf(void)432 void ShutdownMenuBuf ( void )
433 {
434    if (MenuBufStarted==false)
435       return;
436    MenuBufStarted=false;
437    SafeFree(menubuffers[0]);
438    SafeFree(menubuffers[1]);
439    if (loadedgame==false)
440       SetViewSize(viewsize);
441 }
442 
443 //******************************************************************************
444 //
445 // SetupMenuBuf
446 //
447 //******************************************************************************
448 
SetupMenuBuf(void)449 void SetupMenuBuf ( void )
450 {
451 #define SRCH 148
452 #define SRCW 258
453 #define PLANEX1 (-0x24000)
454 #define PLANEX2 (0x23fff)
455 #define PLANEW (16<<10)
456 #define PLANEY (0x40000)
457 #define PLANEW2 (0x5a827)
458 
459    if (MenuBufStarted==true)
460       return;
461    MenuBufStarted=true;
462 
463    // No top offsets like in game
464 
465    centery=100;
466    centeryfrac=centery<<16;
467 
468    strcpy(titlestring,menutitles[0]);
469 
470    screenofs=0;
471    viewwidth=320;
472    viewheight=200;
473 
474    alternatemenubuf=0;
475 
476    ResetPlaneptr();
477    planeptr->texture=-1;
478    planeptr->y1=PLANEX1;
479    planeptr->x1=PLANEW;
480    planeptr->y2=PLANEX2;
481    planeptr->x2=PLANEW;
482    planeptr->origheight=TEXTUREHEIGHT;
483    planeptr->texturewidth=TEXTUREWIDTH;
484    NextPlaneptr();
485    planeptr->texture=-1;
486    planeptr->y1=PLANEX1;
487    planeptr->x1=-PLANEW;
488    planeptr->y2=PLANEX2;
489    planeptr->x2=-PLANEW;
490    planeptr->origheight=TEXTUREHEIGHT;
491    planeptr->texturewidth=TEXTUREWIDTH;
492    NextPlaneptr();
493    planeptr->texture=W_GetNumForName(MENUBACKNAME);
494    planeptr->y1=PLANEX1;
495    planeptr->x1=PLANEW;
496    planeptr->y2=PLANEX1;
497    planeptr->x2=-PLANEW;
498    planeptr->origheight=TEXTUREHEIGHT;
499    planeptr->texturewidth=TEXTUREWIDTH;
500    NextPlaneptr();
501    planeptr->texture=W_GetNumForName(MENUBACKNAME);
502    planeptr->y1=PLANEX2;
503    planeptr->x1=PLANEW;
504    planeptr->y2=PLANEX2;
505    planeptr->x2=-PLANEW;
506    planeptr->origheight=TEXTUREHEIGHT;
507    planeptr->texturewidth=TEXTUREWIDTH;
508    NextPlaneptr();
509 
510    menubuffers[0]=SafeMalloc(TEXTUREW*TEXTUREHEIGHT);
511    menubuffers[1]=SafeMalloc(TEXTUREW*TEXTUREHEIGHT);
512    menubuf=menubuffers[0];
513    ClearMenuBuf();
514    BackgroundDrawn=false;
515 }
516 
517 
518 //******************************************************************************
519 //
520 // PositionMenuBuf
521 //
522 //******************************************************************************
523 
PositionMenuBuf(int angle,int distance,boolean drawbackground)524 void PositionMenuBuf( int angle, int distance, boolean drawbackground )
525 {
526    int px,py;
527    font_t * oldfont;
528    int width,height;
529 
530 
531    if (MenuBufStarted==false)
532       Error("Called PositionMenuBuf without menubuf started\n");
533    CalcTics();
534    SetupPlanes();
535    if ((drawbackground==true) || (BackgroundDrawn==false))
536       {
537       VL_DrawPostPic (W_GetNumForName("trilogo"));
538       }
539    px=FixedMulShift(distance,costable[angle&(FINEANGLES-1)],16);
540    py=FixedMulShift(-distance,sintable[angle&(FINEANGLES-1)],16);
541    CalcPlanes(px,py,(angle+ANG180)&(FINEANGLES-1));
542    DrawTransformedPlanes();
543    DrawPlanePosts();
544    oldfont=CurrentFont;
545    CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
546    US_MeasureStr (&width, &height, titlestring);
547    US_ClippedPrint ((320-width)>>1, MENUTITLEY-titleyoffset, titlestring);
548    CurrentFont=oldfont;
549    FlipPage();
550    titleshade+=titleshadedir;
551    if (abs(titleshade-16)>6)
552       titleshadedir=-titleshadedir;
553    if (BackgroundDrawn==false)
554       {
555       VL_CopyDisplayToHidden();
556       BackgroundDrawn=true;
557       }
558 }
559 
560 //******************************************************************************
561 //
562 // RefreshMenuBuf
563 //
564 //******************************************************************************
565 
RefreshMenuBuf(int time)566 void RefreshMenuBuf( int time )
567 {
568    int i;
569 
570    if (MenuBufStarted==false)
571       Error("Called RefreshMenuBuf without menubuf started\n");
572 
573    if (readytoflip)
574       return;
575 
576    for (i=0;i<=time;i+=tics)
577       {
578       PositionMenuBuf (0,NORMALVIEW,false);
579       }
580 }
581 
582 //******************************************************************************
583 //
584 // ScaleMenuBufPost
585 //
586 //******************************************************************************
587 
ScaleMenuBufPost(byte * src,int topoffset,byte * buf)588 void ScaleMenuBufPost (byte * src, int topoffset, byte * buf)
589 {
590    int  d;
591    int  offset;
592    int  length;
593    int  s;
594 
595 
596    while (1)
597       {
598       offset=*(src++);
599       if (offset==0xff)
600          return;
601       else
602          {
603          d=offset-topoffset;
604          length=*(src++);
605          for (s=0;s<length;s++,d++)
606             *(buf+d)=*(src+s);
607          src+=length;
608          }
609       }
610 }
611 
612 //******************************************************************************
613 //
614 // SetAlternateMenuBuf
615 //
616 //******************************************************************************
617 
SetAlternateMenuBuf(void)618 void SetAlternateMenuBuf ( void )
619 {
620   if (MenuBufStarted==false)
621      Error("Called SetAlternateMenuBuf without menubuf started\n");
622 
623   alternatemenubuf^=1;
624   readytoflip=1;
625   menubuf=menubuffers[alternatemenubuf];
626 }
627 
628 //******************************************************************************
629 //
630 // SetMenuTitle
631 //
632 //******************************************************************************
633 
SetMenuTitle(const char * menutitle)634 void SetMenuTitle ( const char * menutitle )
635 {
636   if (MenuBufStarted==false)
637      Error("Called SetMenuTitle without menubuf started\n");
638   strcpy(menutitles[alternatemenubuf],menutitle);
639   if (readytoflip==0)
640      strcpy(titlestring,menutitle);
641 }
642 
643 //******************************************************************************
644 //
645 // DrawMenuBufPicture
646 //
647 //******************************************************************************
648 
DrawMenuBufPicture(int x,int y,const byte * pic,int w,int h)649 void DrawMenuBufPicture (int x, int y, const byte * pic, int w, int h)
650 {
651    byte *buffer;
652    int i;
653 
654    if (MenuBufStarted==false)
655       Error("Called DrawMenuBufPictoure without menubuf started\n");
656 
657    if ((x<0) || (x+w>=TEXTUREW))
658       Error ("DrawMenuBufPicture: x is out of range\n");
659    if ((y<0) || (y+h>=TEXTUREHEIGHT))
660       Error ("DrawMenuBufPicture: y is out of range\n");
661 
662    for (i=0;i<w;i++)
663       {
664       buffer = (byte*)menubuf+y+((x+i)*TEXTUREHEIGHT);
665       memcpy(buffer,pic,h);
666       pic+=h;
667       }
668 }
669 
670 //******************************************************************************
671 //
672 // DrawMenuBufItem
673 //
674 //******************************************************************************
675 
DrawMenuBufItem(int x,int y,int shapenum)676 void DrawMenuBufItem (int x, int y, int shapenum)
677 {
678    byte *buffer;
679    int cnt;
680    byte *shape;
681    patch_t *p;
682 
683    if (MenuBufStarted==false)
684       Error("Called DrawMenuBufItem without menubuf started\n");
685 
686    shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
687    p = (patch_t *)shape;
688 
689    if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
690       Error ("DrawMenuBufItem: x is out of range\n");
691    if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
692       Error ("DrawMenuBufItem: y is out of range\n");
693 
694    buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
695 
696    for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
697       ScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
698                         p->topoffset, buffer);
699 }
700 
701 //******************************************************************************
702 //
703 // IScaleMenuBufPost
704 //
705 //******************************************************************************
706 
IScaleMenuBufPost(byte * src,int topoffset,byte * buf,int color)707 void IScaleMenuBufPost (byte * src, int topoffset, byte * buf, int color)
708 {
709    int  d;
710    int  offset;
711    int  length;
712    int  s;
713 
714 
715    while (1)
716       {
717       offset=*(src++);
718       if (offset==0xff)
719          return;
720       else
721          {
722          d=offset-topoffset;
723          length=*(src++);
724          for (s=0;s<length;s++,d++)
725             *(buf+d)=*(intensitytable+((*(src+s))<<8)+color);
726          src+=length;
727          }
728       }
729 }
730 
731 
732 //******************************************************************************
733 //
734 // DrawIMenuBufItem
735 //
736 //******************************************************************************
737 
DrawIMenuBufItem(int x,int y,int shapenum,int color)738 void DrawIMenuBufItem (int x, int y, int shapenum, int color)
739 {
740    byte *buffer;
741    int cnt;
742    byte *shape;
743    patch_t *p;
744 
745 
746    if (MenuBufStarted==false)
747       Error("Called DrawIMenuBufItem without menubuf started\n");
748 
749    shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
750    p = (patch_t *)shape;
751 
752    if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
753       Error ("DrawIMenuBufItem: x is out of range\n");
754    if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
755       Error ("DrawIMenuBufItem: y is out of range\n");
756 
757    buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
758 
759    for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
760       IScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
761                         p->topoffset, buffer, color);
762 }
763 
764 
765 //******************************************************************************
766 //
767 // TScaleMenuBufPost
768 //
769 //******************************************************************************
TScaleMenuBufPost(byte * src,int topoffset,byte * buf)770 void TScaleMenuBufPost (byte * src, int topoffset, byte * buf)
771 {
772    int  d;
773    int  offset;
774    int  length;
775    byte pixel;
776    int  s;
777 
778 
779    while (1)
780       {
781       offset=*(src++);
782       if (offset==0xff)
783          return;
784       else
785          {
786          d=offset-topoffset;
787          length=*(src++);
788          for (s=0;s<length;s++,d++)
789             {
790             pixel = *(buf+d);
791             pixel = *(shadingtable+pixel);
792             *(buf+d) = pixel;
793             }
794          src+=length;
795          }
796       }
797 }
798 
799 
800 //******************************************************************************
801 //
802 // CScaleMenuBufPost
803 //
804 //******************************************************************************
CScaleMenuBufPost(byte * src,int topoffset,byte * buf)805 void CScaleMenuBufPost (byte * src, int topoffset, byte * buf)
806 {
807    int  d;
808    int  offset;
809    int  length;
810    byte pixel;
811    int  s;
812 
813 
814    while (1)
815       {
816       offset=*(src++);
817       if (offset==0xff)
818          return;
819       else
820          {
821          d=offset-topoffset;
822          length=*(src++);
823          for (s=0;s<length;s++,d++)
824             {
825             pixel = *(src+s);
826             pixel = *(shadingtable+pixel);
827             *(buf+d) = pixel;
828             }
829          src+=length;
830          }
831       }
832 }
833 
834 
835 //******************************************************************************
836 //
837 // EraseMenuBufRegion
838 //
839 //******************************************************************************
840 
EraseMenuBufRegion(int x,int y,int width,int height)841 void EraseMenuBufRegion (int x, int y, int width, int height)
842 {
843    byte *buffer;
844    int xx,yy;
845    byte * shape;
846 
847    if (MenuBufStarted==false)
848       Error("Called EraseMenuBufRegion without menubuf started\n");
849 
850    if ((x<0) || (x+width>=TEXTUREW))
851       Error ("EraseMenuBufRegion: x is out of range\n");
852    if ((y<0) || (y+height>=TEXTUREHEIGHT))
853       Error ("EraseMenuBufRegion: y is out of range\n");
854 
855    shape=W_CacheLumpName(MENUBACKNAME,PU_CACHE, Cvt_patch_t, 1);
856    shape+=8;
857    shape+=(x*TEXTUREHEIGHT)+y;
858    buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
859 
860    for (xx = 0; xx < width; xx++)
861       {
862       for (yy = 0; yy < height; yy++)
863          *(buffer+yy)=*(shape+yy);
864       buffer+=TEXTUREHEIGHT;
865       shape+=TEXTUREHEIGHT;
866       }
867 }
868 
869 
870 //******************************************************************************
871 //
872 // DrawTMenuBufPic
873 //
874 //******************************************************************************
875 
DrawTMenuBufPic(int x,int y,int shapenum)876 void DrawTMenuBufPic (int x, int y, int shapenum)
877 {
878    byte *buffer;
879    byte *buf;
880    int xx,yy;
881    int plane;
882    int pixel;
883    byte *shape;
884    byte *src;
885    pic_t *p;
886 
887    if (MenuBufStarted==false)
888       Error("Called DrawTMenuBufPic without menubuf started\n");
889 
890    shadingtable=colormap+(25<<8);
891 
892    shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1);
893    p = (pic_t *)shape;
894 
895    if ((x<0) || ((x+(p->width<<2))>=TEXTUREW))
896       Error ("DrawTMenuBufPic: x is out of range\n");
897    if ((y<0) || ((y+p->height)>=TEXTUREHEIGHT))
898       Error ("DrawTMenuBufPic: y is out of range\n");
899 
900    buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
901 
902    src=(byte *)&p->data;
903    for (plane=0;plane<4;plane++,buffer+=TEXTUREHEIGHT)
904       {
905       for (yy = 0; yy < p->height; yy++)
906          {
907          buf=buffer+yy;
908          for (xx = 0; xx < p->width; xx++,buf+=TEXTUREHEIGHT<<2)
909             {
910             pixel = *(buf);
911             pixel = *(shadingtable+pixel);
912             *(buf) = pixel;
913             }
914          }
915       }
916 }
917 
918 
919 //******************************************************************************
920 //
921 // DrawTMenuBufItem
922 //
923 //******************************************************************************
924 
DrawTMenuBufItem(int x,int y,int shapenum)925 void DrawTMenuBufItem (int x, int y, int shapenum)
926 {
927    byte *buffer;
928    int cnt;
929    byte *shape;
930    patch_t *p;
931 
932 
933    if (MenuBufStarted==false)
934       Error("Called DrawTMenuBufItem without menubuf started\n");
935 
936    shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
937    p = (patch_t *)shape;
938 
939    shadingtable=colormap+(25<<8);
940 
941    if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
942       Error ("DrawTMenuBufItem: x is out of range\n");
943    if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
944       Error ("DrawTMenuBufItem: y is out of range\n");
945 
946    buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
947 
948    for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
949       TScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
950                         p->topoffset, buffer);
951 }
952 
953 //******************************************************************************
954 //
955 // DrawColoredMenuBufItem
956 //
957 //******************************************************************************
958 
DrawColoredMenuBufItem(int x,int y,int shapenum,int color)959 void DrawColoredMenuBufItem (int x, int y, int shapenum, int color)
960 {
961    byte *buffer;
962    int cnt;
963    byte *shape;
964    patch_t *p;
965 
966 
967    if (MenuBufStarted==false)
968       Error("Called DrawColoredMenuBufItem without menubuf started\n");
969 
970    shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
971    p = (patch_t *)shape;
972 
973    shadingtable=playermaps[color]+(16<<8);
974 
975    if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
976       Error ("DrawColoredMenuBufItem: x is out of range\n");
977    if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
978       Error ("DrawColoredMenuBufItem: y is out of range\n");
979 
980    buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
981 
982    for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
983       CScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
984                         p->topoffset, buffer);
985 }
986 
987 //******************************************************************************
988 //
989 // DrawMenuBufPic
990 //
991 //******************************************************************************
992 
DrawMenuBufPic(int x,int y,int shapenum)993 void DrawMenuBufPic (int x, int y, int shapenum)
994 {
995    byte *buffer;
996    byte *buf;
997    int xx,yy;
998    int plane;
999    byte *shape;
1000    byte *src;
1001    pic_t *p;
1002 
1003    if (MenuBufStarted==false)
1004       Error("Called DrawMenuBufPic without menubuf started\n");
1005 
1006    shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1);
1007    p = (pic_t *)shape;
1008 
1009    if ((x<0) || ((x+(p->width<<2))>=TEXTUREW))
1010       Error ("DrawTMenuBufPic: x is out of range\n");
1011    if ((y<0) || ((y+p->height)>=TEXTUREHEIGHT))
1012       Error ("DrawTMenuBufPic: y is out of range\n");
1013 
1014 
1015    buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
1016 
1017    src=(byte *)&p->data;
1018    for (plane=0;plane<4;plane++,buffer+=TEXTUREHEIGHT)
1019       {
1020       for (yy = 0; yy < p->height; yy++)
1021          {
1022          buf=buffer+yy;
1023          for (xx = 0; xx < p->width; xx++,buf+=TEXTUREHEIGHT<<2)
1024             *(buf)=*(src++);
1025          }
1026       }
1027 }
1028 
1029 
1030 
1031 
1032 //******************************************************************************
1033 //
1034 // DrawTMenuBufBox
1035 //
1036 //******************************************************************************
1037 
1038 
DrawTMenuBufBox(int x,int y,int width,int height)1039 void DrawTMenuBufBox ( int x, int y, int width, int height )
1040    {
1041    byte *buffer;
1042    int   xx;
1043    int   yy;
1044    int   pixel;
1045 
1046    if (MenuBufStarted==false)
1047       Error("Called DrawTMenuBufBox without menubuf started\n");
1048 
1049    shadingtable = colormap + ( 25 << 8 );
1050 
1051    if ( ( x < 0 ) || ( ( x + width ) >= TEXTUREW ) )
1052       Error ("DrawTMenuBar : x is out of range\n");
1053    if ( ( y < 0 ) || ( y + height ) >= TEXTUREHEIGHT )
1054       Error ("DrawTMenuBar : y is out of range\n");
1055 
1056    buffer = ( byte * )menubuf + ( x * TEXTUREHEIGHT ) + y;
1057 
1058    for ( xx = 0; xx < width; xx++ )
1059       {
1060       for ( yy = 0; yy < height; yy++ )
1061          {
1062          pixel = *( buffer + yy );
1063          pixel = *( shadingtable + pixel );
1064          *( buffer + yy ) = pixel;
1065          }
1066 
1067       buffer += TEXTUREHEIGHT;
1068       }
1069    }
1070 
1071 
1072 //******************************************************************************
1073 //
1074 // DrawTMenuBufHLine
1075 //
1076 //******************************************************************************
1077 
DrawTMenuBufHLine(int x,int y,int width,boolean up)1078 void DrawTMenuBufHLine (int x, int y, int width, boolean up)
1079 {
1080    byte *buffer;
1081    byte *buf;
1082    int xx;
1083    int plane;
1084    int pixel;
1085    int w = width>>2;
1086    int ww = w;
1087 
1088    if ((x<0) || ((x+(width))>=TEXTUREW))
1089       Error ("DrawTMenuBufBox: x is out of range\n");
1090    if (y<0)
1091       Error ("DrawTMenuBufBox: y is out of range\n");
1092 
1093    buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
1094 
1095    if (up)
1096       shadingtable=colormap+(13<<8);
1097    else
1098       shadingtable=colormap+(25<<8);
1099 
1100    for (plane = 0; plane < 4; plane++, buffer += TEXTUREHEIGHT)
1101    {
1102       w = ww;
1103       switch (plane)
1104       {
1105          case 0:
1106             if (width % 4)
1107                w++;
1108          break;
1109          case 1:
1110             if ((width % 4) > 1)
1111                w++;
1112          break;
1113          case 2:
1114             if ((width % 4) > 2)
1115                w++;
1116          break;
1117       }
1118 
1119 
1120       buf = buffer;
1121       for (xx = 0; xx < w; xx++, buf += (TEXTUREHEIGHT<<2))
1122       {
1123          pixel = *(buf);
1124          pixel = *(shadingtable+pixel);
1125          *(buf) = pixel;
1126       }
1127    }
1128 }
1129 
1130 //******************************************************************************
1131 //
1132 // DrawTMenuBufVLine
1133 //
1134 //******************************************************************************
1135 
DrawTMenuBufVLine(int x,int y,int height,boolean up)1136 void DrawTMenuBufVLine (int x, int y, int height, boolean up)
1137 {
1138    byte *buffer;
1139    byte *buf;
1140    int yy;
1141    int pixel;
1142 
1143    if (x<0)
1144       Error ("DrawTMenuBufBox: x is out of range\n");
1145    if ((y<0) || ((y+height)>=TEXTUREHEIGHT))
1146       Error ("DrawTMenuBufBox: y is out of range\n");
1147 
1148    buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
1149 
1150    if (up)
1151       shadingtable=colormap+(13<<8);
1152    else
1153       shadingtable=colormap+(25<<8);
1154 
1155    for (yy = 0; yy < height; yy++)
1156    {
1157       buf = buffer+yy;
1158       pixel = *(buf);
1159       pixel = *(shadingtable+pixel);
1160       *(buf) = pixel;
1161    }
1162 }
1163 
1164 //******************************************************************************
1165 //******************************************************************************
1166 //
1167 // STRING ROUTINES
1168 //
1169 //******************************************************************************
1170 //******************************************************************************
1171 
1172 
1173 //******************************************************************************
1174 //
1175 // DrawMenuBufPropString ()
1176 //
1177 //******************************************************************************
1178 
DrawMenuBufPropString(int px,int py,const char * string)1179 void DrawMenuBufPropString (int px, int py, const char *string)
1180 {
1181    byte  pix;
1182    int   width,height,ht;
1183    byte  *source, *dest, *origdest;
1184    int   ch;
1185 
1186 
1187    if (MenuBufStarted==false)
1188       Error("Called DrawMenuBufPropString without menubuf started\n");
1189 
1190    ht = CurrentFont->height;
1191    dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py;
1192 
1193    while ((ch = (unsigned char)*string++)!=0)
1194    {
1195       ch -= 31;
1196       width = CurrentFont->width[ch];
1197       source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
1198       while (width--)
1199       {
1200          height = ht;
1201          while (height--)
1202          {
1203             pix = *source;
1204             if (pix)
1205                *dest = pix;
1206 
1207             source++;
1208             dest ++;
1209          }
1210 
1211          PrintX++;
1212          origdest+=TEXTUREHEIGHT;
1213          dest = origdest;
1214       }
1215    }
1216 
1217 }
1218 
1219 
1220 //******************************************************************************
1221 //
1222 // DrawMenuBufIString ()
1223 //
1224 //******************************************************************************
1225 
DrawMenuBufIString(int px,int py,const char * string,int color)1226 void DrawMenuBufIString (int px, int py, const char *string, int color)
1227 {
1228    byte  pix;
1229    int   width,height,ht;
1230    byte  *source, *dest, *origdest;
1231    int   ch;
1232 
1233    if (MenuBufStarted==false)
1234       Error("Called DrawMenuBufPropString without menubuf started\n");
1235 
1236    if ( ( color < 0 ) || ( color > 255 ) )
1237       {
1238       Error( "Intensity Color out of range\n" );
1239       }
1240 
1241    ht = IFont->height;
1242    dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py;
1243 
1244    PrintX = px;
1245    PrintY = py;
1246 
1247    while ((ch = (unsigned char)*string++)!=0)
1248    {
1249       // Tab
1250       if ( ch == '\x9' )
1251          {
1252          int offset;
1253 
1254          PrintX   -= px;
1255          offset    = 4 * 5 - PrintX % ( 4 * 5 );
1256          PrintX   += offset + px;
1257          origdest += offset * TEXTUREHEIGHT;
1258          dest      = origdest;
1259          continue;
1260          }
1261 
1262       ch -= 31;
1263       width = IFont->width[ ch ];
1264 
1265       source = ( ( byte * )IFont ) + IFont->charofs[ ch ];
1266 
1267       while (width--)
1268       {
1269          height = ht;
1270          while (height--)
1271          {
1272             pix = *source;
1273             if ( pix != 0xFE )
1274                {
1275                *dest = ( ( byte )intensitytable[ ( pix << 8 ) + color ] );
1276                GetIntensityColor( pix );
1277                }
1278 
1279             source++;
1280             dest ++;
1281          }
1282 
1283          PrintX++;
1284          origdest+=TEXTUREHEIGHT;
1285          dest = origdest;
1286       }
1287    }
1288 
1289 }
1290 
1291 
1292 //******************************************************************************
1293 //
1294 // DrawTMenuBufPropString ()
1295 //
1296 // Draws a string at px, py to bufferofs
1297 //
1298 //******************************************************************************
1299 
DrawTMenuBufPropString(int px,int py,const char * string)1300 void DrawTMenuBufPropString (int px, int py, const char *string)
1301 {
1302    byte  pix;
1303    int   width,height,ht;
1304    byte  *source, *dest, *origdest;
1305    int   ch;
1306 
1307 
1308    if (MenuBufStarted==false)
1309       Error("Called DrawTMenuBufPropString without menubuf started\n");
1310 
1311    ht = CurrentFont->height;
1312    dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py;
1313 
1314    shadingtable=colormap+(StringShade<<8);
1315    while ((ch = (unsigned char)*string++)!=0)
1316    {
1317       ch -= 31;
1318       width = CurrentFont->width[ch];
1319       source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
1320       while (width--)
1321       {
1322          height = ht;
1323          while (height--)
1324          {
1325             pix = *source;
1326             if (pix)
1327                {
1328                pix = *dest;
1329                pix = *(shadingtable+pix);
1330                *dest = pix;
1331                }
1332             source++;
1333             dest ++;
1334          }
1335 
1336          PrintX++;
1337          origdest+=TEXTUREHEIGHT;
1338          dest = origdest;
1339       }
1340    }
1341 }
1342 
1343 
1344 //******************************************************************************
1345 //
1346 // MenuBufCPrintLine() - Prints a string centered on the current line and
1347 //    advances to the next line. Newlines are not supported.
1348 //
1349 //******************************************************************************
1350 
MenuBufCPrintLine(const char * s)1351 void MenuBufCPrintLine (const char *s)
1352 {
1353    int w, h;
1354 
1355    USL_MeasureString (s, &w, &h, CurrentFont);
1356 
1357    if (w > WindowW)
1358       Error("MenuBufCPrintLine() - String exceeds width");
1359 
1360    PrintX = WindowX + ((WindowW - w) / 2);
1361    DrawMenuBufPropString (PrintX, PrintY, s);
1362    PrintY += h;
1363 }
1364 
1365 //******************************************************************************
1366 //
1367 // MenuBufCPrint() - Prints a string in the current window. Newlines are
1368 //    supported.
1369 //
1370 //******************************************************************************
1371 
MenuBufCPrint(const char * string)1372 void MenuBufCPrint (const char *string)
1373 {
1374    char  c,
1375          *se,
1376          *s;
1377 
1378     /* !!! FIXME: this is lame. */
1379     if (strlen(string) >= sizeof (strbuf))
1380     {
1381         fprintf(stderr, "buffer overflow!\n");
1382         return;
1383     }
1384 
1385     /* prevent writing to literal strings... ( MenubufCPrint("feh"); ) */
1386     strcpy(strbuf, string);
1387     s = strbuf;
1388 
1389    while (*s)
1390    {
1391       se = s;
1392       while ((c = *se) && (c != '\n'))
1393          se++;
1394       *se = '\0';
1395 
1396       MenuBufCPrintLine(s);
1397 
1398       s = se;
1399       if (c)
1400       {
1401          *se = c;
1402          s++;
1403       }
1404    }
1405 }
1406 
1407 //******************************************************************************
1408 //
1409 // MenuBufPrintLine() - Prints a string on the current line and
1410 //    advances to the next line. Newlines are not supported.
1411 //
1412 //******************************************************************************
1413 
MenuBufPrintLine(const char * s)1414 void MenuBufPrintLine (const char *s)
1415 {
1416    int w, h;
1417 
1418    USL_MeasureString (s, &w, &h, CurrentFont);
1419 
1420    if (w > WindowW)
1421       Error("MenuBufCPrintLine() - String exceeds width");
1422 
1423    PrintX = WindowX;
1424    DrawMenuBufPropString (PrintX, PrintY, s);
1425    PrintY += h;
1426 }
1427 
1428 //******************************************************************************
1429 //
1430 // MenuBufPrint() - Prints a string in the current window. Newlines are
1431 //    supported.
1432 //
1433 //******************************************************************************
1434 
MenuBufPrint(const char * string)1435 void MenuBufPrint (const char *string)
1436 {
1437    char  c,
1438          *se,
1439          *s;
1440 
1441    strcpy(strbuf, string);
1442    s = strbuf;
1443 
1444    while (*s)
1445    {
1446       se = s;
1447       while ((c = *se) && (c != '\n'))
1448          se++;
1449       *se = '\0';
1450 
1451       MenuBufPrintLine(s);
1452 
1453       s = se;
1454       if (c)
1455       {
1456          *se = c;
1457          s++;
1458       }
1459    }
1460 }
1461 
1462 //******************************************************************************
1463 //
1464 // MenuTBufPrintLine() - Prints a string on the current line and
1465 //    advances to the next line. Newlines are not supported.
1466 //
1467 //******************************************************************************
1468 
MenuTBufPrintLine(const char * s,int shade)1469 void MenuTBufPrintLine (const char *s, int shade)
1470 {
1471    int w, h;
1472 
1473    USL_MeasureString (s, &w, &h, CurrentFont);
1474 
1475    if (w > WindowW)
1476       Error("MenuBufCPrintLine() - String exceeds width");
1477 
1478    PrintX = WindowX;
1479    StringShade=shade;
1480    DrawTMenuBufPropString (PrintX, PrintY, s);
1481    PrintY += h;
1482 }
1483 
1484 //******************************************************************************
1485 //
1486 // FlipMenuBuf
1487 //
1488 //******************************************************************************
1489 
FlipMenuBuf(void)1490 void FlipMenuBuf ( void )
1491 {
1492    int i;
1493    int dh;
1494    int h;
1495    int y;
1496    int dy;
1497    int time;
1498    int flip;
1499 
1500    if (MenuBufStarted==false)
1501       Error("Called FlipMenuBuf without menubuf started\n");
1502 
1503    if (!readytoflip)
1504       Error("FlipMenuBuf called without SetAlternateMenuBuf beforehand");
1505    readytoflip=0;
1506    if (Menuflipspeed<=5)
1507       {
1508       menubuf=menubuffers[alternatemenubuf];
1509       strcpy(titlestring,menutitles[alternatemenubuf]);
1510       RefreshMenuBuf(0);
1511       }
1512    else
1513       {
1514       menubuf=menubuffers[alternatemenubuf^1];
1515       strcpy(titlestring,menutitles[alternatemenubuf^1]);
1516       time=Menuflipspeed-5;
1517       dh=(1024<<8)/time;
1518       h=0;
1519       dy=((MENUTITLEY*6)<<8)/time;
1520       y=0;
1521       flip=0;
1522       titleyoffset=0;
1523       for (i=0;i<time;i+=tics)
1524          {
1525          PositionMenuBuf(h>>8,NORMALVIEW,true);
1526          h+=dh*tics;
1527          y+=dy*tics;
1528          titleyoffset=y>>8;
1529          if ((h>=512<<8) && (flip==0))
1530             {
1531             MN_PlayMenuSnd (SD_MENUFLIP);
1532             h=1536<<8;
1533             dy=-dy;
1534             menubuf=menubuffers[alternatemenubuf];
1535             strcpy(titlestring,menutitles[alternatemenubuf]);
1536             flip=1;
1537             }
1538          }
1539       }
1540    titleyoffset=0;
1541    BackgroundDrawn=false;
1542 }
1543 
1544 
1545 
1546 //******************************************************************************
1547 //
1548 // RotatePlane
1549 //
1550 //******************************************************************************
1551 
RotatePlane(void)1552 void RotatePlane ( void )
1553 {
1554    SetupMenuBuf();
1555 
1556    while (!(Keyboard[0x01]))
1557       {
1558       RefreshMenuBuf(100);
1559       SetAlternateMenuBuf();
1560       ClearMenuBuf();
1561       DrawMenuBufPic  (0,0,W_GetNumForName("newg11"));
1562       DrawMenuBufItem (0,0,W_GetNumForName("apogee"));
1563       FlipMenuBuf();
1564       EraseMenuBufRegion(30,30,30,30);
1565       RefreshMenuBuf(100);
1566       SetAlternateMenuBuf();
1567       ClearMenuBuf();
1568       FlipMenuBuf();
1569       }
1570    ShutdownMenuBuf();
1571 }
1572