/* Hovertank 3-D Source Code * Copyright (C) 1993-2014 Flat Rock Software * * 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. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "HOVERDEF.H" #pragma hdrstop long bytecount,endcount; // for profiling /* ============================================================================ 3 - D DEFINITIONS ============================================================================ */ fixed tileglobal = TILEGLOBAL; fixed focallength = FOCALLENGTH; fixed mindist = MINDIST; int viewheight = VIEWHEIGHT; fixed scale; tilept tile,lasttile, // tile of wall being followed focal, // focal point in tiles left,mid,right; // rightmost tile in view globpt edge,view; int segstart[VIEWHEIGHT], // addline tracks line segment and draws segend[VIEWHEIGHT], segcolor[VIEWHEIGHT]; // only when the color changes #define ADDLINE(a,b,y,c) \ { \ if (a>segend[y]+1) \ { \ if (y>CENTERY) \ DrawLine(segend[y]+1,a-1,y,8); \ else \ DrawLine(segend[y]+1,a-1,y,0); \ } \ DrawLine(a,a,y,0); \ if (a+1<=b) \ DrawLine(a+1,b,y,c); \ segend[y]=b; \ } #define MAXWALLS 100 #define MIDWALL (MAXWALLS/2) walltype walls[MAXWALLS],*leftwall,*rightwall; //========================================================================== // // refresh stuff // // // calculate location of screens in video memory so they have the // maximum possible distance seperating them (for scaling overflow) // #define EXTRALINES (0x10000l/SCREENWIDTH-STATUSLINES-VIEWHEIGHT*3) unsigned screenloc[3]= { ((STATUSLINES+EXTRALINES/4)*SCREENWIDTH)&0xff00, ((STATUSLINES+EXTRALINES/2+VIEWHEIGHT)*SCREENWIDTH)&0xff00, ((STATUSLINES+3*EXTRALINES/4+2*VIEWHEIGHT)*SCREENWIDTH)&0xff00 }; int screenpage,tics; long lasttimecount; #define SHIFTFRAMES 256 int yshift[SHIFTFRAMES]; // screen sliding variables unsigned slideofs; // // rendering stuff // int firstangle,lastangle; fixed prestep; fixed sintable[ANGLES+ANGLES/4],*costable = sintable+(ANGLES/4); fixed viewx,viewy; // the focal point int viewangle; fixed viewsin,viewcos; int zbuffer[VIEWXH+1]; // holds the height of the wall at that point //========================================================================== void DrawLine (int xl, int xh, int y,int color); void DrawWall (walltype *wallptr); void TraceRay (unsigned angle); fixed FixedByFrac (fixed a, fixed b); fixed FixedAdd (fixed a, fixed b); fixed TransformX (fixed gx, fixed gy); int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max); int BackTrace (int finish); void ForwardTrace (void); int TurnClockwise (void); int TurnCounterClockwise (void); void FollowWall (void); void NewScene (void); void BuildTables (void); //========================================================================== /* ================== = = DrawLine = = Must be in write mode 2 with all planes enabled = The bit mask is left set to the end value, so clear it after all lines are = drawn = ================== */ unsigned char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1}; unsigned char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff}; void DrawLine (int xl, int xh, int y,int color) { unsigned dest,xlb,xhb,maskleft,maskright,mid; xlb=xl/8; xhb=xh/8; if (xhVIEWYH) Quit("DrawLine: y>VIEWYH"); maskleft = leftmask[xl&7]; maskright = rightmask[xh&7]; mid = xhb-xlb-1; dest = screenofs+ylookup[y]+xlb; if (xlb==xhb) { // // entire line is in one byte // maskleft&=maskright; asm mov es,[screenseg] asm mov di,[dest] asm mov dx,GC_INDEX asm mov al,GC_BITMASK asm mov ah,[BYTE PTR maskleft] asm out dx,ax // mask off pixels asm mov al,[BYTE PTR color] asm xchg al,[es:di] // load latches and write pixels return; } asm mov es,[screenseg] asm mov di,[dest] asm mov dx,GC_INDEX asm mov bh,[BYTE PTR color] // // draw left side // asm mov al,GC_BITMASK asm mov ah,[BYTE PTR maskleft] asm out dx,ax // mask off pixels asm mov al,bh asm mov bl,[es:di] // load latches asm stosb // // draw middle // asm mov ax,GC_BITMASK + 255*256 asm out dx,ax // no masking asm mov al,bh asm mov cx,[mid] asm rep stosb // // draw right side // asm mov al,GC_BITMASK asm mov ah,[BYTE PTR maskright] asm out dx,ax // mask off pixels asm xchg bh,[es:di] // load latches and write pixels } //========================================================================== /* =================== = = DrawWall = = Special polygon with vertical edges and symetrical top / bottom = Clips horizontally to clipleft/clipright = Clips vertically to VIEWY/VIEWYH = Should only be called if the wall is at least partially visable = ================== */ void DrawWall (walltype *wallptr) { walltype static wall; int static y1l,y1h,y2l,y2h; int i; unsigned leftheight,rightheight; long height,heightstep; int temp,insight,x,y,slope,endfrac,end; int start,ysteps,left,right; wall = *wallptr; i = wall.height1/2; y1l = CENTERY-i; y1h = CENTERY+i; i = wall.height2/2; y2l = CENTERY-i; y2h = CENTERY+i; if (wall.x1>wall.leftclip) wall.leftclip = wall.x1; if (wall.x2>16; height+=heightstep; } // // draw the wall to the line buffer // if (y1l==y2l) { // // rectangle, no slope // if (y1lVIEWYH) y1h=VIEWYH; for (y=y1l;y<=y1h;y++) ADDLINE(wall.leftclip,wall.rightclip,y,wall.color); return; } if (y1l>6; if (end>wall.rightclip) end=wall.rightclip; else if (end