16 EXTRN finetangent:DWORD ; far array, starts at offset 0
\r
18 EXTRN HitHorizWall:FAR
\r
19 EXTRN HitVertWall:FAR
\r
20 EXTRN HitHorizDoor:FAR
\r
21 EXTRN HitVertDoor:FAR
\r
22 EXTRN HitHorizPWall:FAR
\r
23 EXTRN HitVertPWall:FAR
\r
28 EXTRN viewwidth:WORD
\r
32 EXTRN pixelangle:WORD
\r
45 EXTRN xpartialup:WORD
\r
46 EXTRN ypartialup:WORD
\r
47 EXTRN xpartialdown:WORD
\r
48 EXTRN ypartialdown:WORD
\r
52 EXTRN wallheight:WORD ; array of VIEWWIDTH entries
\r
56 EXTRN xtilestep:WORD
\r
57 EXTRN ytilestep:WORD
\r
58 EXTRN xintercept:DWORD
\r
59 EXTRN yintercept:DWORD
\r
63 EXTRN doorposition:WORD ; table of door position values
\r
66 EXTRN pwallpos:WORD ; amound a pushable wall has been moved
\r
70 ;-------------------
\r
74 ; multiplies long [ystep] (possibly negative), by word [xpartial] (in BX)
\r
79 ;-------------------
\r
81 PROC xpartialbyystep NEAR
\r
86 mov cx,[WORD ystep+2]
\r
87 or cx,cx ; is ystep negatice?
\r
90 ; multiply negative cx:ax by bx
\r
96 mul bx ; fraction*fraction
\r
97 mov di,dx ; di is low word of result
\r
99 mul bx ; units*fraction
\r
108 ; multiply positive cx:ax by bx
\r
112 mul bx ; fraction*fraction
\r
113 mov di,dx ; di is low word of result
\r
115 mul bx ; units*fraction
\r
125 ;-------------------
\r
129 ; multiplies long [xstep] (possibly negative), by word [ypartial] (in BP)
\r
134 ;-------------------
\r
136 PROC ypartialbyxstep NEAR
\r
140 mov ax,[WORD xstep]
\r
141 mov cx,[WORD xstep+2]
\r
142 or cx,cx ; is ystep negatice?
\r
145 ; multiply negative cx:ax by bx
\r
151 mul bp ; fraction*fraction
\r
152 mov di,dx ; di is low word of result
\r
154 mul bp ; units*fraction
\r
163 ; multiply positive cx:ax by bx
\r
167 mul bp ; fraction*fraction
\r
168 mov di,dx ; di is low word of result
\r
170 mul bp ; units*fraction
\r
178 ;============================
\r
183 ;============================
\r
193 ;---------------------------------------------------------------------------
\r
195 ; Setup to trace a ray through pixx view pixel
\r
197 ; CX : angle of the ray through pixx
\r
198 ; ES : points to segment of finetangent array for this block of code
\r
200 ; Upon entrance to initialize block
\r
205 ;---------------------------------------------------------------------------
\r
208 mov ax,SEG finetangent
\r
210 mov cx,[midangle] ; center of view area
\r
213 add cx,[pixelangle+bx] ; delta for this pixel
\r
218 ; -90 - -1 degree arc
\r
221 add cx,FINEANGLES ; -90 is the same as 270
\r
233 mov [xtilestep],1 ; xtilestep = 1
\r
234 mov [ytilestep],-1 ; ytilestep = -1
\r
235 mov [BYTE cs:horizop],OP_JGE ; patch a jge in
\r
236 mov [BYTE cs:vertop],OP_JLE ; patch a jle in
\r
246 mov [WORD xstep],ax
\r
247 mov [WORD xstep+2],dx ; xstep = finetangent[DEG90-1-angle]
\r
259 mov [WORD ystep],ax
\r
260 mov [WORD ystep+2],dx ; ystep = -finetangent[angle]
\r
262 mov bx,[xpartialup] ; xpartial = xpartialup
\r
263 mov bp,[ypartialdown] ; ypartial = ypartialdown
\r
271 ; 90-179 degree arc
\r
275 mov [xtilestep],ax ; xtilestep = -1
\r
276 mov [ytilestep],ax ; ytilestep = -1
\r
277 mov [BYTE cs:horizop],OP_JLE ; patch a jle in
\r
278 mov [BYTE cs:vertop],OP_JLE ; patch a jle in
\r
286 mov ax,[es:bx-DEG90*4]
\r
287 mov dx,[es:bx+2-DEG90*4]
\r
291 mov [WORD xstep],ax
\r
292 mov [WORD xstep+2],dx ; xstep = -finetangent[angle-DEG90]
\r
305 mov [WORD ystep],ax
\r
306 mov [WORD ystep+2],dx ; ystep = -finetangent[DEG180-1-angle]
\r
308 mov bx,[xpartialdown] ; xpartial = xpartialdown
\r
309 mov bp,[ypartialdown] ; ypartial = ypartialdown
\r
317 ; 180-269 degree arc
\r
320 mov [xtilestep],-1 ; xtilestep = -1
\r
321 mov [ytilestep],1 ; ytilestep = 1
\r
322 mov [BYTE cs:horizop],OP_JLE ; patch a jle in
\r
323 mov [BYTE cs:vertop],OP_JGE ; patch a jge in
\r
337 mov [WORD xstep],ax
\r
338 mov [WORD xstep+2],dx ; xstep = -finetangent[DEG270-1-angle]
\r
345 mov ax,[es:bx-DEG180*4]
\r
346 mov dx,[es:bx+2-DEG180*4]
\r
347 mov [WORD ystep],ax
\r
348 mov [WORD ystep+2],dx ; ystep = finetangent[angle-DEG180]
\r
350 mov bx,[xpartialdown] ; xpartial = xpartialdown
\r
351 mov bp,[ypartialup] ; ypartial = ypartialup
\r
360 ; 270-359 degree arc
\r
365 mov [xtilestep],ax ; xtilestep = 1
\r
366 mov [ytilestep],ax ; ytilestep = 1
\r
367 mov [BYTE cs:horizop],OP_JGE ; patch a jge in
\r
368 mov [BYTE cs:vertop],OP_JGE ; patch a jge in
\r
376 mov ax,[es:bx-DEG270*4]
\r
377 mov dx,[es:bx+2-DEG270*4]
\r
378 mov [WORD xstep],ax
\r
379 mov [WORD xstep+2],dx ; xstep = finetangent[angle-DEG270]
\r
389 mov [WORD ystep],ax
\r
390 mov [WORD ystep+2],dx ; ystep = finetangent[DEG360-1-angle]
\r
392 mov bx,[xpartialup] ; xpartial = xpartialup
\r
393 mov bp,[ypartialup] ; ypartial = ypartialup
\r
400 ; 360-449 degree arc
\r
403 sub cx,FINEANGLES ; -449 is the same as 89
\r
406 ;---------------------------------------------------------------------------
\r
408 ; initialise variables for intersection testing
\r
410 ;---------------------------------------------------------------------------
\r
412 call NEAR xpartialbyystep ; xpartial is in BX
\r
413 add ax,[WORD viewy]
\r
414 adc dx,[WORD viewy+2]
\r
415 mov [WORD yintercept],ax
\r
416 mov [WORD yintercept+2],dx
\r
420 mov [xtile],si ; xtile = focaltx+xtilestep
\r
428 add si,dx ; xspot = (xtile<<6) + yinttile
\r
431 call NEAR ypartialbyxstep ; ypartial is in BP
\r
432 add ax,[WORD viewx]
\r
433 adc dx,[WORD viewx+2]
\r
434 mov [WORD xintercept],ax
\r
439 mov bp,bx ; ytile = focalty+ytilestep
\r
448 add di,bx ; yspot = (xinttile<<6) + ytile
\r
451 mov dx,[WORD yintercept+2]
\r
453 mov es,ax ; faster than mov es,[screenseg]
\r
456 ;---------------------------------------------------------------------------
\r
458 ; trace along this angle until we hit a wall
\r
462 ; All variables are killed when a wall is hit
\r
466 ; CX : high word of xintercept
\r
467 ; DX : high word of yintercept
\r
468 ; SI : xspot (yinttile<<6)+xtile (index into tilemap and spotvis)
\r
469 ; DI : yspot (xinttile<<6)+ytile (index into tilemap and spotvis)
\r
473 ;---------------------------------------------------------------------------
\r
477 ; check intersections with vertical walls
\r
484 vertop: ; 0x7e = jle (ytilestep==-1)
\r
485 jle horizentry ; 0x7d = jge (ytilestep==1)
\r
487 test [BYTE tilemap+si],0ffh ; tilehit = *((byte *)tilemap+xspot);
\r
490 mov [BYTE spotvis+si],1 ; *((byte *)spotvis+xspot) = true;
\r
491 add bx,[xtilestep] ; xtile+=xtilestep
\r
492 mov ax,[WORD ystep]
\r
493 add [WORD yintercept],ax ; yintercept += ystep
\r
494 adc dx,[WORD ystep+2]
\r
503 add si,dx ; xspot = (xtile<<6)+yinttile
\r
508 mov al,[BYTE tilemap+si] ; tilehit = *((byte *)tilemap+xspot);
\r
509 mov [BYTE tilehit],al
\r
510 or al,al ; set flags
\r
514 mov [WORD xintercept],0
\r
515 mov [WORD xintercept+2],bx
\r
517 mov [WORD yintercept+2],dx
\r
519 call FAR HitVertWall
\r
525 ; check intersections with horizontal walls
\r
531 horizop: ; 0x7e = jle (xtilestep==-1)
\r
532 jle vertentry ; 0x7d = jge (xtilestep==1)
\r
534 test [BYTE tilemap+di],0ffh ; tilehit = *((byte *)tilemap+yspot);
\r
537 mov [BYTE spotvis+di],1 ; *((byte *)spotvis+yspot) = true;
\r
538 add bp,[ytilestep] ; ytile+=ytilestep
\r
539 mov ax,[WORD xstep]
\r
540 add [WORD xintercept],ax ; xintercept += xstep
\r
541 adc cx,[WORD xstep+2]
\r
550 add di,bp ; yspot = (xinttile<<6)+ytile
\r
555 mov al,[BYTE tilemap+di] ; tilehit = *((byte *)tilemap+yspot);
\r
556 mov [BYTE tilehit],al
\r
557 or al,al ; set flags
\r
559 mov [WORD xintercept+2],cx
\r
561 mov [WORD yintercept],0
\r
562 mov [WORD yintercept+2],bp
\r
564 call FAR HitHorizWall
\r
567 ;---------------------------------------------------------------------------
\r
571 ;---------------------------------------------------------------------------
\r
586 ;===========================================================================
\r
590 ; hit a special horizontal wall, so find which coordinate a door would be
\r
591 ; intersected at, and check to see if the door is open past that point
\r
595 mov [xtile],bx ; save off live register variables
\r
596 mov [WORD yintercept+2],dx
\r
598 test al,040h ; both high bits set == pushable wall
\r
602 and bx,7fh ; strip high bit
\r
603 shl bx,1 ; index into word width door table
\r
605 mov ax,[WORD xstep]
\r
606 mov dx,[WORD xstep+2]
\r
608 rcr ax,1 ; half a step gets to door position
\r
610 add ax,[WORD xintercept] ; add half step to current intercept pos
\r
611 adc dx,cx ; CX hold high word of xintercept
\r
613 cmp cx,dx ; is it still in the same tile?
\r
616 ; midpoint is outside tile, so it hit the side of the wall before a door
\r
619 mov bx,[xtile] ; reload register variables
\r
620 mov dx,[WORD yintercept+2]
\r
621 jmp passhoriz ; continue tracing
\r
623 ; the trace hit the door plane at pixel position AX, see if the door is
\r
627 cmp ax,[doorposition+bx] ; position of leading edge of door
\r
632 mov [WORD xintercept],ax ; save pixel intercept position
\r
633 mov [WORD xintercept+2],cx
\r
635 mov [WORD yintercept],8000h ; intercept in middle of tile
\r
636 mov [WORD yintercept+2],bp
\r
638 call FAR HitHorizDoor
\r
643 ; hit a sliding horizontal wall
\r
648 mov ax,[WORD xstep+2] ; multiply xstep by pwallmove (0-63)
\r
651 mov ax,[WORD xstep]
\r
655 sar dx,1 ; then divide by 64 to accomplish a
\r
656 rcr ax,1 ; fixed point multiplication
\r
668 add ax,[WORD xintercept] ; add partial step to current intercept
\r
669 adc dx,cx ; CX hold high word of xintercept
\r
671 cmp cx,dx ; is it still in the same tile?
\r
672 jne continuehoriz ; no, it hit the side
\r
675 ; draw the pushable wall at the new height
\r
677 mov [WORD xintercept],ax ; save pixel intercept position
\r
678 mov [WORD xintercept+2],dx
\r
680 mov [WORD yintercept+2],bp
\r
681 mov [WORD yintercept],0
\r
683 call FAR HitHorizPWall
\r
688 ;===========================================================================
\r
692 ; hit a special vertical wall, so find which coordinate a door would be
\r
693 ; intersected at, and check to see if the door is open past that point
\r
697 mov [xtile],bx ; save off live register variables
\r
698 mov [WORD yintercept+2],dx
\r
700 test al,040h ; both high bits set == pushable wall
\r
704 and bx,7fh ; strip high bit
\r
705 shl bx,1 ; index into word width doorposition
\r
707 mov ax,[WORD ystep]
\r
708 mov dx,[WORD ystep+2]
\r
710 rcr ax,1 ; half a step gets to door position
\r
712 add ax,[WORD yintercept] ; add half step to current intercept pos
\r
713 adc dx,[WORD yintercept+2]
\r
715 cmp [WORD yintercept+2],dx ; is it still in the same tile?
\r
718 ; midpoint is outside tile, so it hit the side of the wall before a door
\r
721 mov bx,[xtile] ; reload register variables
\r
722 mov dx,[WORD yintercept+2]
\r
723 jmp passvert ; continue tracing
\r
725 ; the trace hit the door plane at pixel position AX, see if the door is
\r
729 cmp ax,[doorposition+bx] ; position of leading edge of door
\r
734 mov [WORD yintercept],ax ; save pixel intercept position
\r
735 mov [WORD xintercept],8000h ; intercept in middle of tile
\r
737 mov [WORD xintercept+2],ax
\r
739 call FAR HitVertDoor
\r
744 ; hit a sliding vertical wall
\r
749 mov ax,[WORD ystep+2] ; multiply ystep by pwallmove (0-63)
\r
752 mov ax,[WORD ystep]
\r
756 sar dx,1 ; then divide by 64 to accomplish a
\r
757 rcr ax,1 ; fixed point multiplication
\r
769 add ax,[WORD yintercept] ; add partial step to current intercept
\r
770 adc dx,[WORD yintercept+2]
\r
772 cmp [WORD yintercept+2],dx ; is it still in the same tile?
\r
773 jne continuevert ; no, it hit the side
\r
776 ; draw the pushable wall at the new height
\r
778 mov [WORD yintercept],ax ; save pixel intercept position
\r
779 mov [WORD yintercept+2],dx
\r
782 mov [WORD xintercept+2],bx
\r
783 mov [WORD xintercept],0
\r
785 call FAR HitVertPWall
\r