ref: 14257941774d9c6e8fbff6632ba7cf02d1ce9c10
dir: /src/rt_build.c/
/* Copyright (C) 1994-1995 Apogee Software, Ltd. Copyright (C) 2002-2015 icculus.org, GNU/Linux port Copyright (C) 2017-2018 Steven LeVesque This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ // RT_BUILD.C #include "rt_def.h" #include <string.h> #include "watcom.h" #include <stdio.h> #include <stdlib.h> #include "rt_build.h" #include "_rt_buil.h" #include "rt_dr_a.h" #include "rt_draw.h" #include "rt_scale.h" #include "rt_menu.h" #include "rt_main.h" #include "isr.h" #include "rt_util.h" #include "engine.h" #include "lumpy.h" #include "rt_fc_a.h" #include "z_zone.h" #include "w_wad.h" #include "rt_view.h" #include "rt_cfg.h" #include "rt_vid.h" #include "rt_sound.h" #include "modexlib.h" #include "rt_str.h" byte * intensitytable; // LOCAL VARIABLES static byte * menubuf; static byte * menubuffers[2]; static char menutitles[2][40]; static int alternatemenubuf=0; static int titleshade=16; static int titleshadedir=1; static int titleyoffset=0; static char titlestring[40]="\0"; static int readytoflip; static boolean MenuBufStarted=false; static int mindist=0x2700; static boolean BackgroundDrawn=false; static plane_t planelist[MAXPLANES],*planeptr; static int StringShade=16; extern void (*USL_MeasureString)(const char *, int *, int *, font_t *); static char strbuf[MaxString]; //****************************************************************************** // // DrawRotPost // //****************************************************************************** void DrawRotPost ( int height, byte * src, byte * buf, int origheight) { int y1; int y2; hp_srcstep=(origheight<<18)/height; y1 = (((centery<<8)-(height<<5)+(MENUOFFY<<8))); y2 = (((height<<6)+y1)>>8); if (((y1>>8)>=200) || (y2<0)) return; if (y1<0) { hp_startfrac=FixedMulShift(-y1,hp_srcstep,8); y2 = (((height<<6)+y1)>>8); y1=0; } else { hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,8); y1>>=8; } if (y2>200) { DrawMenuPost(200-y1, src, buf+ylookup[y1]); } else { DrawMenuPost(y2-y1, src, buf+ylookup[y1]); } } /* ======================== = = GetPoint = ======================== */ void GetPoint (int x1, int y1, int px, int py, int * screenx, int * height, int angle) { fixed gxt,gyt,nx,ny; fixed gxtt,gytt; int gx,gy; // // translate point to view centered coordinates // gx = x1-px; gy = y1-py; // // calculate newx // gxt = FixedMul(gx,costable[angle]); gyt = FixedMul(gy,sintable[angle]); nx =gxt-gyt; if (nx<mindist) nx=mindist; // // calculate newy // gxtt = FixedMul(gx,sintable[angle]); gytt = FixedMul(gy,costable[angle]); ny = gytt+gxtt; // too close, don't overflow the divid' *screenx = 160 + ((ny*NORMALWIDTHMULTIPLIER)/nx); // DEBUG: use assembly divide *height = NORMALHEIGHTDIVISOR/nx; if (*screenx<0) *screenx=0; } /* ======================== = = InterpolatePlane = ======================== */ void InterpolatePlane (visobj_t * plane) { int d1,d2; int top; int topinc; int bot; int botinc; int i; int texture; int dh; int dx; int height; dx=(plane->x2-plane->x1+1); if (plane->h1<=0 || plane->h2<=0 || (dx==0)) return; d1=65536/plane->h1; d2=65536/plane->h2; dh=((plane->h2-plane->h1)<<8)/dx; top=0; topinc=(d1)*((plane->textureend-plane->texturestart)>>4); bot=d2*dx; botinc=d1-d2; height=(plane->h1<<8); if (plane->x1>=viewwidth) return; for (i=plane->x1; i<=plane->x2; i++) { if ((i>=0 && i<viewwidth)&&(posts[i].wallheight<(height>>8))) { if (bot) { texture=((top/bot)+(plane->texturestart>>4))>>6; posts[i].texture=texture*plane->viewx; posts[i].lump=plane->shapenum; posts[i].wallheight=(height>>8); posts[i].offset=plane->viewx; } } top+=topinc; bot+=botinc; height+=dh; } } //****************************************************************************** // // DrawPlanePosts // //****************************************************************************** void DrawPlanePosts (void) { int height; char * buf; byte * shape = NULL; int lastwall=-2; int i; shadingtable=colormap+(16<<8); { buf=(char *)(bufferofs); for (i=0; i<viewwidth; i++,buf++) { height=(posts[i].wallheight); if (height<=4) continue; if (lastwall!=posts[i].lump) { lastwall=posts[i].lump; if (lastwall==-1) shape=menubuf; else shape=W_CacheLumpNum(lastwall,PU_CACHE, Cvt_patch_t, 1); } DrawRotPost (height,shape+posts[i].texture,(byte*)buf,posts[i].offset); } } } //****************************************************************************** // // NextPlaneptr // //****************************************************************************** void NextPlaneptr ( void ) { if (planeptr < &planelist[MAXPLANES-1]) // don't let it overflo' planeptr++; } //****************************************************************************** // // RestPlaneptr // //****************************************************************************** void ResetPlaneptr ( void ) { planeptr = &planelist[0]; } //****************************************************************************** // // NextVisptr // //****************************************************************************** void NextVisptr ( void ) { if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo' visptr++; } //****************************************************************************** // // ResetVisptr // //****************************************************************************** void ResetVisptr ( void ) { visptr = &vislist[0]; } //****************************************************************************** // // SetupPlanes // //****************************************************************************** void SetupPlanes ( void ) { int i; for (i=0; i<320; i++) posts[i].wallheight=-1; } //****************************************************************************** // // CalcPlanes // //****************************************************************************** void CalcPlanes ( int px, int py, int angle ) { plane_t * pptr; ResetVisptr(); for (pptr = &planelist[0]; pptr<planeptr; pptr++) { if (SideOfLine(pptr->x1,pptr->y1,pptr->x2,pptr->y2,px,py)<0) { GetPoint (pptr->x1,pptr->y1,px,py,&visptr->x1,&visptr->h1,angle); GetPoint (pptr->x2,pptr->y2,px,py,&visptr->x2,&visptr->h2,angle); visptr->textureend=0x0; visptr->texturestart=pptr->texturewidth; } else { GetPoint (pptr->x2,pptr->y2,px,py,&visptr->x1,&visptr->h1,angle); GetPoint (pptr->x1,pptr->y1,px,py,&visptr->x2,&visptr->h2,angle); visptr->texturestart=0x0; visptr->textureend=pptr->texturewidth; } visptr->shapenum=pptr->texture; visptr->viewx=pptr->origheight; visptr->viewheight=MAX(visptr->h1,visptr->h2); NextVisptr(); } } //****************************************************************************** // // DrawTransformedPlanes // //****************************************************************************** void DrawTransformedPlanes ( void ) { int numvisible; int greatest; int height; int i; visobj_t * closest = NULL; numvisible = visptr-&vislist[0]; if (!numvisible) return; // no visible objects for (i = 0; i<numvisible; i++) { greatest = 0; for (visstep=&vislist[0] ; visstep<visptr ; visstep++) { height = visstep->viewheight; if (height > greatest) { greatest = height; closest = visstep; } } InterpolatePlane(closest); closest->viewheight = 0; } } //****************************************************************************** // // ClearMenuBuf // //****************************************************************************** void ClearMenuBuf ( void ) { byte * shape; if (MenuBufStarted==false) Error("Called ClearMenuBuf without menubuf started\n"); shape=W_CacheLumpName(MENUBACKNAME,PU_CACHE, Cvt_patch_t, 1); shape+=8; memcpy (menubuf,shape,TEXTUREW*TEXTUREHEIGHT); } //****************************************************************************** // // ShutdownMenuBuf // //****************************************************************************** void ShutdownMenuBuf ( void ) { if (MenuBufStarted==false) return; MenuBufStarted=false; SafeFree(menubuffers[0]); SafeFree(menubuffers[1]); if (loadedgame==false) SetViewSize(viewsize); } //****************************************************************************** // // SetupMenuBuf // //****************************************************************************** void SetupMenuBuf ( void ) { #define SRCH 148 #define SRCW 258 #define PLANEX1 (-0x24000) #define PLANEX2 (0x23fff) #define PLANEW (16<<10) #define PLANEY (0x40000) #define PLANEW2 (0x5a827) if (MenuBufStarted==true) return; MenuBufStarted=true; // No top offsets like in game centery=100; centeryfrac=centery<<16; strcpy(titlestring,menutitles[0]); screenofs=0; viewwidth=320; viewheight=200; alternatemenubuf=0; ResetPlaneptr(); planeptr->texture=-1; planeptr->y1=PLANEX1; planeptr->x1=PLANEW; planeptr->y2=PLANEX2; planeptr->x2=PLANEW; planeptr->origheight=TEXTUREHEIGHT; planeptr->texturewidth=TEXTUREWIDTH; NextPlaneptr(); planeptr->texture=-1; planeptr->y1=PLANEX1; planeptr->x1=-PLANEW; planeptr->y2=PLANEX2; planeptr->x2=-PLANEW; planeptr->origheight=TEXTUREHEIGHT; planeptr->texturewidth=TEXTUREWIDTH; NextPlaneptr(); planeptr->texture=W_GetNumForName(MENUBACKNAME); planeptr->y1=PLANEX1; planeptr->x1=PLANEW; planeptr->y2=PLANEX1; planeptr->x2=-PLANEW; planeptr->origheight=TEXTUREHEIGHT; planeptr->texturewidth=TEXTUREWIDTH; NextPlaneptr(); planeptr->texture=W_GetNumForName(MENUBACKNAME); planeptr->y1=PLANEX2; planeptr->x1=PLANEW; planeptr->y2=PLANEX2; planeptr->x2=-PLANEW; planeptr->origheight=TEXTUREHEIGHT; planeptr->texturewidth=TEXTUREWIDTH; NextPlaneptr(); menubuffers[0]=SafeMalloc(TEXTUREW*TEXTUREHEIGHT); menubuffers[1]=SafeMalloc(TEXTUREW*TEXTUREHEIGHT); menubuf=menubuffers[0]; ClearMenuBuf(); BackgroundDrawn=false; } //****************************************************************************** // // PositionMenuBuf // //****************************************************************************** void PositionMenuBuf( int angle, int distance, boolean drawbackground ) { int px,py; font_t * oldfont; int width,height; if (MenuBufStarted==false) Error("Called PositionMenuBuf without menubuf started\n"); CalcTics(); SetupPlanes(); if ((drawbackground==true) || (BackgroundDrawn==false)) { VL_DrawPostPic (W_GetNumForName("trilogo")); } px=FixedMulShift(distance,costable[angle&(FINEANGLES-1)],16); py=FixedMulShift(-distance,sintable[angle&(FINEANGLES-1)],16); CalcPlanes(px,py,(angle+ANG180)&(FINEANGLES-1)); DrawTransformedPlanes(); DrawPlanePosts(); oldfont=CurrentFont; CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1); US_MeasureStr (&width, &height, "%s", titlestring); US_ClippedPrint ((320-width)>>1, MENUTITLEY-titleyoffset, titlestring); CurrentFont=oldfont; FlipPage(); titleshade+=titleshadedir; if (abs(titleshade-16)>6) titleshadedir=-titleshadedir; } //****************************************************************************** // // RefreshMenuBuf // //****************************************************************************** void RefreshMenuBuf( int time ) { int i; if (MenuBufStarted==false) Error("Called RefreshMenuBuf without menubuf started\n"); if (readytoflip) return; for (i=0; i<=time; i+=tics) { //PositionMenuBuf (0,NORMALVIEW,false); PositionMenuBuf (0,NORMALVIEW,true);//bna++ in not true bg in menu is no redrawn } } //****************************************************************************** // // ScaleMenuBufPost // //****************************************************************************** void ScaleMenuBufPost (byte * src, int topoffset, byte * buf) { int d; int offset; int length; int s; while (1) { offset=*(src++); if (offset==0xff) return; else { d=offset-topoffset; length=*(src++); for (s=0; s<length; s++,d++) *(buf+d)=*(src+s); src+=length; } } } //****************************************************************************** // // SetAlternateMenuBuf // //****************************************************************************** void SetAlternateMenuBuf ( void ) { if (MenuBufStarted==false) Error("Called SetAlternateMenuBuf without menubuf started\n"); alternatemenubuf^=1; readytoflip=1; menubuf=menubuffers[alternatemenubuf]; } //****************************************************************************** // // SetMenuTitle // //****************************************************************************** void SetMenuTitle ( const char * menutitle ) { if (MenuBufStarted==false) Error("Called SetMenuTitle without menubuf started\n"); strcpy(menutitles[alternatemenubuf],menutitle); if (readytoflip==0) strcpy(titlestring,menutitle); } //****************************************************************************** // // DrawMenuBufPicture // //****************************************************************************** void DrawMenuBufPicture (int x, int y, const byte * pic, int w, int h) { byte *buffer; int i; if (MenuBufStarted==false) Error("Called DrawMenuBufPictoure without menubuf started\n"); if ((x<0) || (x+w>=TEXTUREW)) Error ("DrawMenuBufPicture: x is out of range\n"); if ((y<0) || (y+h>=TEXTUREHEIGHT)) Error ("DrawMenuBufPicture: y is out of range\n"); for (i=0; i<w; i++) { buffer = (byte*)menubuf+y+((x+i)*TEXTUREHEIGHT); memcpy(buffer,pic,h); pic+=h; } } //****************************************************************************** // // DrawMenuBufItem // //****************************************************************************** void DrawMenuBufItem (int x, int y, int shapenum) { byte *buffer; int cnt; byte *shape; patch_t *p; if (MenuBufStarted==false) Error("Called DrawMenuBufItem without menubuf started\n"); shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1); p = (patch_t *)shape; if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW)) Error ("DrawMenuBufItem: x is out of range\n"); if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT)) Error ("DrawMenuBufItem: y is out of range\n"); buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT); for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT) ScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape), p->topoffset, buffer); } //****************************************************************************** // // IScaleMenuBufPost // //****************************************************************************** void IScaleMenuBufPost (byte * src, int topoffset, byte * buf, int color) { int d; int offset; int length; int s; while (1) { offset=*(src++); if (offset==0xff) return; else { d=offset-topoffset; length=*(src++); for (s=0; s<length; s++,d++) *(buf+d)=*(intensitytable+((*(src+s))<<8)+color); src+=length; } } } //****************************************************************************** // // DrawIMenuBufItem // //****************************************************************************** void DrawIMenuBufItem (int x, int y, int shapenum, int color) { byte *buffer; int cnt; byte *shape; patch_t *p; if (MenuBufStarted==false) Error("Called DrawIMenuBufItem without menubuf started\n"); shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1); p = (patch_t *)shape; if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW)) Error ("DrawIMenuBufItem: x is out of range\n"); if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT)) Error ("DrawIMenuBufItem: y is out of range\n"); buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT); for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT) IScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape), p->topoffset, buffer, color); } //****************************************************************************** // // TScaleMenuBufPost // //****************************************************************************** void TScaleMenuBufPost (byte * src, int topoffset, byte * buf) { int d; int offset; int length; byte pixel; int s; while (1) { offset=*(src++); if (offset==0xff) return; else { d=offset-topoffset; length=*(src++); for (s=0; s<length; s++,d++) { pixel = *(buf+d); pixel = *(shadingtable+pixel); *(buf+d) = pixel; } src+=length; } } } //****************************************************************************** // // CScaleMenuBufPost // //****************************************************************************** void CScaleMenuBufPost (byte * src, int topoffset, byte * buf) { int d; int offset; int length; byte pixel; int s; while (1) { offset=*(src++); if (offset==0xff) return; else { d=offset-topoffset; length=*(src++); for (s=0; s<length; s++,d++) { pixel = *(src+s); pixel = *(shadingtable+pixel); *(buf+d) = pixel; } src+=length; } } } //****************************************************************************** // // EraseMenuBufRegion // //****************************************************************************** void EraseMenuBufRegion (int x, int y, int width, int height) { byte *buffer; int xx,yy; byte * shape; if (MenuBufStarted==false) Error("Called EraseMenuBufRegion without menubuf started\n"); if ((x<0) || (x+width>=TEXTUREW)) Error ("EraseMenuBufRegion: x is out of range\n"); if ((y<0) || (y+height>=TEXTUREHEIGHT)) Error ("EraseMenuBufRegion: y is out of range\n"); shape=W_CacheLumpName(MENUBACKNAME,PU_CACHE, Cvt_patch_t, 1); shape+=8; shape+=(x*TEXTUREHEIGHT)+y; buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y; for (xx = 0; xx < width; xx++) { for (yy = 0; yy < height; yy++) *(buffer+yy)=*(shape+yy); buffer+=TEXTUREHEIGHT; shape+=TEXTUREHEIGHT; } } //****************************************************************************** // // DrawTMenuBufPic // //****************************************************************************** void DrawTMenuBufPic (int x, int y, int shapenum) { byte *buffer; byte *buf; int xx,yy; int plane; int pixel; byte *shape; pic_t *p; if (MenuBufStarted==false) Error("Called DrawTMenuBufPic without menubuf started\n"); shadingtable=colormap+(25<<8); shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1); p = (pic_t *)shape; if ((x<0) || ((x+(p->width<<2))>=TEXTUREW)) Error ("DrawTMenuBufPic: x is out of range\n"); if ((y<0) || ((y+p->height)>=TEXTUREHEIGHT)) Error ("DrawTMenuBufPic: y is out of range\n"); buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y; for (plane=0; plane<4; plane++,buffer+=TEXTUREHEIGHT) { for (yy = 0; yy < p->height; yy++) { buf=buffer+yy; for (xx = 0; xx < p->width; xx++,buf+=TEXTUREHEIGHT<<2) { pixel = *(buf); pixel = *(shadingtable+pixel); *(buf) = pixel; } } } } //****************************************************************************** // // DrawTMenuBufItem // //****************************************************************************** void DrawTMenuBufItem (int x, int y, int shapenum) { byte *buffer; int cnt; byte *shape; patch_t *p; if (MenuBufStarted==false) Error("Called DrawTMenuBufItem without menubuf started\n"); shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1); p = (patch_t *)shape; shadingtable=colormap+(25<<8); if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW)) Error ("DrawTMenuBufItem: x is out of range\n"); if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT)) Error ("DrawTMenuBufItem: y is out of range\n"); buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT); for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT) TScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape), p->topoffset, buffer); } //****************************************************************************** // // DrawColoredMenuBufItem // //****************************************************************************** void DrawColoredMenuBufItem (int x, int y, int shapenum, int color) { byte *buffer; int cnt; byte *shape; patch_t *p; if (MenuBufStarted==false) Error("Called DrawColoredMenuBufItem without menubuf started\n"); shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1); p = (patch_t *)shape; shadingtable=playermaps[color]+(16<<8); if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW)) Error ("DrawColoredMenuBufItem: x is out of range\n"); if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT)) Error ("DrawColoredMenuBufItem: y is out of range\n"); buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT); for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT) CScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape), p->topoffset, buffer); } //****************************************************************************** // // DrawMenuBufPic // //****************************************************************************** void DrawMenuBufPic (int x, int y, int shapenum) { byte *buffer; byte *buf; int xx,yy; int plane; byte *shape; byte *src; pic_t *p; if (MenuBufStarted==false) Error("Called DrawMenuBufPic without menubuf started\n"); shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1); p = (pic_t *)shape; if ((x<0) || ((x+(p->width<<2))>=TEXTUREW)) Error ("DrawTMenuBufPic: x is out of range\n"); if ((y<0) || ((y+p->height)>=TEXTUREHEIGHT)) Error ("DrawTMenuBufPic: y is out of range\n"); buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y; src=(byte *)&p->data; for (plane=0; plane<4; plane++,buffer+=TEXTUREHEIGHT) { for (yy = 0; yy < p->height; yy++) { buf=buffer+yy; for (xx = 0; xx < p->width; xx++,buf+=TEXTUREHEIGHT<<2) *(buf)=*(src++); } } } //****************************************************************************** // // DrawTMenuBufBox // //****************************************************************************** void DrawTMenuBufBox ( int x, int y, int width, int height ) { byte *buffer; int xx; int yy; int pixel; if (MenuBufStarted==false) Error("Called DrawTMenuBufBox without menubuf started\n"); shadingtable = colormap + ( 25 << 8 ); if ( ( x < 0 ) || ( ( x + width ) >= TEXTUREW ) ) Error ("DrawTMenuBar : x is out of range\n"); if ( ( y < 0 ) || ( y + height ) >= TEXTUREHEIGHT ) Error ("DrawTMenuBar : y is out of range\n"); buffer = ( byte * )menubuf + ( x * TEXTUREHEIGHT ) + y; for ( xx = 0; xx < width; xx++ ) { for ( yy = 0; yy < height; yy++ ) { pixel = *( buffer + yy ); pixel = *( shadingtable + pixel ); *( buffer + yy ) = pixel; } buffer += TEXTUREHEIGHT; } } //****************************************************************************** // // DrawTMenuBufHLine // //****************************************************************************** void DrawTMenuBufHLine (int x, int y, int width, boolean up) { byte *buffer; byte *buf; int xx; int plane; int pixel; int w = width>>2; int ww = w; if ((x<0) || ((x+(width))>=TEXTUREW)) Error ("DrawTMenuBufBox: x is out of range\n"); if (y<0) Error ("DrawTMenuBufBox: y is out of range\n"); buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y; if (up) shadingtable=colormap+(13<<8); else shadingtable=colormap+(25<<8); for (plane = 0; plane < 4; plane++, buffer += TEXTUREHEIGHT) { w = ww; switch (plane) { case 0: if (width % 4) w++; break; case 1: if ((width % 4) > 1) w++; break; case 2: if ((width % 4) > 2) w++; break; } buf = buffer; for (xx = 0; xx < w; xx++, buf += (TEXTUREHEIGHT<<2)) { pixel = *(buf); pixel = *(shadingtable+pixel); *(buf) = pixel; } } } //****************************************************************************** // // DrawTMenuBufVLine // //****************************************************************************** void DrawTMenuBufVLine (int x, int y, int height, boolean up) { byte *buffer; byte *buf; int yy; int pixel; if (x<0) Error ("DrawTMenuBufBox: x is out of range\n"); if ((y<0) || ((y+height)>=TEXTUREHEIGHT)) Error ("DrawTMenuBufBox: y is out of range\n"); buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y; if (up) shadingtable=colormap+(13<<8); else shadingtable=colormap+(25<<8); for (yy = 0; yy < height; yy++) { buf = buffer+yy; pixel = *(buf); pixel = *(shadingtable+pixel); *(buf) = pixel; } } //****************************************************************************** //****************************************************************************** // // STRING ROUTINES // //****************************************************************************** //****************************************************************************** //****************************************************************************** // // DrawMenuBufPropString () // //****************************************************************************** void DrawMenuBufPropString (int px, int py, const char *string) { byte pix; int width,height,ht; byte *source, *dest, *origdest; int ch; if (MenuBufStarted==false) Error("Called DrawMenuBufPropString without menubuf started\n"); ht = CurrentFont->height; dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py; while ((ch = (unsigned char)*string++)!=0) { ch -= 31; width = CurrentFont->width[ch]; source = ((byte *)CurrentFont)+CurrentFont->charofs[ch]; while (width--) { height = ht; while (height--) { pix = *source; if (pix) *dest = pix; source++; dest ++; } PrintX++; origdest+=TEXTUREHEIGHT; dest = origdest; } } } //****************************************************************************** // // DrawMenuBufIString () // //****************************************************************************** void DrawMenuBufIString (int px, int py, const char *string, int color) { byte pix; int width,height,ht; byte *source, *dest, *origdest; int ch; if (MenuBufStarted==false) Error("Called DrawMenuBufPropString without menubuf started\n"); if ( ( color < 0 ) || ( color > 255 ) ) { Error( "Intensity Color out of range\n" ); } ht = IFont->height; dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py; PrintX = px; PrintY = py; while ((ch = (unsigned char)*string++)!=0) { // Tab if ( ch == '\x9' ) { int offset; PrintX -= px; offset = 4 * 5 - PrintX % ( 4 * 5 ); PrintX += offset + px; origdest += offset * TEXTUREHEIGHT; dest = origdest; continue; } ch -= 31; width = IFont->width[ ch ]; source = ( ( byte * )IFont ) + IFont->charofs[ ch ]; while (width--) { height = ht; while (height--) { pix = *source; if ( pix != 0xFE ) { *dest = ( ( byte )intensitytable[ ( pix << 8 ) + color ] ); GetIntensityColor( pix ); } source++; dest ++; } PrintX++; origdest+=TEXTUREHEIGHT; dest = origdest; } } } //****************************************************************************** // // DrawTMenuBufPropString () // // Draws a string at px, py to bufferofs // //****************************************************************************** void DrawTMenuBufPropString (int px, int py, const char *string) { byte pix; int width,height,ht; byte *source, *dest, *origdest; int ch; if (MenuBufStarted==false) Error("Called DrawTMenuBufPropString without menubuf started\n"); ht = CurrentFont->height; dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py; shadingtable=colormap+(StringShade<<8); while ((ch = (unsigned char)*string++)!=0) { ch -= 31; width = CurrentFont->width[ch]; source = ((byte *)CurrentFont)+CurrentFont->charofs[ch]; while (width--) { height = ht; while (height--) { pix = *source; if (pix) { pix = *dest; pix = *(shadingtable+pix); *dest = pix; } source++; dest ++; } PrintX++; origdest+=TEXTUREHEIGHT; dest = origdest; } } } //****************************************************************************** // // MenuBufCPrintLine() - Prints a string centered on the current line and // advances to the next line. Newlines are not supported. // //****************************************************************************** void MenuBufCPrintLine (const char *s) { int w, h; USL_MeasureString (s, &w, &h, CurrentFont); if (w > WindowW) Error("MenuBufCPrintLine() - String exceeds width"); PrintX = WindowX + ((WindowW - w) / 2); DrawMenuBufPropString (PrintX, PrintY, s); PrintY += h; } //****************************************************************************** // // MenuBufCPrint() - Prints a string in the current window. Newlines are // supported. // //****************************************************************************** void MenuBufCPrint (const char *string) { char c, *se, *s; /* !!! FIXME: this is lame. */ if (strlen(string) >= sizeof (strbuf)) { fprintf(stderr, "buffer overflow!\n"); return; } /* prevent writing to literal strings... ( MenubufCPrint("feh"); ) */ strcpy(strbuf, string); s = strbuf; while (*s) { se = s; while ((c = *se) && (c != '\n')) se++; *se = '\0'; MenuBufCPrintLine(s); s = se; if (c) { *se = c; s++; } } } //****************************************************************************** // // MenuBufPrintLine() - Prints a string on the current line and // advances to the next line. Newlines are not supported. // //****************************************************************************** void MenuBufPrintLine (const char *s) { int w, h; USL_MeasureString (s, &w, &h, CurrentFont); if (w > WindowW) Error("MenuBufCPrintLine() - String exceeds width"); PrintX = WindowX; DrawMenuBufPropString (PrintX, PrintY, s); PrintY += h; } //****************************************************************************** // // MenuBufPrint() - Prints a string in the current window. Newlines are // supported. // //****************************************************************************** void MenuBufPrint (const char *string) { char c, *se, *s; strcpy(strbuf, string); s = strbuf; while (*s) { se = s; while ((c = *se) && (c != '\n')) se++; *se = '\0'; MenuBufPrintLine(s); s = se; if (c) { *se = c; s++; } } } //****************************************************************************** // // MenuTBufPrintLine() - Prints a string on the current line and // advances to the next line. Newlines are not supported. // //****************************************************************************** void MenuTBufPrintLine (const char *s, int shade) { int w, h; USL_MeasureString (s, &w, &h, CurrentFont); if (w > WindowW) Error("MenuBufCPrintLine() - String exceeds width"); PrintX = WindowX; StringShade=shade; DrawTMenuBufPropString (PrintX, PrintY, s); PrintY += h; } //****************************************************************************** // // FlipMenuBuf // //****************************************************************************** void FlipMenuBuf ( void ) { int i; int dh; int h; int y; int dy; int time; int flip; if (MenuBufStarted==false) Error("Called FlipMenuBuf without menubuf started\n"); if (!readytoflip) Error("FlipMenuBuf called without SetAlternateMenuBuf beforehand"); readytoflip=0; if (Menuflipspeed<=5) { menubuf=menubuffers[alternatemenubuf]; strcpy(titlestring,menutitles[alternatemenubuf]); RefreshMenuBuf(0); } else { menubuf=menubuffers[alternatemenubuf^1]; strcpy(titlestring,menutitles[alternatemenubuf^1]); time=Menuflipspeed-5; dh=(1024<<8)/time; h=0; dy=((MENUTITLEY*6)<<8)/time; y=0; flip=0; titleyoffset=0; for (i=0; i<time; i+=tics) { PositionMenuBuf(h>>8,NORMALVIEW,true); h+=dh*tics; y+=dy*tics; titleyoffset=y>>8; if ((h>=512<<8) && (flip==0)) { MN_PlayMenuSnd (SD_MENUFLIP); h=1536<<8; dy=-dy; menubuf=menubuffers[alternatemenubuf]; strcpy(titlestring,menutitles[alternatemenubuf]); flip=1; } } } titleyoffset=0; BackgroundDrawn=false; } //****************************************************************************** // // RotatePlane // //****************************************************************************** void RotatePlane ( void ) { SetupMenuBuf(); while (!(Keyboard[0x01])) { RefreshMenuBuf(100); SetAlternateMenuBuf(); ClearMenuBuf(); DrawMenuBufPic (0,0,W_GetNumForName("newg11")); DrawMenuBufItem (0,0,W_GetNumForName("apogee")); FlipMenuBuf(); EraseMenuBufRegion(30,30,30,30); RefreshMenuBuf(100); SetAlternateMenuBuf(); ClearMenuBuf(); FlipMenuBuf(); } ShutdownMenuBuf(); }