+++ /dev/null
-// WL_DRAW.C\r
-\r
-#include "WL_DEF.H"\r
-#include <DOS.H>\r
-#pragma hdrstop\r
-\r
-//#define DEBUGWALLS\r
-//#define DEBUGTICS\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-// the door is the last picture before the sprites\r
-#define DOORWALL (PMSpriteStart-8)\r
-\r
-#define ACTORSIZE 0x4000\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-#ifdef DEBUGWALLS\r
-unsigned screenloc[3]= {0,0,0};\r
-#else\r
-unsigned screenloc[3]= {PAGE1START,PAGE2START,PAGE3START};\r
-#endif\r
-unsigned freelatch = FREESTART;\r
-\r
-long lasttimecount;\r
-long frameon;\r
-\r
-unsigned wallheight[MAXVIEWWIDTH];\r
-\r
-fixed tileglobal = TILEGLOBAL;\r
-fixed mindist = MINDIST;\r
-\r
-\r
-//\r
-// math tables\r
-//\r
-int pixelangle[MAXVIEWWIDTH];\r
-long far finetangent[FINEANGLES/4];\r
-fixed far sintable[ANGLES+ANGLES/4],far *costable = sintable+(ANGLES/4);\r
-\r
-//\r
-// refresh variables\r
-//\r
-fixed viewx,viewy; // the focal point\r
-int viewangle;\r
-fixed viewsin,viewcos;\r
-\r
-\r
-\r
-fixed FixedByFrac (fixed a, fixed b);\r
-void TransformActor (objtype *ob);\r
-void BuildTables (void);\r
-void ClearScreen (void);\r
-int CalcRotate (objtype *ob);\r
-void DrawScaleds (void);\r
-void CalcTics (void);\r
-void FixOfs (void);\r
-void ThreeDRefresh (void);\r
-\r
-\r
-\r
-//\r
-// wall optimization variables\r
-//\r
-int lastside; // true for vertical\r
-long lastintercept;\r
-int lasttilehit;\r
-\r
-\r
-//\r
-// ray tracing variables\r
-//\r
-int focaltx,focalty,viewtx,viewty;\r
-\r
-int midangle,angle;\r
-unsigned xpartial,ypartial;\r
-unsigned xpartialup,xpartialdown,ypartialup,ypartialdown;\r
-unsigned xinttile,yinttile;\r
-\r
-unsigned tilehit;\r
-unsigned pixx;\r
-\r
-int xtile,ytile;\r
-int xtilestep,ytilestep;\r
-long xintercept,yintercept;\r
-long xstep,ystep;\r
-\r
-int horizwall[MAXWALLTILES],vertwall[MAXWALLTILES];\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-void AsmRefresh (void); // in WL_DR_A.ASM\r
-\r
-/*\r
-============================================================================\r
-\r
- 3 - D DEFINITIONS\r
-\r
-============================================================================\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
-//\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 neg cx\r
-asm neg ax\r
-asm sbb 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 neg dx\r
-asm neg ax\r
-asm sbb dx,0\r
-\r
-ansok:;\r
-\r
-}\r
-\r
-#pragma warn +rvl\r
-\r
-//==========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= TransformActor\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
-= scale : conversion from global value to screen value\r
-=\r
-= sets:\r
-= screenx,transx,transy,screenheight: projected edge location and size\r
-=\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
- long temp;\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-ACTORSIZE; // fudge the shape forward a bit, because\r
- // the midpoint could put parts of the shape\r
- // into an adjacent wall\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
- ob->transx = nx;\r
- ob->transy = ny;\r
-\r
- if (nx<mindist) // too close, don't overflow the divide\r
- {\r
- ob->viewheight = 0;\r
- return;\r
- }\r
-\r
- ob->viewx = centerx + ny*scale/nx; // DEBUG: use assembly divide\r
-\r
-//\r
-// calculate height (heightnumerator/(nx>>8))\r
-//\r
- asm mov ax,[WORD PTR heightnumerator]\r
- asm mov dx,[WORD PTR heightnumerator+2]\r
- asm idiv [WORD PTR nx+1] // nx>>8\r
- asm mov [WORD PTR temp],ax\r
- asm mov [WORD PTR temp+2],dx\r
-\r
- ob->viewheight = temp;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= TransformTile\r
-=\r
-= Takes paramaters:\r
-= tx,ty : tile the object is centered in\r
-=\r
-= globals:\r
-= viewx,viewy : point of view\r
-= viewcos,viewsin : sin/cos of viewangle\r
-= scale : conversion from global value to screen value\r
-=\r
-= sets:\r
-= screenx,transx,transy,screenheight: projected edge location and size\r
-=\r
-= Returns true if the tile is withing getting distance\r
-=\r
-========================\r
-*/\r
-\r
-boolean TransformTile (int tx, int ty, int *dispx, int *dispheight)\r
-{\r
- int ratio;\r
- fixed gx,gy,gxt,gyt,nx,ny;\r
- long temp;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = ((long)tx<<TILESHIFT)+0x8000-viewx;\r
- gy = ((long)ty<<TILESHIFT)+0x8000-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
- nx = gxt-gyt-0x2000; // 0x2000 is size of object\r
-\r
-//\r
-// calculate newy\r
-//\r
- gxt = FixedByFrac(gx,viewsin);\r
- gyt = FixedByFrac(gy,viewcos);\r
- ny = gyt+gxt;\r
-\r
-\r
-//\r
-// calculate perspective ratio\r
-//\r
- if (nx<mindist) // too close, don't overflow the divide\r
- {\r
- *dispheight = 0;\r
- return false;\r
- }\r
-\r
- *dispx = centerx + ny*scale/nx; // DEBUG: use assembly divide\r
-\r
-//\r
-// calculate height (heightnumerator/(nx>>8))\r
-//\r
- asm mov ax,[WORD PTR heightnumerator]\r
- asm mov dx,[WORD PTR heightnumerator+2]\r
- asm idiv [WORD PTR nx+1] // nx>>8\r
- asm mov [WORD PTR temp],ax\r
- asm mov [WORD PTR temp+2],dx\r
-\r
- *dispheight = temp;\r
-\r
-//\r
-// see if it should be grabbed\r
-//\r
- if (nx<TILEGLOBAL && ny>-TILEGLOBAL/2 && ny<TILEGLOBAL/2)\r
- return true;\r
- else\r
- return false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= CalcHeight\r
-=\r
-= Calculates the height of xintercept,yintercept from viewx,viewy\r
-=\r
-====================\r
-*/\r
-\r
-#pragma warn -rvl // I stick the return value in with ASMs\r
-\r
-int CalcHeight (void)\r
-{\r
- int transheight;\r
- int ratio;\r
- fixed gxt,gyt,nx,ny;\r
- long gx,gy;\r
-\r
- gx = xintercept-viewx;\r
- gxt = FixedByFrac(gx,viewcos);\r
-\r
- gy = yintercept-viewy;\r
- gyt = FixedByFrac(gy,viewsin);\r
-\r
- nx = gxt-gyt;\r
-\r
- //\r
- // calculate perspective ratio (heightnumerator/(nx>>8))\r
- //\r
- if (nx<mindist)\r
- nx=mindist; // don't let divide overflow\r
-\r
- asm mov ax,[WORD PTR heightnumerator]\r
- asm mov dx,[WORD PTR heightnumerator+2]\r
- asm idiv [WORD PTR nx+1] // nx>>8\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= ScalePost\r
-=\r
-===================\r
-*/\r
-\r
-long postsource;\r
-unsigned postx;\r
-unsigned postwidth;\r
-\r
-void near ScalePost (void) // VGA version\r
-{\r
- asm mov ax,SCREENSEG\r
- asm mov es,ax\r
-\r
- asm mov bx,[postx]\r
- asm shl bx,1\r
- asm mov bp,WORD PTR [wallheight+bx] // fractional height (low 3 bits frac)\r
- asm and bp,0xfff8 // bp = heightscaler*4\r
- asm shr bp,1\r
- asm cmp bp,[maxscaleshl2]\r
- asm jle heightok\r
- asm mov bp,[maxscaleshl2]\r
-heightok:\r
- asm add bp,OFFSET fullscalefarcall\r
- //\r
- // scale a byte wide strip of wall\r
- //\r
- asm mov bx,[postx]\r
- asm mov di,bx\r
- asm shr di,1 // X in bytes\r
- asm shr di,1\r
- asm add di,[bufferofs]\r
-\r
- asm and bx,3\r
- /* begin 8086 hack\r
- asm shl bx,3\r
- */\r
- asm push cx\r
- asm mov cl,3\r
- asm shl bx,cl\r
- asm pop cx\r
- /* end 8086 hack */\r
- asm add bx,[postwidth]\r
-\r
- asm mov al,BYTE PTR [mapmasks1-1+bx] // -1 because no widths of 0\r
- asm mov dx,SC_INDEX+1\r
- asm out dx,al // set bit mask register\r
- asm lds si,DWORD PTR [postsource]\r
- asm call DWORD PTR [bp] // scale the line of pixels\r
-\r
- asm mov al,BYTE PTR [ss:mapmasks2-1+bx] // -1 because no widths of 0\r
- asm or al,al\r
- asm jz nomore\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 [bp] // scale the line of pixels\r
-\r
- asm mov al,BYTE PTR [ss:mapmasks3-1+bx] // -1 because no widths of 0\r
- asm or al,al\r
- asm jz nomore\r
- //\r
- // draw a third byte for vertical strips that cross three bytes\r
- //\r
- asm inc di\r
- asm out dx,al // set bit mask register\r
- asm call DWORD PTR [bp] // scale the line of pixels\r
-\r
-\r
-nomore:\r
- asm mov ax,ss\r
- asm mov ds,ax\r
-}\r
-\r
-void FarScalePost (void) // just so other files can call\r
-{\r
- ScalePost ();\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= HitVertWall\r
-=\r
-= tilehit bit 7 is 0, because it's not a door tile\r
-= if bit 6 is 1 and the adjacent tile is a door tile, use door side pic\r
-=\r
-====================\r
-*/\r
-\r
-void HitVertWall (void)\r
-{\r
- int wallpic;\r
- unsigned texture;\r
-\r
- texture = (yintercept>>4)&0xfc0;\r
- if (xtilestep == -1)\r
- {\r
- texture = 0xfc0-texture;\r
- xintercept += TILEGLOBAL;\r
- }\r
- wallheight[pixx] = CalcHeight();\r
-\r
- if (lastside==1 && lastintercept == xtile && lasttilehit == tilehit)\r
- {\r
- // in the same wall type as last time, so check for optimized draw\r
- if (texture == (unsigned)postsource)\r
- {\r
- // wide scale\r
- postwidth++;\r
- wallheight[pixx] = wallheight[pixx-1];\r
- return;\r
- }\r
- else\r
- {\r
- ScalePost ();\r
- (unsigned)postsource = texture;\r
- postwidth = 1;\r
- postx = pixx;\r
- }\r
- }\r
- else\r
- {\r
- // new wall\r
- if (lastside != -1) // if not the first scaled post\r
- ScalePost ();\r
-\r
- lastside = true;\r
- lastintercept = xtile;\r
-\r
- lasttilehit = tilehit;\r
- postx = pixx;\r
- postwidth = 1;\r
-\r
- if (tilehit & 0x40)\r
- { // check for adjacent doors\r
- ytile = yintercept>>TILESHIFT;\r
- if ( tilemap[xtile-xtilestep][ytile]&0x80 )\r
- wallpic = DOORWALL+3;\r
- else\r
- wallpic = vertwall[tilehit & ~0x40];\r
- }\r
- else\r
- wallpic = vertwall[tilehit];\r
-\r
- *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
- (unsigned)postsource = texture;\r
-\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= HitHorizWall\r
-=\r
-= tilehit bit 7 is 0, because it's not a door tile\r
-= if bit 6 is 1 and the adjacent tile is a door tile, use door side pic\r
-=\r
-====================\r
-*/\r
-\r
-void HitHorizWall (void)\r
-{\r
- int wallpic;\r
- unsigned texture;\r
-\r
- texture = (xintercept>>4)&0xfc0;\r
- if (ytilestep == -1)\r
- yintercept += TILEGLOBAL;\r
- else\r
- texture = 0xfc0-texture;\r
- wallheight[pixx] = CalcHeight();\r
-\r
- if (lastside==0 && lastintercept == ytile && lasttilehit == tilehit)\r
- {\r
- // in the same wall type as last time, so check for optimized draw\r
- if (texture == (unsigned)postsource)\r
- {\r
- // wide scale\r
- postwidth++;\r
- wallheight[pixx] = wallheight[pixx-1];\r
- return;\r
- }\r
- else\r
- {\r
- ScalePost ();\r
- (unsigned)postsource = texture;\r
- postwidth = 1;\r
- postx = pixx;\r
- }\r
- }\r
- else\r
- {\r
- // new wall\r
- if (lastside != -1) // if not the first scaled post\r
- ScalePost ();\r
-\r
- lastside = 0;\r
- lastintercept = ytile;\r
-\r
- lasttilehit = tilehit;\r
- postx = pixx;\r
- postwidth = 1;\r
-\r
- if (tilehit & 0x40)\r
- { // check for adjacent doors\r
- xtile = xintercept>>TILESHIFT;\r
- if ( tilemap[xtile][ytile-ytilestep]&0x80 )\r
- wallpic = DOORWALL+2;\r
- else\r
- wallpic = horizwall[tilehit & ~0x40];\r
- }\r
- else\r
- wallpic = horizwall[tilehit];\r
-\r
- *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
- (unsigned)postsource = texture;\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= HitHorizDoor\r
-=\r
-====================\r
-*/\r
-\r
-void HitHorizDoor (void)\r
-{\r
- unsigned texture,doorpage,doornum;\r
-\r
- doornum = tilehit&0x7f;\r
- texture = ( (xintercept-doorposition[doornum]) >> 4) &0xfc0;\r
-\r
- wallheight[pixx] = CalcHeight();\r
-\r
- if (lasttilehit == tilehit)\r
- {\r
- // in the same door as last time, so check for optimized draw\r
- if (texture == (unsigned)postsource)\r
- {\r
- // wide scale\r
- postwidth++;\r
- wallheight[pixx] = wallheight[pixx-1];\r
- return;\r
- }\r
- else\r
- {\r
- ScalePost ();\r
- (unsigned)postsource = texture;\r
- postwidth = 1;\r
- postx = pixx;\r
- }\r
- }\r
- else\r
- {\r
- if (lastside != -1) // if not the first scaled post\r
- ScalePost (); // draw last post\r
- // first pixel in this door\r
- lastside = 2;\r
- lasttilehit = tilehit;\r
- postx = pixx;\r
- postwidth = 1;\r
-\r
- switch (doorobjlist[doornum].lock)\r
- {\r
- case dr_normal:\r
- doorpage = DOORWALL;\r
- break;\r
- case dr_lock1:\r
- case dr_lock2:\r
- case dr_lock3:\r
- case dr_lock4:\r
- doorpage = DOORWALL+6;\r
- break;\r
- case dr_elevator:\r
- doorpage = DOORWALL+4;\r
- break;\r
- }\r
-\r
- *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage);\r
- (unsigned)postsource = texture;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= HitVertDoor\r
-=\r
-====================\r
-*/\r
-\r
-void HitVertDoor (void)\r
-{\r
- unsigned texture,doorpage,doornum;\r
-\r
- doornum = tilehit&0x7f;\r
- texture = ( (yintercept-doorposition[doornum]) >> 4) &0xfc0;\r
-\r
- wallheight[pixx] = CalcHeight();\r
-\r
- if (lasttilehit == tilehit)\r
- {\r
- // in the same door as last time, so check for optimized draw\r
- if (texture == (unsigned)postsource)\r
- {\r
- // wide scale\r
- postwidth++;\r
- wallheight[pixx] = wallheight[pixx-1];\r
- return;\r
- }\r
- else\r
- {\r
- ScalePost ();\r
- (unsigned)postsource = texture;\r
- postwidth = 1;\r
- postx = pixx;\r
- }\r
- }\r
- else\r
- {\r
- if (lastside != -1) // if not the first scaled post\r
- ScalePost (); // draw last post\r
- // first pixel in this door\r
- lastside = 2;\r
- lasttilehit = tilehit;\r
- postx = pixx;\r
- postwidth = 1;\r
-\r
- switch (doorobjlist[doornum].lock)\r
- {\r
- case dr_normal:\r
- doorpage = DOORWALL;\r
- break;\r
- case dr_lock1:\r
- case dr_lock2:\r
- case dr_lock3:\r
- case dr_lock4:\r
- doorpage = DOORWALL+6;\r
- break;\r
- case dr_elevator:\r
- doorpage = DOORWALL+4;\r
- break;\r
- }\r
-\r
- *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage+1);\r
- (unsigned)postsource = texture;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= HitHorizPWall\r
-=\r
-= A pushable wall in action has been hit\r
-=\r
-====================\r
-*/\r
-\r
-void HitHorizPWall (void)\r
-{\r
- int wallpic;\r
- unsigned texture,offset;\r
-\r
- texture = (xintercept>>4)&0xfc0;\r
- offset = pwallpos<<10;\r
- if (ytilestep == -1)\r
- yintercept += TILEGLOBAL-offset;\r
- else\r
- {\r
- texture = 0xfc0-texture;\r
- yintercept += offset;\r
- }\r
-\r
- wallheight[pixx] = CalcHeight();\r
-\r
- if (lasttilehit == tilehit)\r
- {\r
- // in the same wall type as last time, so check for optimized draw\r
- if (texture == (unsigned)postsource)\r
- {\r
- // wide scale\r
- postwidth++;\r
- wallheight[pixx] = wallheight[pixx-1];\r
- return;\r
- }\r
- else\r
- {\r
- ScalePost ();\r
- (unsigned)postsource = texture;\r
- postwidth = 1;\r
- postx = pixx;\r
- }\r
- }\r
- else\r
- {\r
- // new wall\r
- if (lastside != -1) // if not the first scaled post\r
- ScalePost ();\r
-\r
- lasttilehit = tilehit;\r
- postx = pixx;\r
- postwidth = 1;\r
-\r
- wallpic = horizwall[tilehit&63];\r
-\r
- *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
- (unsigned)postsource = texture;\r
- }\r
-\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= HitVertPWall\r
-=\r
-= A pushable wall in action has been hit\r
-=\r
-====================\r
-*/\r
-\r
-void HitVertPWall (void)\r
-{\r
- int wallpic;\r
- unsigned texture,offset;\r
-\r
- texture = (yintercept>>4)&0xfc0;\r
- offset = pwallpos<<10;\r
- if (xtilestep == -1)\r
- {\r
- xintercept += TILEGLOBAL-offset;\r
- texture = 0xfc0-texture;\r
- }\r
- else\r
- xintercept += offset;\r
-\r
- wallheight[pixx] = CalcHeight();\r
-\r
- if (lasttilehit == tilehit)\r
- {\r
- // in the same wall type as last time, so check for optimized draw\r
- if (texture == (unsigned)postsource)\r
- {\r
- // wide scale\r
- postwidth++;\r
- wallheight[pixx] = wallheight[pixx-1];\r
- return;\r
- }\r
- else\r
- {\r
- ScalePost ();\r
- (unsigned)postsource = texture;\r
- postwidth = 1;\r
- postx = pixx;\r
- }\r
- }\r
- else\r
- {\r
- // new wall\r
- if (lastside != -1) // if not the first scaled post\r
- ScalePost ();\r
-\r
- lasttilehit = tilehit;\r
- postx = pixx;\r
- postwidth = 1;\r
-\r
- wallpic = vertwall[tilehit&63];\r
-\r
- *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
- (unsigned)postsource = texture;\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-=====================\r
-=\r
-= ClearScreen\r
-=\r
-=====================\r
-*/\r
-\r
-void ClearScreen (void)\r
-{\r
- unsigned floor=egaFloor[gamestate.episode*10+mapon],\r
- ceiling=egaCeiling[gamestate.episode*10+mapon];\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\r
-asm mov ax,[viewwidth]\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm sub dx,ax // dx = 40-viewwidth/8\r
-\r
-asm mov bx,[viewwidth]\r
-asm shr bx,1 // bl = viewwidth/16\r
-asm shr bx,1\r
-asm shr bx,1\r
-asm shr bx,1\r
-asm mov bh,BYTE PTR [viewheight]\r
-asm shr bh,1 // half height\r
-\r
-asm mov ax,[ceiling]\r
-asm mov es,[screenseg]\r
-asm mov di,[bufferofs]\r
-\r
-toploop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm add di,dx\r
-asm dec bh\r
-asm jnz toploop\r
-\r
-asm mov bh,BYTE PTR [viewheight]\r
-asm shr bh,1 // half height\r
-asm mov ax,[floor]\r
-\r
-bottomloop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm add di,dx\r
-asm dec bh\r
-asm jnz bottomloop\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
-#endif\r
-//==========================================================================\r
-\r
-unsigned vgaCeiling[]=\r
-{\r
-#ifndef SPEAR\r
- 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xbfbf,\r
- 0x4e4e,0x4e4e,0x4e4e,0x1d1d,0x8d8d,0x4e4e,0x1d1d,0x2d2d,0x1d1d,0x8d8d,\r
- 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x2d2d,0xdddd,0x1d1d,0x1d1d,0x9898,\r
-\r
- 0x1d1d,0x9d9d,0x2d2d,0xdddd,0xdddd,0x9d9d,0x2d2d,0x4d4d,0x1d1d,0xdddd,\r
- 0x7d7d,0x1d1d,0x2d2d,0x2d2d,0xdddd,0xd7d7,0x1d1d,0x1d1d,0x1d1d,0x2d2d,\r
- 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xdddd,0xdddd,0x7d7d,0xdddd,0xdddd,0xdddd\r
-#else\r
- 0x6f6f,0x4f4f,0x1d1d,0xdede,0xdfdf,0x2e2e,0x7f7f,0x9e9e,0xaeae,0x7f7f,\r
- 0x1d1d,0xdede,0xdfdf,0xdede,0xdfdf,0xdede,0xe1e1,0xdcdc,0x2e2e,0x1d1d,0xdcdc\r
-#endif\r
-};\r
-\r
-/*\r
-=====================\r
-=\r
-= VGAClearScreen\r
-=\r
-=====================\r
-*/\r
-\r
-void VGAClearScreen (void)\r
-{\r
- unsigned ceiling=vgaCeiling[gamestate.episode*10+mapon];\r
-\r
- //\r
- // clear the screen\r
- //\r
-asm mov dx,SC_INDEX\r
-asm mov ax,SC_MAPMASK+15*256 // write through all planes\r
-asm out dx,ax\r
-\r
-asm mov dx,80\r
-asm mov ax,[viewwidth]\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm sub dx,ax // dx = 40-viewwidth/2\r
-\r
-asm mov bx,[viewwidth]\r
-asm shr bx,1 // bl = viewwidth/8\r
-asm shr bx,1\r
-asm shr bx,1\r
-asm mov bh,BYTE PTR [viewheight]\r
-asm shr bh,1 // half height\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[bufferofs]\r
-asm mov ax,[ceiling]\r
-\r
-toploop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm add di,dx\r
-asm dec bh\r
-asm jnz toploop\r
-\r
-asm mov bh,BYTE PTR [viewheight]\r
-asm shr bh,1 // half height\r
-asm mov ax,0x1919\r
-\r
-bottomloop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm add di,dx\r
-asm dec bh\r
-asm jnz bottomloop\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= CalcRotate\r
-=\r
-=====================\r
-*/\r
-\r
-int CalcRotate (objtype *ob)\r
-{\r
- int angle,viewangle;\r
-\r
- // this isn't exactly correct, as it should vary by a trig value,\r
- // but it is close enough with only eight rotations\r
-\r
- viewangle = player->angle + (centerx - ob->viewx)/8;\r
-\r
- if (ob->obclass == rocketobj || ob->obclass == hrocketobj)\r
- angle = (viewangle-180)- ob->angle;\r
- else\r
- angle = (viewangle-180)- dirangle[ob->dir];\r
-\r
- angle+=ANGLES/16;\r
- while (angle>=ANGLES)\r
- angle-=ANGLES;\r
- while (angle<0)\r
- angle+=ANGLES;\r
-\r
- if (ob->state->rotate == 2) // 2 rotation pain frame\r
- return 4*(angle/(ANGLES/2)); // seperated by 3 (art layout...)\r
-\r
- return angle/(ANGLES/8);\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawScaleds\r
-=\r
-= Draws all objects that are visable\r
-=\r
-=====================\r
-*/\r
-\r
-#define MAXVISABLE 50\r
-\r
-typedef struct\r
-{\r
- int viewx,\r
- viewheight,\r
- shapenum;\r
-} visobj_t;\r
-\r
-visobj_t vislist[MAXVISABLE],*visptr,*visstep,*farthest;\r
-\r
-void DrawScaleds (void)\r
-{\r
- int i,j,least,numvisable,height;\r
- memptr shape;\r
- byte *tilespot,*visspot;\r
- int shapenum;\r
- unsigned spotloc;\r
-\r
- statobj_t *statptr;\r
- objtype *obj;\r
-\r
- visptr = &vislist[0];\r
-\r
-//\r
-// place static objects\r
-//\r
- for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++)\r
- {\r
- if ((visptr->shapenum = statptr->shapenum) == -1)\r
- continue; // object has been deleted\r
-\r
- if (!*statptr->visspot)\r
- continue; // not visable\r
-\r
- if (TransformTile (statptr->tilex,statptr->tiley\r
- ,&visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS)\r
- {\r
- GetBonus (statptr);\r
- continue;\r
- }\r
-\r
- if (!visptr->viewheight)\r
- continue; // to close to the object\r
-\r
- if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow\r
- visptr++;\r
- }\r
-\r
-//\r
-// place active objects\r
-//\r
- for (obj = player->next;obj;obj=obj->next)\r
- {\r
- if (!(visptr->shapenum = obj->state->shapenum))\r
- continue; // no shape\r
-\r
- spotloc = (obj->tilex<<6)+obj->tiley; // optimize: keep in struct?\r
- visspot = &spotvis[0][0]+spotloc;\r
- tilespot = &tilemap[0][0]+spotloc;\r
-\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
- obj->active = true;\r
- TransformActor (obj);\r
- if (!obj->viewheight)\r
- continue; // too close or far away\r
-\r
- visptr->viewx = obj->viewx;\r
- visptr->viewheight = obj->viewheight;\r
- if (visptr->shapenum == -1)\r
- visptr->shapenum = obj->temp1; // special shape\r
-\r
- if (obj->state->rotate)\r
- visptr->shapenum += CalcRotate (obj);\r
-\r
- if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow\r
- visptr++;\r
- obj->flags |= FL_VISABLE;\r
- }\r
- else\r
- obj->flags &= ~FL_VISABLE;\r
- }\r
-\r
-//\r
-// draw from back to front\r
-//\r
- numvisable = visptr-&vislist[0];\r
-\r
- if (!numvisable)\r
- return; // no visable objects\r
-\r
- for (i = 0; i<numvisable; i++)\r
- {\r
- least = 32000;\r
- for (visstep=&vislist[0] ; visstep<visptr ; visstep++)\r
- {\r
- height = visstep->viewheight;\r
- if (height < least)\r
- {\r
- least = height;\r
- farthest = visstep;\r
- }\r
- }\r
- //\r
- // draw farthest\r
- //\r
- ScaleShape(farthest->viewx,farthest->shapenum,farthest->viewheight);\r
-\r
- farthest->viewheight = 32000;\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==============\r
-=\r
-= DrawPlayerWeapon\r
-=\r
-= Draw the player's hands\r
-=\r
-==============\r
-*/\r
-\r
-int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY,SPR_PISTOLREADY\r
- ,SPR_MACHINEGUNREADY,SPR_CHAINREADY};\r
-\r
-void DrawPlayerWeapon (void)\r
-{\r
- int shapenum;\r
-\r
-#ifndef SPEAR\r
- if (gamestate.victoryflag)\r
- {\r
- if (player->state == &s_deathcam && (TimeCount&32) )\r
- SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1);\r
- return;\r
- }\r
-#endif\r
-\r
- if (gamestate.weapon != -1)\r
- {\r
- shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe;\r
- SimpleScaleShape(viewwidth/2,shapenum,viewheight+1);\r
- }\r
-\r
- if (demorecord || demoplayback)\r
- SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1);\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
-// 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
- do\r
- {\r
- newtime = TimeCount;\r
- tics = newtime-lasttimecount;\r
- } while (!tics); // make sure at least one tic passes\r
-\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
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= FixOfs\r
-=\r
-========================\r
-*/\r
-\r
-void FixOfs (void)\r
-{\r
- VW_ScreenToScreen (displayofs,bufferofs,viewwidth/8,viewheight);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= WallRefresh\r
-=\r
-====================\r
-*/\r
-\r
-void WallRefresh (void)\r
-{\r
-//\r
-// set up variables for this view\r
-//\r
- viewangle = player->angle;\r
- midangle = 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
-\r
- focaltx = viewx>>TILESHIFT;\r
- focalty = viewy>>TILESHIFT;\r
-\r
- viewtx = player->x >> TILESHIFT;\r
- viewty = player->y >> TILESHIFT;\r
-\r
- xpartialdown = viewx&(TILEGLOBAL-1);\r
- xpartialup = TILEGLOBAL-xpartialdown;\r
- ypartialdown = viewy&(TILEGLOBAL-1);\r
- ypartialup = TILEGLOBAL-ypartialdown;\r
-\r
- lastside = -1; // the first pixel is on a new wall\r
- AsmRefresh ();\r
- ScalePost (); // no more optimization on last post\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= ThreeDRefresh\r
-=\r
-========================\r
-*/\r
-\r
-void ThreeDRefresh (void)\r
-{\r
- int tracedir;\r
-\r
-// this wouldn't need to be done except for my debugger/video wierdness\r
- outportb (SC_INDEX,SC_MAPMASK);\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,2048 // 64*64 / 2\r
-asm rep stosw\r
-\r
- bufferofs += screenofs;\r
-\r
-//\r
-// follow the walls from there to the right, drawwing as we go\r
-//\r
- VGAClearScreen ();\r
-\r
- WallRefresh ();\r
-\r
-//\r
-// draw all the scaled images\r
-//\r
- DrawScaleds(); // draw scaled stuff\r
- DrawPlayerWeapon (); // draw player's hands\r
-\r
-//\r
-// show screen and time last cycle\r
-//\r
- if (fizzlein)\r
- {\r
- FizzleFade(bufferofs,displayofs+screenofs,viewwidth,viewheight,20,false);\r
- fizzlein = false;\r
-\r
- lasttimecount = TimeCount = 0; // don't make a big tic count\r
-\r
- }\r
-\r
- bufferofs -= screenofs;\r
- displayofs = bufferofs;\r
-\r
- asm cli\r
- asm mov cx,[displayofs]\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 sti\r
-\r
- bufferofs += SCREENSIZE;\r
- if (bufferofs > PAGE3START)\r
- bufferofs = PAGE1START;\r
-\r
- frameon++;\r
- PM_NextFrame();\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r