11 =============================================================================
\r
15 =============================================================================
\r
18 // the door is the last picture before the sprites
\r
19 #define DOORWALL (PMSpriteStart-8)
\r
21 #define ACTORSIZE 0x4000
\r
24 =============================================================================
\r
28 =============================================================================
\r
33 unsigned screenloc[3]= {0,0,0};
\r
35 unsigned screenloc[3]= {PAGE1START,PAGE2START,PAGE3START};
\r
37 unsigned freelatch = FREESTART;
\r
42 unsigned wallheight[MAXVIEWWIDTH];
\r
44 fixed tileglobal = TILEGLOBAL;
\r
45 fixed mindist = MINDIST;
\r
51 int pixelangle[MAXVIEWWIDTH];
\r
52 long far finetangent[FINEANGLES/4];
\r
53 fixed far sintable[ANGLES+ANGLES/4],far *costable = sintable+(ANGLES/4);
\r
56 // refresh variables
\r
58 fixed viewx,viewy; // the focal point
\r
60 fixed viewsin,viewcos;
\r
64 fixed FixedByFrac (fixed a, fixed b);
\r
65 void TransformActor (objtype *ob);
\r
66 void BuildTables (void);
\r
67 void ClearScreen (void);
\r
68 int CalcRotate (objtype *ob);
\r
69 void DrawScaleds (void);
\r
70 void CalcTics (void);
\r
72 void ThreeDRefresh (void);
\r
77 // wall optimization variables
\r
79 int lastside; // true for vertical
\r
85 // ray tracing variables
\r
87 int focaltx,focalty,viewtx,viewty;
\r
90 unsigned xpartial,ypartial;
\r
91 unsigned xpartialup,xpartialdown,ypartialup,ypartialdown;
\r
92 unsigned xinttile,yinttile;
\r
98 int xtilestep,ytilestep;
\r
99 long xintercept,yintercept;
\r
102 int horizwall[MAXWALLTILES],vertwall[MAXWALLTILES];
\r
106 =============================================================================
\r
110 =============================================================================
\r
114 void AsmRefresh (void); // in WL_DR_A.ASM
\r
117 ============================================================================
\r
121 ============================================================================
\r
125 //==========================================================================
\r
129 ========================
\r
133 = multiply a 16/16 bit, 2's complement fixed point number by a 16 bit
\r
134 = fraction, passed as a signed magnitude 32 bit number
\r
136 ========================
\r
139 #pragma warn -rvl // I stick the return value in with ASMs
\r
141 fixed FixedByFrac (fixed a, fixed b)
\r
146 asm mov si,[WORD PTR b+2] // sign of result = sign of fraction
\r
148 asm mov ax,[WORD PTR a]
\r
149 asm mov cx,[WORD PTR a+2]
\r
152 asm jns aok: // negative?
\r
156 asm xor si,0x8000 // toggle sign of result
\r
160 // multiply cx:ax by bx
\r
162 asm mov bx,[WORD PTR b]
\r
163 asm mul bx // fraction*fraction
\r
164 asm mov di,dx // di is low word of result
\r
166 asm mul bx // units*fraction
\r
171 // put result dx:ax in 2's complement
\r
173 asm test si,0x8000 // is the result negative?
\r
185 //==========================================================================
\r
188 ========================
\r
192 = Takes paramaters:
\r
193 = gx,gy : globalx/globaly of point
\r
196 = viewx,viewy : point of view
\r
197 = viewcos,viewsin : sin/cos of viewangle
\r
198 = scale : conversion from global value to screen value
\r
201 = screenx,transx,transy,screenheight: projected edge location and size
\r
203 ========================
\r
210 void TransformActor (objtype *ob)
\r
213 fixed gx,gy,gxt,gyt,nx,ny;
\r
217 // translate point to view centered coordinates
\r
225 gxt = FixedByFrac(gx,viewcos);
\r
226 gyt = FixedByFrac(gy,viewsin);
\r
227 nx = gxt-gyt-ACTORSIZE; // fudge the shape forward a bit, because
\r
228 // the midpoint could put parts of the shape
\r
229 // into an adjacent wall
\r
234 gxt = FixedByFrac(gx,viewsin);
\r
235 gyt = FixedByFrac(gy,viewcos);
\r
239 // calculate perspective ratio
\r
244 if (nx<mindist) // too close, don't overflow the divide
\r
246 ob->viewheight = 0;
\r
250 ob->viewx = centerx + ny*scale/nx; // DEBUG: use assembly divide
\r
253 // calculate height (heightnumerator/(nx>>8))
\r
255 asm mov ax,[WORD PTR heightnumerator]
\r
256 asm mov dx,[WORD PTR heightnumerator+2]
\r
257 asm idiv [WORD PTR nx+1] // nx>>8
\r
258 asm mov [WORD PTR temp],ax
\r
259 asm mov [WORD PTR temp+2],dx
\r
261 ob->viewheight = temp;
\r
264 //==========================================================================
\r
267 ========================
\r
271 = Takes paramaters:
\r
272 = tx,ty : tile the object is centered in
\r
275 = viewx,viewy : point of view
\r
276 = viewcos,viewsin : sin/cos of viewangle
\r
277 = scale : conversion from global value to screen value
\r
280 = screenx,transx,transy,screenheight: projected edge location and size
\r
282 = Returns true if the tile is withing getting distance
\r
284 ========================
\r
287 boolean TransformTile (int tx, int ty, int *dispx, int *dispheight)
\r
290 fixed gx,gy,gxt,gyt,nx,ny;
\r
294 // translate point to view centered coordinates
\r
296 gx = ((long)tx<<TILESHIFT)+0x8000-viewx;
\r
297 gy = ((long)ty<<TILESHIFT)+0x8000-viewy;
\r
302 gxt = FixedByFrac(gx,viewcos);
\r
303 gyt = FixedByFrac(gy,viewsin);
\r
304 nx = gxt-gyt-0x2000; // 0x2000 is size of object
\r
309 gxt = FixedByFrac(gx,viewsin);
\r
310 gyt = FixedByFrac(gy,viewcos);
\r
315 // calculate perspective ratio
\r
317 if (nx<mindist) // too close, don't overflow the divide
\r
323 *dispx = centerx + ny*scale/nx; // DEBUG: use assembly divide
\r
326 // calculate height (heightnumerator/(nx>>8))
\r
328 asm mov ax,[WORD PTR heightnumerator]
\r
329 asm mov dx,[WORD PTR heightnumerator+2]
\r
330 asm idiv [WORD PTR nx+1] // nx>>8
\r
331 asm mov [WORD PTR temp],ax
\r
332 asm mov [WORD PTR temp+2],dx
\r
334 *dispheight = temp;
\r
337 // see if it should be grabbed
\r
339 if (nx<TILEGLOBAL && ny>-TILEGLOBAL/2 && ny<TILEGLOBAL/2)
\r
345 //==========================================================================
\r
348 ====================
\r
352 = Calculates the height of xintercept,yintercept from viewx,viewy
\r
354 ====================
\r
357 #pragma warn -rvl // I stick the return value in with ASMs
\r
359 int CalcHeight (void)
\r
363 fixed gxt,gyt,nx,ny;
\r
366 gx = xintercept-viewx;
\r
367 gxt = FixedByFrac(gx,viewcos);
\r
369 gy = yintercept-viewy;
\r
370 gyt = FixedByFrac(gy,viewsin);
\r
375 // calculate perspective ratio (heightnumerator/(nx>>8))
\r
378 nx=mindist; // don't let divide overflow
\r
380 asm mov ax,[WORD PTR heightnumerator]
\r
381 asm mov dx,[WORD PTR heightnumerator+2]
\r
382 asm idiv [WORD PTR nx+1] // nx>>8
\r
386 //==========================================================================
\r
389 ===================
\r
393 ===================
\r
398 unsigned postwidth;
\r
400 void near ScalePost (void) // VGA version
\r
402 asm mov ax,SCREENSEG
\r
407 asm mov bp,WORD PTR [wallheight+bx] // fractional height (low 3 bits frac)
\r
408 asm and bp,0xfff8 // bp = heightscaler*4
\r
410 asm cmp bp,[maxscaleshl2]
\r
412 asm mov bp,[maxscaleshl2]
\r
414 asm add bp,OFFSET fullscalefarcall
\r
416 // scale a byte wide strip of wall
\r
420 asm shr di,1 // X in bytes
\r
422 asm add di,[bufferofs]
\r
432 /* end 8086 hack */
\r
433 asm add bx,[postwidth]
\r
435 asm mov al,BYTE PTR [mapmasks1-1+bx] // -1 because no widths of 0
\r
436 asm mov dx,SC_INDEX+1
\r
437 asm out dx,al // set bit mask register
\r
438 asm lds si,DWORD PTR [postsource]
\r
439 asm call DWORD PTR [bp] // scale the line of pixels
\r
441 asm mov al,BYTE PTR [ss:mapmasks2-1+bx] // -1 because no widths of 0
\r
446 // draw a second byte for vertical strips that cross two bytes
\r
449 asm out dx,al // set bit mask register
\r
450 asm call DWORD PTR [bp] // scale the line of pixels
\r
452 asm mov al,BYTE PTR [ss:mapmasks3-1+bx] // -1 because no widths of 0
\r
456 // draw a third byte for vertical strips that cross three bytes
\r
459 asm out dx,al // set bit mask register
\r
460 asm call DWORD PTR [bp] // scale the line of pixels
\r
468 void FarScalePost (void) // just so other files can call
\r
475 ====================
\r
479 = tilehit bit 7 is 0, because it's not a door tile
\r
480 = if bit 6 is 1 and the adjacent tile is a door tile, use door side pic
\r
482 ====================
\r
485 void HitVertWall (void)
\r
490 texture = (yintercept>>4)&0xfc0;
\r
491 if (xtilestep == -1)
\r
493 texture = 0xfc0-texture;
\r
494 xintercept += TILEGLOBAL;
\r
496 wallheight[pixx] = CalcHeight();
\r
498 if (lastside==1 && lastintercept == xtile && lasttilehit == tilehit)
\r
500 // in the same wall type as last time, so check for optimized draw
\r
501 if (texture == (unsigned)postsource)
\r
505 wallheight[pixx] = wallheight[pixx-1];
\r
511 (unsigned)postsource = texture;
\r
519 if (lastside != -1) // if not the first scaled post
\r
523 lastintercept = xtile;
\r
525 lasttilehit = tilehit;
\r
529 if (tilehit & 0x40)
\r
530 { // check for adjacent doors
\r
531 ytile = yintercept>>TILESHIFT;
\r
532 if ( tilemap[xtile-xtilestep][ytile]&0x80 )
\r
533 wallpic = DOORWALL+3;
\r
535 wallpic = vertwall[tilehit & ~0x40];
\r
538 wallpic = vertwall[tilehit];
\r
540 *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);
\r
541 (unsigned)postsource = texture;
\r
548 ====================
\r
552 = tilehit bit 7 is 0, because it's not a door tile
\r
553 = if bit 6 is 1 and the adjacent tile is a door tile, use door side pic
\r
555 ====================
\r
558 void HitHorizWall (void)
\r
563 texture = (xintercept>>4)&0xfc0;
\r
564 if (ytilestep == -1)
\r
565 yintercept += TILEGLOBAL;
\r
567 texture = 0xfc0-texture;
\r
568 wallheight[pixx] = CalcHeight();
\r
570 if (lastside==0 && lastintercept == ytile && lasttilehit == tilehit)
\r
572 // in the same wall type as last time, so check for optimized draw
\r
573 if (texture == (unsigned)postsource)
\r
577 wallheight[pixx] = wallheight[pixx-1];
\r
583 (unsigned)postsource = texture;
\r
591 if (lastside != -1) // if not the first scaled post
\r
595 lastintercept = ytile;
\r
597 lasttilehit = tilehit;
\r
601 if (tilehit & 0x40)
\r
602 { // check for adjacent doors
\r
603 xtile = xintercept>>TILESHIFT;
\r
604 if ( tilemap[xtile][ytile-ytilestep]&0x80 )
\r
605 wallpic = DOORWALL+2;
\r
607 wallpic = horizwall[tilehit & ~0x40];
\r
610 wallpic = horizwall[tilehit];
\r
612 *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);
\r
613 (unsigned)postsource = texture;
\r
618 //==========================================================================
\r
621 ====================
\r
625 ====================
\r
628 void HitHorizDoor (void)
\r
630 unsigned texture,doorpage,doornum;
\r
632 doornum = tilehit&0x7f;
\r
633 texture = ( (xintercept-doorposition[doornum]) >> 4) &0xfc0;
\r
635 wallheight[pixx] = CalcHeight();
\r
637 if (lasttilehit == tilehit)
\r
639 // in the same door as last time, so check for optimized draw
\r
640 if (texture == (unsigned)postsource)
\r
644 wallheight[pixx] = wallheight[pixx-1];
\r
650 (unsigned)postsource = texture;
\r
657 if (lastside != -1) // if not the first scaled post
\r
658 ScalePost (); // draw last post
\r
659 // first pixel in this door
\r
661 lasttilehit = tilehit;
\r
665 switch (doorobjlist[doornum].lock)
\r
668 doorpage = DOORWALL;
\r
674 doorpage = DOORWALL+6;
\r
677 doorpage = DOORWALL+4;
\r
681 *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage);
\r
682 (unsigned)postsource = texture;
\r
686 //==========================================================================
\r
689 ====================
\r
693 ====================
\r
696 void HitVertDoor (void)
\r
698 unsigned texture,doorpage,doornum;
\r
700 doornum = tilehit&0x7f;
\r
701 texture = ( (yintercept-doorposition[doornum]) >> 4) &0xfc0;
\r
703 wallheight[pixx] = CalcHeight();
\r
705 if (lasttilehit == tilehit)
\r
707 // in the same door as last time, so check for optimized draw
\r
708 if (texture == (unsigned)postsource)
\r
712 wallheight[pixx] = wallheight[pixx-1];
\r
718 (unsigned)postsource = texture;
\r
725 if (lastside != -1) // if not the first scaled post
\r
726 ScalePost (); // draw last post
\r
727 // first pixel in this door
\r
729 lasttilehit = tilehit;
\r
733 switch (doorobjlist[doornum].lock)
\r
736 doorpage = DOORWALL;
\r
742 doorpage = DOORWALL+6;
\r
745 doorpage = DOORWALL+4;
\r
749 *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage+1);
\r
750 (unsigned)postsource = texture;
\r
754 //==========================================================================
\r
758 ====================
\r
762 = A pushable wall in action has been hit
\r
764 ====================
\r
767 void HitHorizPWall (void)
\r
770 unsigned texture,offset;
\r
772 texture = (xintercept>>4)&0xfc0;
\r
773 offset = pwallpos<<10;
\r
774 if (ytilestep == -1)
\r
775 yintercept += TILEGLOBAL-offset;
\r
778 texture = 0xfc0-texture;
\r
779 yintercept += offset;
\r
782 wallheight[pixx] = CalcHeight();
\r
784 if (lasttilehit == tilehit)
\r
786 // in the same wall type as last time, so check for optimized draw
\r
787 if (texture == (unsigned)postsource)
\r
791 wallheight[pixx] = wallheight[pixx-1];
\r
797 (unsigned)postsource = texture;
\r
805 if (lastside != -1) // if not the first scaled post
\r
808 lasttilehit = tilehit;
\r
812 wallpic = horizwall[tilehit&63];
\r
814 *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);
\r
815 (unsigned)postsource = texture;
\r
822 ====================
\r
826 = A pushable wall in action has been hit
\r
828 ====================
\r
831 void HitVertPWall (void)
\r
834 unsigned texture,offset;
\r
836 texture = (yintercept>>4)&0xfc0;
\r
837 offset = pwallpos<<10;
\r
838 if (xtilestep == -1)
\r
840 xintercept += TILEGLOBAL-offset;
\r
841 texture = 0xfc0-texture;
\r
844 xintercept += offset;
\r
846 wallheight[pixx] = CalcHeight();
\r
848 if (lasttilehit == tilehit)
\r
850 // in the same wall type as last time, so check for optimized draw
\r
851 if (texture == (unsigned)postsource)
\r
855 wallheight[pixx] = wallheight[pixx-1];
\r
861 (unsigned)postsource = texture;
\r
869 if (lastside != -1) // if not the first scaled post
\r
872 lasttilehit = tilehit;
\r
876 wallpic = vertwall[tilehit&63];
\r
878 *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);
\r
879 (unsigned)postsource = texture;
\r
884 //==========================================================================
\r
886 //==========================================================================
\r
890 =====================
\r
894 =====================
\r
897 void ClearScreen (void)
\r
899 unsigned floor=egaFloor[gamestate.episode*10+mapon],
\r
900 ceiling=egaCeiling[gamestate.episode*10+mapon];
\r
903 // clear the screen
\r
905 asm mov dx,GC_INDEX
\r
906 asm mov ax,GC_MODE + 256*2 // read mode 0, write mode 2
\r
908 asm mov ax,GC_BITMASK + 255*256
\r
912 asm mov ax,[viewwidth]
\r
916 asm sub dx,ax // dx = 40-viewwidth/8
\r
918 asm mov bx,[viewwidth]
\r
919 asm shr bx,1 // bl = viewwidth/16
\r
923 asm mov bh,BYTE PTR [viewheight]
\r
924 asm shr bh,1 // half height
\r
926 asm mov ax,[ceiling]
\r
927 asm mov es,[screenseg]
\r
928 asm mov di,[bufferofs]
\r
937 asm mov bh,BYTE PTR [viewheight]
\r
938 asm shr bh,1 // half height
\r
949 asm mov dx,GC_INDEX
\r
950 asm mov ax,GC_MODE + 256*10 // read mode 1, write mode 2
\r
952 asm mov al,GC_BITMASK
\r
957 //==========================================================================
\r
959 unsigned vgaCeiling[]=
\r
962 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xbfbf,
\r
963 0x4e4e,0x4e4e,0x4e4e,0x1d1d,0x8d8d,0x4e4e,0x1d1d,0x2d2d,0x1d1d,0x8d8d,
\r
964 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x2d2d,0xdddd,0x1d1d,0x1d1d,0x9898,
\r
966 0x1d1d,0x9d9d,0x2d2d,0xdddd,0xdddd,0x9d9d,0x2d2d,0x4d4d,0x1d1d,0xdddd,
\r
967 0x7d7d,0x1d1d,0x2d2d,0x2d2d,0xdddd,0xd7d7,0x1d1d,0x1d1d,0x1d1d,0x2d2d,
\r
968 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xdddd,0xdddd,0x7d7d,0xdddd,0xdddd,0xdddd
\r
970 0x6f6f,0x4f4f,0x1d1d,0xdede,0xdfdf,0x2e2e,0x7f7f,0x9e9e,0xaeae,0x7f7f,
\r
971 0x1d1d,0xdede,0xdfdf,0xdede,0xdfdf,0xdede,0xe1e1,0xdcdc,0x2e2e,0x1d1d,0xdcdc
\r
976 =====================
\r
980 =====================
\r
983 void VGAClearScreen (void)
\r
985 unsigned ceiling=vgaCeiling[gamestate.episode*10+mapon];
\r
988 // clear the screen
\r
990 asm mov dx,SC_INDEX
\r
991 asm mov ax,SC_MAPMASK+15*256 // write through all planes
\r
995 asm mov ax,[viewwidth]
\r
998 asm sub dx,ax // dx = 40-viewwidth/2
\r
1000 asm mov bx,[viewwidth]
\r
1001 asm shr bx,1 // bl = viewwidth/8
\r
1004 asm mov bh,BYTE PTR [viewheight]
\r
1005 asm shr bh,1 // half height
\r
1007 asm mov es,[screenseg]
\r
1008 asm mov di,[bufferofs]
\r
1009 asm mov ax,[ceiling]
\r
1018 asm mov bh,BYTE PTR [viewheight]
\r
1019 asm shr bh,1 // half height
\r
1027 asm jnz bottomloop
\r
1030 //==========================================================================
\r
1033 =====================
\r
1037 =====================
\r
1040 int CalcRotate (objtype *ob)
\r
1042 int angle,viewangle;
\r
1044 // this isn't exactly correct, as it should vary by a trig value,
\r
1045 // but it is close enough with only eight rotations
\r
1047 viewangle = player->angle + (centerx - ob->viewx)/8;
\r
1049 if (ob->obclass == rocketobj || ob->obclass == hrocketobj)
\r
1050 angle = (viewangle-180)- ob->angle;
\r
1052 angle = (viewangle-180)- dirangle[ob->dir];
\r
1055 while (angle>=ANGLES)
\r
1060 if (ob->state->rotate == 2) // 2 rotation pain frame
\r
1061 return 4*(angle/(ANGLES/2)); // seperated by 3 (art layout...)
\r
1063 return angle/(ANGLES/8);
\r
1068 =====================
\r
1072 = Draws all objects that are visable
\r
1074 =====================
\r
1077 #define MAXVISABLE 50
\r
1086 visobj_t vislist[MAXVISABLE],*visptr,*visstep,*farthest;
\r
1088 void DrawScaleds (void)
\r
1090 int i,j,least,numvisable,height;
\r
1092 byte *tilespot,*visspot;
\r
1096 statobj_t *statptr;
\r
1099 visptr = &vislist[0];
\r
1102 // place static objects
\r
1104 for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++)
\r
1106 if ((visptr->shapenum = statptr->shapenum) == -1)
\r
1107 continue; // object has been deleted
\r
1109 if (!*statptr->visspot)
\r
1110 continue; // not visable
\r
1112 if (TransformTile (statptr->tilex,statptr->tiley
\r
1113 ,&visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS)
\r
1115 GetBonus (statptr);
\r
1119 if (!visptr->viewheight)
\r
1120 continue; // to close to the object
\r
1122 if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
\r
1127 // place active objects
\r
1129 for (obj = player->next;obj;obj=obj->next)
\r
1131 if (!(visptr->shapenum = obj->state->shapenum))
\r
1132 continue; // no shape
\r
1134 spotloc = (obj->tilex<<6)+obj->tiley; // optimize: keep in struct?
\r
1135 visspot = &spotvis[0][0]+spotloc;
\r
1136 tilespot = &tilemap[0][0]+spotloc;
\r
1139 // could be in any of the nine surrounding tiles
\r
1142 || ( *(visspot-1) && !*(tilespot-1) )
\r
1143 || ( *(visspot+1) && !*(tilespot+1) )
\r
1144 || ( *(visspot-65) && !*(tilespot-65) )
\r
1145 || ( *(visspot-64) && !*(tilespot-64) )
\r
1146 || ( *(visspot-63) && !*(tilespot-63) )
\r
1147 || ( *(visspot+65) && !*(tilespot+65) )
\r
1148 || ( *(visspot+64) && !*(tilespot+64) )
\r
1149 || ( *(visspot+63) && !*(tilespot+63) ) )
\r
1151 obj->active = true;
\r
1152 TransformActor (obj);
\r
1153 if (!obj->viewheight)
\r
1154 continue; // too close or far away
\r
1156 visptr->viewx = obj->viewx;
\r
1157 visptr->viewheight = obj->viewheight;
\r
1158 if (visptr->shapenum == -1)
\r
1159 visptr->shapenum = obj->temp1; // special shape
\r
1161 if (obj->state->rotate)
\r
1162 visptr->shapenum += CalcRotate (obj);
\r
1164 if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
\r
1166 obj->flags |= FL_VISABLE;
\r
1169 obj->flags &= ~FL_VISABLE;
\r
1173 // draw from back to front
\r
1175 numvisable = visptr-&vislist[0];
\r
1178 return; // no visable objects
\r
1180 for (i = 0; i<numvisable; i++)
\r
1183 for (visstep=&vislist[0] ; visstep<visptr ; visstep++)
\r
1185 height = visstep->viewheight;
\r
1186 if (height < least)
\r
1189 farthest = visstep;
\r
1195 ScaleShape(farthest->viewx,farthest->shapenum,farthest->viewheight);
\r
1197 farthest->viewheight = 32000;
\r
1202 //==========================================================================
\r
1207 = DrawPlayerWeapon
\r
1209 = Draw the player's hands
\r
1214 int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY,SPR_PISTOLREADY
\r
1215 ,SPR_MACHINEGUNREADY,SPR_CHAINREADY};
\r
1217 void DrawPlayerWeapon (void)
\r
1222 if (gamestate.victoryflag)
\r
1224 if (player->state == &s_deathcam && (TimeCount&32) )
\r
1225 SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1);
\r
1230 if (gamestate.weapon != -1)
\r
1232 shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe;
\r
1233 SimpleScaleShape(viewwidth/2,shapenum,viewheight+1);
\r
1236 if (demorecord || demoplayback)
\r
1237 SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1);
\r
1241 //==========================================================================
\r
1245 =====================
\r
1249 =====================
\r
1252 void CalcTics (void)
\r
1254 long newtime,oldtimecount;
\r
1257 // calculate tics since last refresh for adaptive timing
\r
1259 if (lasttimecount > TimeCount)
\r
1260 TimeCount = lasttimecount; // if the game was paused a LONG time
\r
1264 newtime = TimeCount;
\r
1265 tics = newtime-lasttimecount;
\r
1266 } while (!tics); // make sure at least one tic passes
\r
1268 lasttimecount = newtime;
\r
1270 #ifdef FILEPROFILE
\r
1271 strcpy (scratch,"\tTics:");
\r
1272 itoa (tics,str,10);
\r
1273 strcat (scratch,str);
\r
1274 strcat (scratch,"\n");
\r
1275 write (profilehandle,scratch,strlen(scratch));
\r
1280 TimeCount -= (tics-MAXTICS);
\r
1286 //==========================================================================
\r
1290 ========================
\r
1294 ========================
\r
1297 void FixOfs (void)
\r
1299 VW_ScreenToScreen (displayofs,bufferofs,viewwidth/8,viewheight);
\r
1303 //==========================================================================
\r
1307 ====================
\r
1311 ====================
\r
1314 void WallRefresh (void)
\r
1317 // set up variables for this view
\r
1319 viewangle = player->angle;
\r
1320 midangle = viewangle*(FINEANGLES/ANGLES);
\r
1321 viewsin = sintable[viewangle];
\r
1322 viewcos = costable[viewangle];
\r
1323 viewx = player->x - FixedByFrac(focallength,viewcos);
\r
1324 viewy = player->y + FixedByFrac(focallength,viewsin);
\r
1326 focaltx = viewx>>TILESHIFT;
\r
1327 focalty = viewy>>TILESHIFT;
\r
1329 viewtx = player->x >> TILESHIFT;
\r
1330 viewty = player->y >> TILESHIFT;
\r
1332 xpartialdown = viewx&(TILEGLOBAL-1);
\r
1333 xpartialup = TILEGLOBAL-xpartialdown;
\r
1334 ypartialdown = viewy&(TILEGLOBAL-1);
\r
1335 ypartialup = TILEGLOBAL-ypartialdown;
\r
1337 lastside = -1; // the first pixel is on a new wall
\r
1339 ScalePost (); // no more optimization on last post
\r
1342 //==========================================================================
\r
1345 ========================
\r
1349 ========================
\r
1352 void ThreeDRefresh (void)
\r
1356 // this wouldn't need to be done except for my debugger/video wierdness
\r
1357 outportb (SC_INDEX,SC_MAPMASK);
\r
1360 // clear out the traced array
\r
1364 asm mov di,OFFSET spotvis
\r
1366 asm mov cx,2048 // 64*64 / 2
\r
1369 bufferofs += screenofs;
\r
1372 // follow the walls from there to the right, drawwing as we go
\r
1374 VGAClearScreen ();
\r
1379 // draw all the scaled images
\r
1381 DrawScaleds(); // draw scaled stuff
\r
1382 DrawPlayerWeapon (); // draw player's hands
\r
1385 // show screen and time last cycle
\r
1389 FizzleFade(bufferofs,displayofs+screenofs,viewwidth,viewheight,20,false);
\r
1392 lasttimecount = TimeCount = 0; // don't make a big tic count
\r
1396 bufferofs -= screenofs;
\r
1397 displayofs = bufferofs;
\r
1400 asm mov cx,[displayofs]
\r
1401 asm mov dx,3d4h // CRTC address register
\r
1402 asm mov al,0ch // start address high register
\r
1406 asm out dx,al // set the high byte
\r
1409 bufferofs += SCREENSIZE;
\r
1410 if (bufferofs > PAGE3START)
\r
1411 bufferofs = PAGE1START;
\r
1418 //===========================================================================
\r