+++ /dev/null
-/* Catacomb Apocalypse Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_DRAW.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-//#define DRAWEACH // draw walls one at a time for debugging\r
-\r
-unsigned highest;\r
-unsigned mostwalls,numwalls;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define PI 3.141592657\r
-#define ANGLEQUAD (ANGLES/4)\r
-\r
-unsigned oldend;\r
-\r
-#define FINEANGLES 3600\r
-\r
-#define MINRATIO 16\r
-\r
-\r
-const unsigned MAXSCALEHEIGHT = (VIEWWIDTH/2);\r
-const unsigned MAXVISHEIGHT = (VIEWHEIGHT/2);\r
-const unsigned BASESCALE = 32;\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-//\r
-// calculate location of screens in video memory so they have the\r
-// maximum possible distance seperating them (for scaling overflow)\r
-//\r
-\r
-unsigned screenloc[3]= {PAGE1START,PAGE2START,PAGE3START};\r
-unsigned freelatch = FREESTART;\r
-\r
-boolean fizzlein;\r
-\r
-long scaleshapecalll;\r
-long scaletablecall;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-long bytecount,endcount; // for profiling\r
-int animframe;\r
-int pixelangle[VIEWWIDTH];\r
-int far finetangent[FINEANGLES+1];\r
-int fineviewangle;\r
-unsigned viewxpix,viewypix;\r
-\r
-/*\r
-============================================================================\r
-\r
- 3 - D DEFINITIONS\r
-\r
-============================================================================\r
-*/\r
-\r
-fixed tileglobal = TILEGLOBAL;\r
-fixed focallength = FOCALLENGTH;\r
-fixed mindist = MINDIST;\r
-int viewheight = VIEWHEIGHT;\r
-fixed scale;\r
-\r
-\r
-tilept tile,lasttile, // tile of wall being followed\r
- focal, // focal point in tiles\r
- left,mid,right; // rightmost tile in view\r
-\r
-globpt edge,view;\r
-\r
-int segstart[VIEWHEIGHT], // addline tracks line segment and draws\r
- segend[VIEWHEIGHT],\r
- segcolor[VIEWHEIGHT]; // only when the color changes\r
-\r
-\r
-walltype walls[MAXWALLS],*leftwall,*rightwall;\r
-\r
-\r
-//==========================================================================\r
-\r
-//\r
-// refresh stuff\r
-//\r
-\r
-int screenpage;\r
-\r
-long lasttimecount;\r
-\r
-//\r
-// rendering stuff\r
-//\r
-\r
-int firstangle,lastangle;\r
-\r
-fixed prestep;\r
-\r
-fixed sintable[ANGLES+ANGLES/4],*costable = sintable+(ANGLES/4);\r
-\r
-fixed viewx,viewy; // the focal point\r
-int viewangle;\r
-fixed viewsin,viewcos;\r
-\r
-int zbuffer[VIEWXH+1]; // holds the height of the wall at that point\r
-\r
-//==========================================================================\r
-\r
-void DrawLine (int xl, int xh, int y,int color);\r
-void DrawWall (walltype *wallptr);\r
-void TraceRay (unsigned angle);\r
-fixed FixedByFrac (fixed a, fixed b);\r
-fixed FixedAdd (void);\r
-fixed TransformX (fixed gx, fixed gy);\r
-int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max);\r
-int BackTrace (int finish);\r
-void ForwardTrace (void);\r
-int TurnClockwise (void);\r
-int TurnCounterClockwise (void);\r
-void FollowWall (void);\r
-\r
-void NewScene (void);\r
-void BuildTables (void);\r
-\r
-//==========================================================================\r
-\r
-\r
-#if 0\r
-/*\r
-==================\r
-=\r
-= DrawLine\r
-=\r
-= Must be in write mode 2 with all planes enabled\r
-= The bit mask is left set to the end value, so clear it after all lines are\r
-= drawn\r
-=\r
-= draws a black dot at the left edge of the line\r
-=\r
-==================\r
-*/\r
-\r
-unsigned static char dotmask[8] = {0x80,0x40,0x20,0x10,8,4,2,1};\r
-unsigned static char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};\r
-unsigned static char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};\r
-\r
-void DrawLine (int xl, int xh, int y,int color)\r
-{\r
- unsigned dest,xlp,xlb,xhb,maskleft,maskright,maskdot,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- if (xh<xl)\r
- Quit("DrawLine: xh<xl");\r
- if (y<VIEWY)\r
- Quit("DrawLine: y<VIEWY");\r
- if (y>VIEWYH)\r
- Quit("DrawLine: y>VIEWYH");\r
-\r
- xlp = xl&7;\r
- maskleft = leftmask[xlp];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- //\r
- // set the GC index register to point to the bit mask register\r
- //\r
- asm mov al,GC_BITMASK\r
- asm mov dx,GC_INDEX\r
- asm out dx,al\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
- asm mov dx,GC_INDEX+1\r
-\r
- asm mov al,[BYTE PTR maskleft]\r
- asm out dx,al // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
- return;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX+1\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,[BYTE PTR maskleft]\r
-asm out dx,al // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-asm inc di\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,255\r
-asm out dx,al // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,[BYTE PTR maskright]\r
-asm out dx,al // mask off pixels\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-void DrawLineDot (int xl, int xh, int y,int color)\r
-{\r
- unsigned dest,xlp,xlb,xhb,maskleft,maskright,maskdot,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- if (xh<xl)\r
- Quit("DrawLine: xh<xl");\r
- if (y<VIEWY)\r
- Quit("DrawLine: y<VIEWY");\r
- if (y>VIEWYH)\r
- Quit("DrawLine: y>VIEWYH");\r
-\r
- xlp = xl&7;\r
- maskdot = dotmask[xlp];\r
- maskleft = leftmask[xlp];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- //\r
- // set the GC index register to point to the bit mask register\r
- //\r
- asm mov al,GC_BITMASK\r
- asm mov dx,GC_INDEX\r
- asm out dx,al\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
- asm mov dx,GC_INDEX+1\r
-\r
- asm mov al,[BYTE PTR maskleft]\r
- asm out dx,al // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
-\r
- //\r
- // write the black dot at the start\r
- //\r
- asm mov al,[BYTE PTR maskdot]\r
- asm out dx,al // mask off pixels\r
-\r
- asm xor al,al\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
-\r
- return;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX+1\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,[BYTE PTR maskleft]\r
-asm out dx,al // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-\r
-//\r
-// write the black dot at the start\r
-//\r
-asm mov al,[BYTE PTR maskdot]\r
-asm out dx,al // mask off pixels\r
-asm xor al,al\r
-asm xchg al,[es:di] // load latches and write pixels\r
-asm inc di\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,255\r
-asm out dx,al // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,[BYTE PTR maskright]\r
-asm out dx,al // mask off pixels\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-long wallscalesource;\r
-\r
-#ifdef DRAWEACH\r
-/*\r
-====================\r
-=\r
-= ScaleOneWall\r
-=\r
-====================\r
-*/\r
-\r
-void near ScaleOneWall (int xl, int xh)\r
-{\r
- int x,pixwidth,height;\r
-\r
- *(((unsigned *)&wallscalesource)+1) = wallseg[xl];\r
-\r
- for (x=xl;x<=xh;x+=pixwidth)\r
- {\r
- height = wallheight[x];\r
- pixwidth = wallwidth[x];\r
- (unsigned)wallscalesource = wallofs[x];\r
-\r
- *(((unsigned *)&scaletablecall)+1) = (unsigned)scaledirectory[height];\r
- (unsigned)scaletablecall = scaledirectory[height]->codeofs[0];\r
-\r
- //\r
- // scale a byte wide strip of wall\r
- //\r
- asm mov bx,[x]\r
- asm mov di,bx\r
- asm shr di,1\r
- asm shr di,1\r
- asm shr di,1 // X in bytes\r
- asm add di,[bufferofs]\r
- asm and bx,7\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm add bx,[pixwidth] // bx = pixel*8+pixwidth-1\r
- asm dec bx\r
- asm mov al,BYTE PTR [bitmasks1+bx]\r
- asm mov dx,GC_INDEX+1\r
- asm out dx,al // set bit mask register\r
- asm mov es,[screenseg]\r
- asm lds si,[wallscalesource]\r
- asm call [DWORD PTR ss:scaletablecall] // scale the line of pixels\r
-\r
- asm mov al,BYTE PTR [ss:bitmasks2+bx]\r
- asm or al,al\r
- asm jz nosecond\r
-\r
- //\r
- // draw a second byte for vertical strips that cross two bytes\r
- //\r
- asm inc di\r
- asm out dx,al // set bit mask register\r
- asm call [DWORD PTR ss:scaletablecall] // scale the line of pixels\r
- nosecond:\r
- asm mov ax,ss\r
- asm mov ds,ax\r
- }\r
-}\r
-\r
-#endif\r
-\r
-char wall_anim_pos[NUMFLOORS];\r
-\r
-// EAST / WEST WALLS\r
-//\r
-int far walllight1[NUMFLOORS] = {0,\r
-\r
- 0,//CRYSTAL1LIGHTPIC,\r
- 0,//EGYPT1LIGHTPIC,\r
- EGYPT2LIGHTPIC,\r
- EGYPT3LIGHTPIC,\r
-\r
- FIREWALL1PIC,\r
- FIREWALL2PIC,\r
- FIREWALL3PIC,\r
- FIREWALL4PIC,\r
-\r
-\r
- NEMESISPIC,\r
-\r
- ALTARLEFTPIC,\r
- ALTARRIGHTPIC,\r
-\r
- TEMPLEWALLLIGHTPIC,\r
-\r
- TORCHWALL1PIC,\r
- TORCHWALL2PIC,\r
-\r
- BRNBRKLIGHTPIC,\r
- BRNBRKEMLIGHTPIC,\r
-\r
- IRONGATEPIC,\r
-\r
- BRNFLGLIGHTPIC,\r
- BRNFLGWINDOWLIGHTPIC,\r
- BRNFLGVINELIGHTPIC,\r
- BRNFLGDMGLIGHTPIC,\r
-\r
- SPACEDMG1LIGHTPIC,\r
- SPACEDMG2LIGHTPIC,\r
-\r
- SPACE1LIGHTPIC,\r
- SPACE2LIGHTPIC,\r
- SPACE3LIGHTPIC,\r
- SPACE4LIGHTPIC,\r
-\r
- SPACE5LIGHTPIC,\r
- SPACE6LIGHTPIC,\r
- SPACE7LIGHTPIC,\r
- SPACE8LIGHTPIC,\r
-\r
- 0,//SPACE9LIGHTPIC,\r
- 0,//SPACEDMG9LIGHTPIC,\r
- SPACE10LIGHTPIC,\r
- RUSTDOORLIGHTPIC,\r
-\r
- SPACE11LIGHTPIC,\r
- SPACE12LIGHTPIC,\r
- SPACE13LIGHTPIC,\r
- SPACE14LIGHTPIC,\r
-\r
- SPACEDMG5LIGHTPIC,\r
- SPACEDMG6LIGHTPIC,\r
-\r
- TAP1PIC,\r
- TAP2PIC,\r
- ENDPIC,\r
- 0,//SIRONLIGHTPIC,\r
-\r
- SPCDOOR1LIGHTPIC,\r
- SPCDOOR2LIGHTPIC,\r
- SPCDOOR3LIGHTPIC,\r
- SPCDOOR4LIGHTPIC,\r
-\r
- COLUMNSLIGHTPIC,\r
-\r
- DEMONSTATUELIGHTPIC,\r
-\r
- 0,//CRYSTALBWALL1LIGHTPIC,\r
-\r
- 0,//SRUSTLIGHTPIC,\r
-\r
- TROLLSTATUELIGHTPIC,\r
-\r
- BRNDMGVINELIGHTPIC,\r
- TAP3PIC,\r
- HORNDOORPIC,\r
- RUNEDOORPIC,\r
-\r
- EXP_WALL_1PIC,\r
- EXP_WALL_2PIC,\r
- EXP_WALL_3PIC,\r
- WATER_EXP_WALL_1PIC,\r
- WATER_EXP_WALL_2PIC,\r
- WATER_EXP_WALL_3PIC,\r
-\r
- IRONDMGLIGHTPIC,\r
- IRONLIGHTPIC,\r
- 0,\r
- TROLLBLOODYLIGHTPIC,\r
- TROLLLIGHTPIC,\r
-\r
- 0, // INVISIBLE WALL\r
-\r
- STONEDOORLIGHTPIC,\r
- 0,\r
-\r
- IRONWTR1LIGHTPIC,\r
- IRONWTR2LIGHTPIC,\r
- IRONWTR3LIGHTPIC,\r
-\r
- RUSTWTR1LIGHTPIC,\r
- RUSTWTR2LIGHTPIC,\r
- RUSTWTR3LIGHTPIC,\r
-\r
- CEMETARYLIGHTPIC,\r
- 0, // STAIRDWNLIGHTPIC,\r
-\r
- WGRATE1LIGHTPIC,\r
- WGRATE2LIGHTPIC,\r
- WGRATE3LIGHTPIC,\r
-\r
- MAS_WIN_LIGHTPIC,\r
- MAS_DOOR_LIGHTPIC,\r
- MAS_VINE1_LIGHTPIC,\r
- MAS_VINE2_LIGHTPIC,\r
-\r
- // Start of non-solid walls\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
-\r
- // solid walls\r
- SGRATEPIC,\r
-};\r
-\r
-// NORTH / SOUTH WALLS\r
-//\r
-int far walldark1[NUMFLOORS] = {0,\r
-\r
- 0,//CRYSTAL1DARKPIC,\r
- 0,//EGYPT1DARKPIC,\r
- EGYPT2DARKPIC,\r
- EGYPT3DARKPIC,\r
-\r
- FIREWALL1PIC,\r
- FIREWALL2PIC,\r
- FIREWALL3PIC,\r
- FIREWALL4PIC,\r
-\r
- NEMESISPIC,\r
-\r
- ALTARLEFTPIC,\r
- ALTARRIGHTPIC,\r
-\r
- TEMPLEWALLDARKPIC,\r
-\r
- TORCHWALL1PIC,\r
- TORCHWALL2PIC,\r
-\r
- BRNBRKDARKPIC,\r
- BRNBRKEMDARKPIC,\r
-\r
- IRONGATEPIC,\r
-\r
- BRNFLGDARKPIC,\r
- BRNFLGWINDOWDARKPIC,\r
- BRNFLGVINEDARKPIC,\r
- BRNFLGDMGDARKPIC,\r
-\r
- SPACEDMG1DARKPIC,\r
- SPACEDMG2DARKPIC,\r
-\r
- SPACE1DARKPIC,\r
- SPACE2DARKPIC,\r
- SPACE3DARKPIC,\r
- SPACE4DARKPIC,\r
-\r
- SPACE5DARKPIC,\r
- SPACE6DARKPIC,\r
- SPACE7DARKPIC,\r
- SPACE8DARKPIC,\r
-\r
- 0,//SPACE9DARKPIC,\r
- 0,//SPACEDMG9DARKPIC,\r
- SPACE10DARKPIC,\r
- RUSTDOORDARKPIC,\r
-\r
- SPACE11DARKPIC,\r
- SPACE12DARKPIC,\r
- SPACE13DARKPIC,\r
- SPACE14DARKPIC,\r
-\r
- SPACEDMG5DARKPIC,\r
- SPACEDMG6DARKPIC,\r
-\r
- TAP1PIC,\r
- TAP2PIC,\r
- ENDPIC,\r
- 0,//SIRONDARKPIC,\r
-\r
- SPCDOOR1DARKPIC,\r
- SPCDOOR2DARKPIC,\r
- SPCDOOR3DARKPIC,\r
- SPCDOOR4DARKPIC,\r
-\r
- COLUMNSDARKPIC,\r
-\r
- DEMONSTATUEDARKPIC,\r
-\r
- 0,//CRYSTALBWALL1DARKPIC,\r
-\r
- 0,//SRUSTDARKPIC,\r
-\r
- TROLLSTATUEDARKPIC,\r
-\r
- BRNDMGVINEDARKPIC,\r
- TAP3PIC,\r
- HORNDOORPIC,\r
- RUNEDOORPIC,\r
-\r
- EXP_WALL_1PIC,\r
- EXP_WALL_2PIC,\r
- EXP_WALL_3PIC,\r
-\r
- WATER_EXP_WALL_1PIC,\r
- WATER_EXP_WALL_2PIC,\r
- WATER_EXP_WALL_3PIC,\r
-\r
- IRONDMGDARKPIC,\r
- IRONDARKPIC,\r
- 0,\r
- TROLLBLOODYDARKPIC,\r
-\r
- TROLLDARKPIC,\r
-\r
- 0, // INVISIBLE WALL\r
-\r
- STONEDOORDARKPIC,\r
- 0,\r
-\r
- IRONWTR1DARKPIC,\r
- IRONWTR2DARKPIC,\r
- IRONWTR3DARKPIC,\r
-\r
- RUSTWTR1DARKPIC,\r
- RUSTWTR2DARKPIC,\r
- RUSTWTR3DARKPIC,\r
-\r
- CEMETARYDARKPIC,\r
- 0,\r
-\r
- WGRATE1DARKPIC,\r
- WGRATE2DARKPIC,\r
- WGRATE3DARKPIC,\r
-\r
- MAS_WIN_DARKPIC,\r
- MAS_DOOR_DARKPIC,\r
- MAS_VINE1_DARKPIC,\r
- MAS_VINE2_DARKPIC,\r
-\r
- // Start of non-solid walls\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
-\r
- // solid walls\r
- SGRATEPIC,\r
-};\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawVWall\r
-=\r
-= Draws a wall by vertical segments, for texture mapping!\r
-=\r
-= wallptr->side is true for east/west walls (constant x)\r
-=\r
-= fracheight and fracstep are 16.16 bit fractions\r
-=\r
-=====================\r
-*/\r
-\r
-void DrawVWall (walltype *wallptr)\r
-{\r
- int x,i;\r
- unsigned source;\r
- unsigned width,sourceint;\r
- unsigned wallpic,wallpicseg;\r
- unsigned skip;\r
- long fracheight,fracstep,longheightchange;\r
- unsigned height;\r
- int heightchange;\r
- unsigned slope,distance;\r
- int traceangle,angle;\r
- int mapadd;\r
- unsigned lastpix,lastsource,lastwidth;\r
-\r
- if (wallptr->rightclip < wallptr->leftclip)\r
- Quit ("DrawVWall: Right < Left");\r
-\r
-//\r
-// setup for height calculation\r
-//\r
- wallptr->height1 >>= 1;\r
- wallptr->height2 >>= 1;\r
- wallptr->planecoord>>=10; // remove non significant bits\r
-\r
- width = wallptr->x2 - wallptr->x1;\r
- if (width)\r
- {\r
- heightchange = wallptr->height2 - wallptr->height1;\r
- asm mov ax,[heightchange]\r
- asm mov WORD PTR [longheightchange+2],ax\r
- asm mov WORD PTR [longheightchange],0 // avoid long shift by 16\r
- fracstep = longheightchange/width;\r
- }\r
-\r
- fracheight = ((long)wallptr->height1<<16)+0x8000;\r
- skip = wallptr->leftclip - wallptr->x1;\r
- if (skip)\r
- fracheight += fracstep*skip;\r
-\r
-//\r
-// setup for texture mapping\r
-//\r
-// mapadd is 64*64 (to keep source positive) + the origin wall intercept\r
-// distance has 6 unit bits, and 6 frac bits\r
-// traceangle is the center view angle in FINEANGLES, moved to be in\r
-// the +-90 degree range (to thew right of origin)\r
-//\r
- traceangle = fineviewangle;\r
- //\r
- // find wall picture to map from\r
- //\r
- if (wallptr->side)\r
- { // east or west wall\r
-\r
- wallpic = walllight1[wallptr->color+wall_anim_pos[wallptr->color]];\r
- if (wallptr->planecoord < viewxpix)\r
- {\r
- distance = viewxpix-wallptr->planecoord;\r
- traceangle -= FINEANGLES/2;\r
- mapadd = (64-viewypix&63); // the pixel spot of the origin\r
- }\r
- else\r
- {\r
- distance = wallptr->planecoord-viewxpix;\r
- // traceangle is correct\r
- mapadd = viewypix&63; // the pixel spot of the origin\r
- }\r
- }\r
- else\r
- { // north or south wall\r
-\r
- wallpic = walldark1[wallptr->color+wall_anim_pos[wallptr->color]];\r
- if (wallptr->planecoord < viewypix)\r
- {\r
- distance = viewypix-wallptr->planecoord;\r
- traceangle -= FINEANGLES/4;\r
- mapadd = viewxpix&63; // the pixel spot of the origin\r
- }\r
- else\r
- {\r
- distance = wallptr->planecoord-viewypix;\r
- traceangle -= FINEANGLES*3/4;\r
- mapadd = (64-viewxpix&63); // the pixel spot of the origin\r
- }\r
- }\r
-\r
- mapadd = 64*64-mapadd; // make sure it stays positive\r
-\r
- wallpicseg = (unsigned)walldirectory[wallpic-FIRSTWALLPIC];\r
- if (traceangle > FINEANGLES/2)\r
- traceangle -= FINEANGLES;\r
-\r
-//\r
-// calculate everything\r
-//\r
-// IMPORTANT! This loop is executed around 5000 times / second!\r
-//\r
- lastpix = lastsource = (unsigned)-1;\r
-\r
- for (x = wallptr->leftclip ; x <= wallptr->rightclip ; x++)\r
- {\r
- //\r
- // height\r
- //\r
- asm mov ax,WORD PTR [fracheight]\r
- asm mov dx,WORD PTR [fracheight+2]\r
- asm mov cx,dx\r
- asm add ax,WORD PTR [fracstep]\r
- asm adc dx,WORD PTR [fracstep+2]\r
- asm mov WORD PTR [fracheight],ax\r
- asm mov WORD PTR [fracheight+2],dx\r
- asm mov bx,[x]\r
- asm shl bx,1\r
- asm cmp cx,MAXSCALEHEIGHT\r
- asm jbe storeheight\r
- asm mov cx,MAXSCALEHEIGHT\r
-storeheight:\r
- asm mov WORD PTR [wallheight+bx],cx\r
- asm mov WORD PTR [zbuffer+bx],cx\r
-\r
-// height = fracheight>>16;\r
-// fracheight += fracstep;\r
-// if (height > MAXSCALEHEIGHT)\r
-// height = MAXSCALEHEIGHT;\r
-// wallheight[x] = zbuffer[x] = height;\r
-\r
- //\r
- // texture map\r
- //\r
- angle = pixelangle[x]+traceangle;\r
- if (angle<0)\r
- angle+=FINEANGLES;\r
-\r
- slope = finetangent[angle];\r
-\r
-//\r
-// distance is an unsigned 6.6 bit number (12 pixel bits)\r
-// slope is a signed 5.10 bit number\r
-// result is a signed 11.16 bit number\r
-//\r
-\r
-#if 0\r
- source = distance*slope;\r
- source >>=20;\r
-\r
- source += mapadd;\r
- source &= 63; // mask off the unused units\r
- source = 63-source;\r
- source <<= 6; // multiply by 64 for offset into pic\r
-#endif\r
- asm mov ax,[distance]\r
- asm imul [slope] // ax is the source pixel\r
- asm mov al,ah\r
- asm shr al,1\r
- asm shr al,1 // low 6 bits is now pixel number\r
- asm add ax,[mapadd]\r
- asm and ax,63\r
- asm mov dx,63\r
- asm sub dx,ax // otherwise it is backwards\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1 // *64 to index into shape\r
- asm mov [source],dx\r
-\r
- if (source != lastsource)\r
- {\r
- if (lastpix != (unsigned)-1)\r
- {\r
- wallofs[lastpix] = lastsource;\r
- wallseg[lastpix] = wallpicseg;\r
- wallwidth[lastpix] = lastwidth;\r
- }\r
- lastpix = x;\r
- lastsource = source;\r
- lastwidth = 1;\r
- }\r
- else\r
- lastwidth++; // optimized draw, same map as last one\r
- }\r
- wallofs[lastpix] = lastsource;\r
- wallseg[lastpix] = wallpicseg;\r
- wallwidth[lastpix] = lastwidth;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= TraceRay\r
-=\r
-= Used to find the left and rightmost tile in the view area to be traced from\r
-= Follows a ray of the given angle from viewx,viewy in the global map until\r
-= it hits a solid tile\r
-= sets:\r
-= tile.x,tile.y : tile coordinates of contacted tile\r
-= tilecolor : solid tile's color\r
-=\r
-==================\r
-*/\r
-\r
-int tilecolor;\r
-\r
-void TraceRay (unsigned angle)\r
-{\r
- long tracex,tracey,tracexstep,traceystep,searchx,searchy;\r
- fixed fixtemp;\r
- int otx,oty,searchsteps;\r
-\r
- tracexstep = costable[angle];\r
- traceystep = sintable[angle];\r
-\r
-//\r
-// advance point so it is even with the view plane before we start checking\r
-//\r
- fixtemp = FixedByFrac(prestep,tracexstep);\r
- tracex = viewx+fixtemp;\r
- fixtemp = FixedByFrac(prestep,traceystep);\r
- tracey = viewy-fixtemp;\r
-\r
- tile.x = tracex>>TILESHIFT; // starting point in tiles\r
- tile.y = tracey>>TILESHIFT;\r
-\r
-\r
- if (tracexstep<0) // use 2's complement, not signed magnitude\r
- tracexstep = -(tracexstep&0x7fffffff);\r
-\r
- if (traceystep<0) // use 2's complement, not signed magnitude\r
- traceystep = -(traceystep&0x7fffffff);\r
-\r
-//\r
-// we assume viewx,viewy is not inside a solid tile, so go ahead one step\r
-//\r
-\r
- do // until a solid tile is hit\r
- {\r
- otx = tile.x;\r
- oty = tile.y;\r
- spotvis[otx][oty] = true;\r
- tracex += tracexstep;\r
- tracey -= traceystep;\r
- tile.x = tracex>>TILESHIFT;\r
- tile.y = tracey>>TILESHIFT;\r
-\r
- if (tile.x!=otx && tile.y!=oty && (tilemap[otx][tile.y] || tilemap[tile.x][oty]) )\r
- {\r
- //\r
- // trace crossed two solid tiles, so do a binary search along the line\r
- // to find a spot where only one tile edge is crossed\r
- //\r
- searchsteps = 0;\r
- searchx = tracexstep;\r
- searchy = traceystep;\r
- do\r
- {\r
- searchx/=2;\r
- searchy/=2;\r
- if (tile.x!=otx && tile.y!=oty)\r
- {\r
- // still too far\r
- tracex -= searchx;\r
- tracey += searchy;\r
- }\r
- else\r
- {\r
- // not far enough, no tiles crossed\r
- tracex += searchx;\r
- tracey -= searchy;\r
- }\r
-\r
- //\r
- // if it is REAL close, go for the most clockwise intersection\r
- //\r
- if (++searchsteps == 16)\r
- {\r
- tracex = (long)otx<<TILESHIFT;\r
- tracey = (long)oty<<TILESHIFT;\r
- if (tracexstep>0)\r
- {\r
- if (traceystep<0)\r
- {\r
- tracex += TILEGLOBAL-1;\r
- tracey += TILEGLOBAL;\r
- }\r
- else\r
- {\r
- tracex += TILEGLOBAL;\r
- }\r
- }\r
- else\r
- {\r
- if (traceystep<0)\r
- {\r
- tracex --;\r
- tracey += TILEGLOBAL-1;\r
- }\r
- else\r
- {\r
- tracey --;\r
- }\r
- }\r
- }\r
-\r
- tile.x = tracex>>TILESHIFT;\r
- tile.y = tracey>>TILESHIFT;\r
-\r
- } while (( tile.x!=otx && tile.y!=oty) || (tile.x==otx && tile.y==oty) );\r
- }\r
- } while (!(tilecolor = tilemap[tile.x][tile.y]) );\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= FixedByFrac\r
-=\r
-= multiply a 16/16 bit, 2's complement fixed point number by a 16 bit\r
-= fraction, passed as a signed magnitude 32 bit number\r
-=\r
-========================\r
-*/\r
-\r
-#pragma warn -rvl // I stick the return value in with ASMs\r
-\r
-fixed FixedByFrac (fixed a, fixed b)\r
-{\r
- fixed value;\r
-\r
-//\r
-// setup\r
-//\r
-asm mov si,[WORD PTR b+2] // sign of result = sign of fraction\r
-\r
-asm mov ax,[WORD PTR a]\r
-asm mov cx,[WORD PTR a+2]\r
-\r
-asm or cx,cx\r
-asm jns aok: // negative?\r
-asm not ax\r
-asm not cx\r
-asm add ax,1\r
-asm adc cx,0\r
-asm xor si,0x8000 // toggle sign of result\r
-aok:\r
-\r
-//\r
-// multiply cx:ax by bx\r
-//\r
-asm mov bx,[WORD PTR b]\r
-asm mul bx // fraction*fraction\r
-asm mov di,dx // di is low word of result\r
-asm mov ax,cx //\r
-asm mul bx // units*fraction\r
-asm add ax,di\r
-asm adc dx,0\r
-\r
-//\r
-// put result dx:ax in 2's complement\r
-//\r
-asm test si,0x8000 // is the result negative?\r
-asm jz ansok:\r
-asm not ax\r
-asm not dx\r
-asm add ax,1\r
-asm adc dx,0\r
-\r
-ansok:;\r
-\r
-}\r
-\r
-#pragma warn +rvl\r
-\r
-#if 0\r
-/*\r
-=========================\r
-=\r
-= FixedAdd\r
-=\r
-= add two 16 bit fixed point numbers\r
-= to subtract, invert the sign of B before invoking\r
-=\r
-=========================\r
-*/\r
-\r
-fixed FixedAdd (fixed a, fixed b)\r
-{\r
- fixed value;\r
-\r
-asm mov ax,[WORD PTR a]\r
-asm mov dx,[WORD PTR a+2]\r
-\r
-asm mov bx,[WORD PTR b]\r
-asm mov cx,[WORD PTR b+2]\r
-\r
-asm or dx,dx\r
-asm jns aok: // negative?\r
-asm and dx,0x7fff\r
-asm not ax // convert a from signed magnitude to 2's compl\r
-asm not dx\r
-asm add ax,1\r
-asm adc dx,0\r
-aok:\r
-\r
-asm or cx,cx\r
-asm jns bok: // negative?\r
-asm and cx,0x7fff\r
-asm not bx // convert b from signed magnitude to 2's compl\r
-asm not cx\r
-asm add bx,1\r
-asm adc cx,0\r
-bok:\r
-\r
-asm add ax,bx // perform the addition\r
-asm adc dx,cx\r
-asm jns done\r
-\r
-asm and dx,0x7fff // value was negative\r
-asm not ax // back to signed magnitude\r
-asm not dx\r
-asm add ax,1\r
-asm adc dx,0\r
-\r
-done:\r
-\r
-asm mov [WORD PTR value],ax\r
-asm mov [WORD PTR value+2],dx\r
-\r
- return value;\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= TransformPoint\r
-=\r
-= Takes paramaters:\r
-= gx,gy : globalx/globaly of point\r
-=\r
-= globals:\r
-= viewx,viewy : point of view\r
-= viewcos,viewsin : sin/cos of viewangle\r
-=\r
-=\r
-= defines:\r
-= CENTERX : pixel location of center of view window\r
-= TILEGLOBAL : size of one\r
-= FOCALLENGTH : distance behind viewx/y for center of projection\r
-= scale : conversion from global value to screen value\r
-=\r
-= returns:\r
-= screenx,screenheight: projected edge location and size\r
-=\r
-========================\r
-*/\r
-\r
-void TransformPoint (fixed gx, fixed gy, int *screenx, unsigned *screenheight)\r
-{\r
- int ratio;\r
- fixed gxt,gyt,nx,ny;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = gx-viewx;\r
- gy = gy-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
- nx = gxt-gyt;\r
-\r
-//\r
-// calculate newy\r
-//\r
- gxt = FixedByFrac(gx,viewsin);\r
- gyt = FixedByFrac(gy,viewcos);\r
- ny = gyt+gxt;\r
-\r
-//\r
-// calculate perspective ratio\r
-//\r
- if (nx<0)\r
- nx = 0;\r
-\r
- ratio = nx*scale/FOCALLENGTH;\r
-\r
- if (ratio<=MINRATIO)\r
- ratio = MINRATIO;\r
-\r
- *screenx = CENTERX + ny/ratio;\r
-\r
- *screenheight = TILEGLOBAL/ratio;\r
-\r
-}\r
-\r
-\r
-//\r
-// transform actor\r
-//\r
-void TransformActor (objtype *ob)\r
-{\r
- int ratio;\r
- fixed gx,gy,gxt,gyt,nx,ny;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = ob->x-viewx;\r
- gy = ob->y-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
- nx = gxt-gyt-ob->size;\r
-\r
-//\r
-// calculate newy\r
-//\r
- gxt = FixedByFrac(gx,viewsin);\r
- gyt = FixedByFrac(gy,viewcos);\r
- ny = gyt+gxt;\r
-\r
-//\r
-// calculate perspective ratio\r
-//\r
- if (nx<0)\r
- nx = 0;\r
-\r
- ratio = nx*scale/FOCALLENGTH;\r
-\r
- if (ratio<=MINRATIO)\r
- ratio = MINRATIO;\r
-\r
- ob->viewx = CENTERX + ny/ratio;\r
-\r
- ob->viewheight = TILEGLOBAL/ratio;\r
-}\r
-\r
-//==========================================================================\r
-\r
-fixed TransformX (fixed gx, fixed gy)\r
-{\r
- int ratio;\r
- fixed gxt,gyt,nx,ny;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = gx-viewx;\r
- gy = gy-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
-\r
- return gxt-gyt;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= BuildTables\r
-=\r
-= Calculates:\r
-=\r
-= scale projection constant\r
-= sintable/costable overlapping fractional tables\r
-= firstangle/lastangle angles from focalpoint to left/right view edges\r
-= prestep distance from focal point before checking for tiles\r
-=\r
-==================\r
-*/\r
-\r
-void BuildTables (void)\r
-{\r
- int i;\r
- long intang;\r
- long x;\r
- float angle,anglestep,radtoint;\r
- double tang;\r
- fixed value;\r
-\r
-//\r
-// calculate the angle offset from view angle of each pixel's ray\r
-//\r
- radtoint = (float)FINEANGLES/2/PI;\r
- for (i=0;i<VIEWWIDTH/2;i++)\r
- {\r
- // start 1/2 pixel over, so viewangle bisects two middle pixels\r
- x = (TILEGLOBAL*i+TILEGLOBAL/2)/VIEWWIDTH;\r
- tang = (float)x/(FOCALLENGTH+MINDIST);\r
- angle = atan(tang);\r
- intang = angle*radtoint;\r
- pixelangle[VIEWWIDTH/2-1-i] = intang;\r
- pixelangle[VIEWWIDTH/2+i] = -intang;\r
- }\r
-\r
-//\r
-// calculate fine tangents\r
-// 1 sign bit, 5 units (clipped to), 10 fracs\r
-//\r
-#define MININT (-MAXINT)\r
-\r
- for (i=0;i<FINEANGLES/4;i++)\r
- {\r
- intang = tan(i/radtoint)*(1l<<10);\r
-\r
- //\r
- // if the tangent is not reprentable in this many bits, bound the\r
- // units part ONLY\r
- //\r
- if (intang>MAXINT)\r
- intang = 0x8f00 | (intang & 0xff);\r
- else if (intang<MININT)\r
- intang = 0xff00 | (intang & 0xff);\r
-\r
- finetangent[i] = intang;\r
-// finetangent[FINEANGLES/2+i] = intang;\r
-// finetangent[FINEANGLES/2-i-1] = -intang;\r
- finetangent[FINEANGLES-i-1] = -intang;\r
- }\r
-\r
-//\r
-// calculate scale value so one tile at mindist allmost fills the view horizontally\r
-//\r
- scale = GLOBAL1/VIEWWIDTH;\r
- scale *= focallength;\r
- scale /= (focallength+mindist);\r
-\r
-//\r
-// costable overlays sintable with a quarter phase shift\r
-// ANGLES is assumed to be divisable by four\r
-//\r
-// The low word of the value is the fraction, the high bit is the sign bit,\r
-// bits 16-30 should be 0\r
-//\r
-\r
- angle = 0;\r
- anglestep = PI/2/ANGLEQUAD;\r
- for (i=0;i<=ANGLEQUAD;i++)\r
- {\r
- value=GLOBAL1*sin(angle);\r
- sintable[i]=\r
- sintable[i+ANGLES]=\r
- sintable[ANGLES/2-i] = value;\r
- sintable[ANGLES-i]=\r
- sintable[ANGLES/2+i] = value | 0x80000000l;\r
- angle += anglestep;\r
- }\r
-\r
-//\r
-// figure trace angles for first and last pixel on screen\r
-//\r
- angle = atan((float)VIEWWIDTH/2*scale/FOCALLENGTH);\r
- angle *= ANGLES/(PI*2);\r
-\r
- intang = (int)angle+1;\r
- firstangle = intang;\r
- lastangle = -intang;\r
-\r
- prestep = GLOBAL1*((float)FOCALLENGTH/costable[firstangle]);\r
-\r
-//\r
-// misc stuff\r
-//\r
- walls[0].x2 = VIEWX-1;\r
- walls[0].height2 = 32000;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= ClearScreen\r
-=\r
-=====================\r
-*/\r
-\r
-void ClearScreen (void)\r
-{\r
- unsigned topcolor=*skycolor, bottomcolor=*groundcolor;\r
- unsigned topimage=topcolor&0xf0,bottomimage=bottomcolor&0xf0;\r
- unsigned pfoffset=0;\r
-\r
-\r
-#if USE_STRIPS\r
- if (topimage == 0x20) // special code for lightning\r
- topimage = topcolor = 0;\r
-\r
-// Manually wipe screen with solid color.\r
-// If BOTH sky and ground are 'images' don't manually clear it!\r
-//\r
- if ((!topimage) || (!bottomimage))\r
- {\r
-#endif\r
-\r
- //\r
- // clear the screen\r
- //\r
-asm mov dx,GC_INDEX\r
-asm mov ax,GC_MODE + 256*2 // read mode 0, write mode 2\r
-asm out dx,ax\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax\r
-\r
-//asm mov dx,40-VIEWWIDTH/8 // dx = modulo\r
-asm mov bl,VIEWWIDTH/16\r
-asm mov bh,CENTERY+1\r
-\r
-asm mov ax,topcolor\r
-asm mov es,[screenseg]\r
-asm mov di,[bufferofs]\r
-asm add di,((SCREENWIDTH*VIEWY)+(VIEWX/8))\r
-\r
-toploop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm stosb\r
-//asm add di,dx // no need to add "0" modulo\r
-asm dec bh\r
-asm jnz toploop\r
-\r
-asm mov bh,CENTERY+1\r
-asm mov ax,bottomcolor\r
-\r
-bottomloop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm stosb\r
-//asm add di,dx // no need to add "0" modulo\r
-asm dec bh\r
-asm jnz bottomloop\r
-\r
-#if USE_STRIPS\r
- }\r
-\r
-\r
-//\r
-// code to test parallax turning\r
-//\r
-\r
- if (topimage)\r
- {\r
- topimage -= 16;\r
- pfoffset = LONG_PERCENTAGE(3200,359,(359-player->angle),12);\r
- while (pfoffset >= 640)\r
- pfoffset -= 640;\r
- LatchDrawPicStrip(0,0,SKY1PIC+topimage,pfoffset+8);\r
- }\r
-\r
- if (bottomimage)\r
- {\r
-//// pfoffset = LONG_PERCENTAGE(3200,359,(359-player->angle),12)+320;\r
-// pfoffset += 320;\r
-// while (pfoffset >= 640)\r
-// pfoffset -= 640;\r
-// LatchDrawPicStrip(0,64,SKY1PIC+topimage,pfoffset+8);\r
- bottomimage -= 16;\r
- LatchDrawPic(0,64,GND1PIC+bottomimage);\r
- }\r
-#endif\r
-\r
-\r
-asm mov dx,GC_INDEX\r
-asm mov ax,GC_MODE + 256*10 // read mode 1, write mode 2\r
-asm out dx,ax\r
-asm mov al,GC_BITMASK\r
-asm out dx,al\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawWallList\r
-=\r
-= Clips and draws all the walls traced this refresh\r
-=\r
-=====================\r
-*/\r
-\r
-void DrawWallList (void)\r
-{\r
- int i,leftx,newleft,rightclip;\r
- walltype *wall, *check;\r
-\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm mov di,OFFSET wallwidth\r
-asm xor ax,ax\r
-asm mov cx,VIEWWIDTH/2\r
-asm rep stosw\r
-\r
- ClearScreen ();\r
-\r
- rightwall->x1 = VIEWXH+1;\r
- rightwall->height1 = 32000;\r
- (rightwall+1)->x1 = 32000;\r
-\r
- leftx = -1;\r
-\r
- for (wall=&walls[1];wall<rightwall && leftx<=VIEWXH ;wall++)\r
- {\r
- if (leftx >= wall->x2)\r
- continue;\r
-\r
- rightclip = wall->x2;\r
-\r
- check = wall+1;\r
- while (check->x1 <= rightclip && check->height1 >= wall->height2)\r
- {\r
- rightclip = check->x1-1;\r
- check++;\r
- }\r
-\r
- if (rightclip>VIEWXH)\r
- rightclip=VIEWXH;\r
-\r
- if (leftx < wall->x1 - 1)\r
- newleft = wall->x1-1; // there was black space between walls\r
- else\r
- newleft = leftx;\r
-\r
- if (rightclip > newleft)\r
- {\r
- wall->leftclip = newleft+1;\r
- wall->rightclip = rightclip;\r
- DrawVWall (wall);\r
- leftx = rightclip;\r
- }\r
- }\r
-\r
-#ifndef DRAWEACH\r
- ScaleWalls (); // draw all the walls\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawScaleds\r
-=\r
-= Draws all objects that are visable\r
-=\r
-=====================\r
-*/\r
-\r
-objtype *depthsort[MAXACTORS];\r
-\r
-void DrawScaleds (void)\r
-{\r
-#if USE_INERT_LIST\r
- extern inertobjtype inertobjlist[], *inert;\r
-\r
- boolean inertlist=false;\r
-#endif\r
- int i,j,least,numvisable,height;\r
- objtype *obj,**vislist,*farthest;\r
- memptr shape;\r
- byte *tilespot,*visspot;\r
-\r
- numvisable = 0;\r
-\r
-//\r
-// calculate base positions of all objects\r
-//\r
- vislist = &depthsort[0];\r
-\r
- obj = player->next;\r
- while (obj)\r
- {\r
- tilespot = &tilemap[0][0]+(obj->tilex<<6)+obj->tiley;\r
- visspot = &spotvis[0][0]+(obj->tilex<<6)+obj->tiley;\r
- //\r
- // could be in any of the nine surrounding tiles\r
- //\r
- if (*visspot\r
- || ( *(visspot-1) && !*(tilespot-1) )\r
- || ( *(visspot+1) && !*(tilespot+1) )\r
- || ( *(visspot-65) && !*(tilespot-65) )\r
- || ( *(visspot-64) && !*(tilespot-64) )\r
- || ( *(visspot-63) && !*(tilespot-63) )\r
- || ( *(visspot+65) && !*(tilespot+65) )\r
- || ( *(visspot+64) && !*(tilespot+64) )\r
- || ( *(visspot+63) && !*(tilespot+63) ) )\r
- {\r
-#if USE_INERT_LIST\r
- if (!inertlist)\r
-#endif\r
- if ((obj->active == noalways) || (obj->active == always))\r
- obj->active = always;\r
- else\r
- obj->active = yes;\r
- TransformActor (obj);\r
- if (!obj->viewheight || obj->viewheight > VIEWWIDTH)\r
- goto cont; // too close or far away\r
-\r
- if (!obj->state->shapenum)\r
- goto cont;\r
-\r
- *vislist++ = obj;\r
- numvisable++;\r
- }\r
- else\r
-#if USE_INERT_LIST\r
- if (!inertlist)\r
-#endif\r
- if ((obj->active != always) && (obj->active != noalways))\r
- obj->active = no;\r
-\r
-cont:;\r
- obj = obj->next;\r
-#if USE_INERT_LIST\r
- if ((!obj) && (!inertlist))\r
- {\r
- if (inert != inertobjlist)\r
- obj = (objtype *)inertobjlist;\r
- inertlist = true;\r
- }\r
-#endif\r
- }\r
-\r
- if (vislist == &depthsort[0])\r
- return; // no visable objects\r
-\r
-//\r
-// draw from back to front\r
-//\r
- for (i = 0; i<numvisable; i++)\r
- {\r
- least = 32000;\r
- for (j=0;j<numvisable;j++)\r
- {\r
- height = depthsort[j]->viewheight;\r
- if (height < least)\r
- {\r
- least = height;\r
- farthest = depthsort[j];\r
- }\r
- }\r
- //\r
- // draw farthest\r
- //\r
- shape = shapedirectory[farthest->state->shapenum-FIRSTSCALEPIC];\r
- ScaleShape(farthest->viewx,shape,farthest->viewheight);\r
- farthest->viewheight = 32000;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= CalcTics\r
-=\r
-=====================\r
-*/\r
-\r
-void CalcTics (void)\r
-{\r
- long newtime,oldtimecount;\r
-\r
-\r
-#ifdef PROFILE\r
- tics = 1;\r
- return;\r
-#endif\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- if (lasttimecount > TimeCount)\r
- TimeCount = lasttimecount; // if the game was paused a LONG time\r
-\r
-#if 0\r
- if (DemoMode) // demo recording and playback needs\r
- { // to be constant\r
-//\r
-// take DEMOTICS or more tics, and modify Timecount to reflect time taken\r
-//\r
- oldtimecount = lasttimecount;\r
- while (TimeCount<oldtimecount+DEMOTICS*2)\r
- ;\r
- lasttimecount = oldtimecount + DEMOTICS;\r
- TimeCount = lasttimecount + DEMOTICS;\r
- realtics = tics = DEMOTICS;\r
- }\r
- else\r
-#endif\r
- {\r
-//\r
-// non demo, so report actual time\r
-//\r
- newtime = TimeCount;\r
- realtics = tics = newtime-lasttimecount;\r
- lasttimecount = newtime;\r
-\r
-#ifdef FILEPROFILE\r
- strcpy (scratch,"\tTics:");\r
- itoa (tics,str,10);\r
- strcat (scratch,str);\r
- strcat (scratch,"\n");\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- if (tics>MAXTICS)\r
- {\r
- TimeCount -= (tics-MAXTICS);\r
- tics = MAXTICS;\r
- }\r
-\r
- if (realtics>MAXREALTICS)\r
- realtics = MAXREALTICS;\r
- }\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= DrawHand\r
-=\r
-========================\r
-*/\r
-\r
-void DrawHand (void)\r
-{\r
- #define HAND_X_POS ((VIEWWIDTH/16)-(10/2)) // "10" = hand width in bytes\r
-\r
- #define picnum HAND1PICM\r
-\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
-// if (gamestate.shotpower || boltsleft)\r
-// picnum += (((unsigned)TimeCount>>3)&1);\r
-\r
- source = grsegs[picnum];\r
- dest = ylookup[VIEWHEIGHT-handheight]+HAND_X_POS+bufferofs; // 12\r
- width = picmtable[picnum-STARTPICM].width;\r
- height = picmtable[picnum-STARTPICM].height;\r
-\r
- VW_MaskBlock(source,0,dest,width,handheight,width*height);\r
- EGAMAPMASK(15);\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= ThreeDRefresh\r
-=\r
-========================\r
-*/\r
-\r
-void ThreeDRefresh (void)\r
-{\r
- int tracedir;\r
-\r
-restart:\r
- aborttrace = false;\r
-\r
-//\r
-// clear out the traced array\r
-//\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm mov di,OFFSET spotvis\r
-asm xor ax,ax\r
-asm mov cx,[mapwidth] // mapheight*32 words\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm rep stosw\r
-\r
-\r
-//\r
-// set up variables for this view\r
-//\r
-\r
- viewangle = player->angle;\r
- fineviewangle = viewangle*(FINEANGLES/ANGLES);\r
- viewsin = sintable[viewangle];\r
- viewcos = costable[viewangle];\r
- viewx = player->x - FixedByFrac(FOCALLENGTH,viewcos);\r
- viewy = player->y + FixedByFrac(FOCALLENGTH,viewsin);\r
- viewx &= 0xfffffc00; // stop on a pixel boundary\r
- viewy &= 0xfffffc00;\r
- viewx += 0x180;\r
- viewy += 0x180;\r
- viewxpix = viewx>>10;\r
- viewypix = viewy>>10;\r
-\r
- focal.x = viewx>>TILESHIFT;\r
- focal.y = viewy>>TILESHIFT;\r
-\r
-//\r
-// find the rightmost visable tile in view\r
-//\r
- tracedir = viewangle + lastangle;\r
- if (tracedir<0)\r
- tracedir+=ANGLES;\r
- else if (tracedir>=ANGLES)\r
- tracedir-=ANGLES;\r
- TraceRay( tracedir );\r
- right.x = tile.x;\r
- right.y = tile.y;\r
-\r
-//\r
-// find the leftmost visable tile in view\r
-//\r
- tracedir = viewangle + firstangle;\r
- if (tracedir<0)\r
- tracedir+=ANGLES;\r
- else if (tracedir>=ANGLES)\r
- tracedir-=ANGLES;\r
- TraceRay( tracedir );\r
-\r
-//\r
-// follow the walls from there to the right\r
-//\r
- rightwall = &walls[1];\r
- FollowWalls ();\r
-\r
- if (aborttrace)\r
- goto restart;\r
-\r
-//\r
-// actually draw stuff\r
-//\r
- if (++screenpage == 3)\r
- screenpage = 0;\r
-\r
- bufferofs = screenloc[screenpage];\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
-//\r
-// draw the wall list saved be FollowWalls ()\r
-//\r
-// animframe = (TimeCount&8)>>3;\r
-\r
-//\r
-// draw all the scaled images\r
-//\r
- asm mov dx,GC_INDEX\r
-\r
- asm mov ax,GC_COLORDONTCARE\r
- asm out dx,ax // don't look at any of the planes\r
-\r
- asm mov ax,GC_MODE + 256*(10) // read mode 1, write mode 2\r
- asm out dx,ax\r
-\r
- asm mov al,GC_BITMASK\r
- asm out dx,al\r
-\r
- AnimateWallList();\r
- DrawWallList();\r
- DrawScaleds();\r
-\r
- EGAWRITEMODE(0);\r
- EGABITMASK(0xff);\r
-\r
-//\r
-// draw hand\r
-//\r
- if (handheight)\r
- DrawHand ();\r
-\r
-//\r
-// show screen and time last cycle\r
-//\r
- if (fizzlein)\r
- {\r
- fizzlein = false;\r
- FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,true);\r
- lasttimecount = TimeCount;\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
-\r
-asm cli\r
-asm mov cx,[bufferofs]\r
-asm mov dx,3d4h // CRTC address register\r
-asm mov al,0ch // start address high register\r
-asm out dx,al\r
-asm inc dx\r
-asm mov al,ch\r
-asm out dx,al // set the high byte\r
-asm dec dx\r
-asm mov al,0dh // start address low register\r
-asm out dx,al\r
-asm inc dx\r
-asm mov al,cl\r
-asm out dx,al // set the low byte\r
-asm sti\r
-\r
- displayofs = bufferofs;\r
-\r
- CalcTics ();\r
-\r
-}\r
-\r