WL_DR_A.ASM (14472B)
1 IDEAL 2 MODEL MEDIUM,C 3 P286 4 5 SCREENSEG = 0a000h 6 7 FINEANGLES = 3600 8 DEG90 = 900 9 DEG180 = 1800 10 DEG270 = 2700 11 DEG360 = 3600 12 13 OP_JLE = 07eh 14 OP_JGE = 07dh 15 16 EXTRN finetangent:DWORD ; far array, starts at offset 0 17 18 EXTRN HitHorizWall:FAR 19 EXTRN HitVertWall:FAR 20 EXTRN HitHorizDoor:FAR 21 EXTRN HitVertDoor:FAR 22 EXTRN HitHorizPWall:FAR 23 EXTRN HitVertPWall:FAR 24 25 26 DATASEG 27 28 EXTRN viewwidth:WORD 29 30 EXTRN tilemap:BYTE 31 EXTRN spotvis:BYTE 32 EXTRN pixelangle:WORD 33 34 35 EXTRN midangle:WORD 36 EXTRN angle:WORD 37 38 EXTRN focaltx:WORD 39 EXTRN focalty:WORD 40 EXTRN viewtx:WORD 41 EXTRN viewty:WORD 42 EXTRN viewx:DWORD 43 EXTRN viewy:DWORD 44 45 EXTRN xpartialup:WORD 46 EXTRN ypartialup:WORD 47 EXTRN xpartialdown:WORD 48 EXTRN ypartialdown:WORD 49 50 EXTRN tilehit:WORD 51 EXTRN pixx:WORD 52 EXTRN wallheight:WORD ; array of VIEWWIDTH entries 53 54 EXTRN xtile:WORD 55 EXTRN ytile:WORD 56 EXTRN xtilestep:WORD 57 EXTRN ytilestep:WORD 58 EXTRN xintercept:DWORD 59 EXTRN yintercept:DWORD 60 EXTRN xstep:DWORD 61 EXTRN ystep:DWORD 62 63 EXTRN doorposition:WORD ; table of door position values 64 65 66 EXTRN pwallpos:WORD ; amound a pushable wall has been moved 67 68 CODESEG 69 70 ;------------------- 71 ; 72 ; xpartialbyystep 73 ; 74 ; multiplies long [ystep] (possibly negative), by word [xpartial] (in BX) 75 ; 76 ; returns dx:ax 77 ; trashes bx,cx,di 78 ; 79 ;------------------- 80 81 PROC xpartialbyystep NEAR 82 ; 83 ; setup 84 ; 85 mov ax,[WORD ystep] 86 mov cx,[WORD ystep+2] 87 or cx,cx ; is ystep negatice? 88 jns @@multpos 89 ; 90 ; multiply negative cx:ax by bx 91 ; 92 neg cx 93 neg ax 94 sbb cx,0 95 96 mul bx ; fraction*fraction 97 mov di,dx ; di is low word of result 98 mov ax,cx ; 99 mul bx ; units*fraction 100 add ax,di 101 adc dx,0 102 103 neg dx 104 neg ax 105 sbb dx,0 106 ret 107 ; 108 ; multiply positive cx:ax by bx 109 ; 110 EVEN 111 @@multpos: 112 mul bx ; fraction*fraction 113 mov di,dx ; di is low word of result 114 mov ax,cx ; 115 mul bx ; units*fraction 116 add ax,di 117 adc dx,0 118 119 ret 120 121 ENDP 122 123 124 125 ;------------------- 126 ; 127 ; ypartialbyxstep 128 ; 129 ; multiplies long [xstep] (possibly negative), by word [ypartial] (in BP) 130 ; 131 ; returns dx:ax 132 ; trashes cx,di,bp 133 ; 134 ;------------------- 135 136 PROC ypartialbyxstep NEAR 137 ; 138 ; setup 139 ; 140 mov ax,[WORD xstep] 141 mov cx,[WORD xstep+2] 142 or cx,cx ; is ystep negatice? 143 jns @@multpos 144 ; 145 ; multiply negative cx:ax by bx 146 ; 147 neg cx 148 neg ax 149 sbb cx,0 150 151 mul bp ; fraction*fraction 152 mov di,dx ; di is low word of result 153 mov ax,cx ; 154 mul bp ; units*fraction 155 add ax,di 156 adc dx,0 157 158 neg dx 159 neg ax 160 sbb dx,0 161 ret 162 ; 163 ; multiply positive cx:ax by bx 164 ; 165 EVEN 166 @@multpos: 167 mul bp ; fraction*fraction 168 mov di,dx ; di is low word of result 169 mov ax,cx ; 170 mul bp ; units*fraction 171 add ax,di 172 adc dx,0 173 ret 174 175 ENDP 176 177 178 ;============================ 179 ; 180 ; AsmRefresh 181 ; 182 ; 183 ;============================ 184 185 PROC AsmRefresh 186 PUBLIC AsmRefresh 187 188 push si 189 push di 190 push bp 191 192 mov [pixx],0 193 ;--------------------------------------------------------------------------- 194 ; 195 ; Setup to trace a ray through pixx view pixel 196 ; 197 ; CX : angle of the ray through pixx 198 ; ES : points to segment of finetangent array for this block of code 199 ; 200 ; Upon entrance to initialize block 201 ; 202 ; BX : xpartial 203 ; BP : ypartial 204 ; 205 ;--------------------------------------------------------------------------- 206 EVEN 207 pixxloop: 208 mov ax,SEG finetangent 209 mov es,ax 210 mov cx,[midangle] ; center of view area 211 mov bx,[pixx] 212 shl bx,1 213 add cx,[pixelangle+bx] ; delta for this pixel 214 cmp cx,0 215 jge not0 216 ;---------- 217 ; 218 ; -90 - -1 degree arc 219 ; 220 ;---------- 221 add cx,FINEANGLES ; -90 is the same as 270 222 jmp entry360 223 224 not0: 225 cmp cx,DEG90 226 jge not90 227 ;---------- 228 ; 229 ; 0-89 degree arc 230 ; 231 ;---------- 232 entry90: 233 mov [xtilestep],1 ; xtilestep = 1 234 mov [ytilestep],-1 ; ytilestep = -1 235 mov [BYTE cs:horizop],OP_JGE ; patch a jge in 236 mov [BYTE cs:vertop],OP_JLE ; patch a jle in 237 mov bx,DEG90-1 238 sub bx,cx 239 shl bx,2 240 mov ax,[es:bx] 241 mov dx,[es:bx+2] 242 mov [WORD xstep],ax 243 mov [WORD xstep+2],dx ; xstep = finetangent[DEG90-1-angle] 244 mov bx,cx 245 shl bx,2 246 mov ax,[es:bx] 247 mov dx,[es:bx+2] 248 neg dx 249 neg ax 250 sbb dx,0 251 mov [WORD ystep],ax 252 mov [WORD ystep+2],dx ; ystep = -finetangent[angle] 253 254 mov bx,[xpartialup] ; xpartial = xpartialup 255 mov bp,[ypartialdown] ; ypartial = ypartialdown 256 jmp initvars 257 258 not90: 259 cmp cx,DEG180 260 jge not180 261 ;---------- 262 ; 263 ; 90-179 degree arc 264 ; 265 ;---------- 266 mov ax,-1 267 mov [xtilestep],ax ; xtilestep = -1 268 mov [ytilestep],ax ; ytilestep = -1 269 mov [BYTE cs:horizop],OP_JLE ; patch a jle in 270 mov [BYTE cs:vertop],OP_JLE ; patch a jle in 271 272 mov bx,cx 273 shl bx,2 274 mov ax,[es:bx-DEG90*4] 275 mov dx,[es:bx+2-DEG90*4] 276 neg dx 277 neg ax 278 sbb dx,0 279 mov [WORD xstep],ax 280 mov [WORD xstep+2],dx ; xstep = -finetangent[angle-DEG90] 281 mov bx,DEG180-1 282 sub bx,cx 283 shl bx,2 284 mov ax,[es:bx] 285 mov dx,[es:bx+2] 286 neg dx 287 neg ax 288 sbb dx,0 289 mov [WORD ystep],ax 290 mov [WORD ystep+2],dx ; ystep = -finetangent[DEG180-1-angle] 291 292 mov bx,[xpartialdown] ; xpartial = xpartialdown 293 mov bp,[ypartialdown] ; ypartial = ypartialdown 294 jmp initvars 295 296 not180: 297 cmp cx,DEG270 298 jge not270 299 ;---------- 300 ; 301 ; 180-269 degree arc 302 ; 303 ;---------- 304 mov [xtilestep],-1 ; xtilestep = -1 305 mov [ytilestep],1 ; ytilestep = 1 306 mov [BYTE cs:horizop],OP_JLE ; patch a jle in 307 mov [BYTE cs:vertop],OP_JGE ; patch a jge in 308 309 mov bx,DEG270-1 310 sub bx,cx 311 shl bx,2 312 mov ax,[es:bx] 313 mov dx,[es:bx+2] 314 neg dx 315 neg ax 316 sbb dx,0 317 mov [WORD xstep],ax 318 mov [WORD xstep+2],dx ; xstep = -finetangent[DEG270-1-angle] 319 mov bx,cx 320 shl bx,2 321 mov ax,[es:bx-DEG180*4] 322 mov dx,[es:bx+2-DEG180*4] 323 mov [WORD ystep],ax 324 mov [WORD ystep+2],dx ; ystep = finetangent[angle-DEG180] 325 326 mov bx,[xpartialdown] ; xpartial = xpartialdown 327 mov bp,[ypartialup] ; ypartial = ypartialup 328 jmp initvars 329 330 331 not270: 332 cmp cx,DEG360 333 jge not360 334 ;---------- 335 ; 336 ; 270-359 degree arc 337 ; 338 ;---------- 339 entry360: 340 mov ax,1 341 mov [xtilestep],ax ; xtilestep = 1 342 mov [ytilestep],ax ; ytilestep = 1 343 mov [BYTE cs:horizop],OP_JGE ; patch a jge in 344 mov [BYTE cs:vertop],OP_JGE ; patch a jge in 345 346 mov bx,cx 347 shl bx,2 348 mov ax,[es:bx-DEG270*4] 349 mov dx,[es:bx+2-DEG270*4] 350 mov [WORD xstep],ax 351 mov [WORD xstep+2],dx ; xstep = finetangent[angle-DEG270] 352 mov bx,DEG360-1 353 sub bx,cx 354 shl bx,2 355 mov ax,[es:bx] 356 mov dx,[es:bx+2] 357 mov [WORD ystep],ax 358 mov [WORD ystep+2],dx ; ystep = finetangent[DEG360-1-angle] 359 360 mov bx,[xpartialup] ; xpartial = xpartialup 361 mov bp,[ypartialup] ; ypartial = ypartialup 362 jmp initvars 363 364 365 not360: 366 ;---------- 367 ; 368 ; 360-449 degree arc 369 ; 370 ;---------- 371 sub cx,FINEANGLES ; -449 is the same as 89 372 jmp entry90 373 374 ;--------------------------------------------------------------------------- 375 ; 376 ; initialise variables for intersection testing 377 ; 378 ;--------------------------------------------------------------------------- 379 initvars: 380 call NEAR xpartialbyystep ; xpartial is in BX 381 add ax,[WORD viewy] 382 adc dx,[WORD viewy+2] 383 mov [WORD yintercept],ax 384 mov [WORD yintercept+2],dx 385 386 mov si,[focaltx] 387 add si,[xtilestep] 388 mov [xtile],si ; xtile = focaltx+xtilestep 389 shl si,6 390 add si,dx ; xspot = (xtile<<6) + yinttile 391 392 393 call NEAR ypartialbyxstep ; ypartial is in BP 394 add ax,[WORD viewx] 395 adc dx,[WORD viewx+2] 396 mov [WORD xintercept],ax 397 mov cx,dx 398 399 mov bx,[focalty] 400 add bx,[ytilestep] 401 mov bp,bx ; ytile = focalty+ytilestep 402 mov di,dx 403 shl di,6 404 add di,bx ; yspot = (xinttile<<6) + ytile 405 406 mov bx,[xtile] 407 mov dx,[WORD yintercept+2] 408 mov ax,SCREENSEG 409 mov es,ax ; faster than mov es,[screenseg] 410 411 412 ;--------------------------------------------------------------------------- 413 ; 414 ; trace along this angle until we hit a wall 415 ; 416 ; CORE LOOP! 417 ; 418 ; All variables are killed when a wall is hit 419 ; 420 ; AX : scratch 421 ; BX : xtile 422 ; CX : high word of xintercept 423 ; DX : high word of yintercept 424 ; SI : xspot (yinttile<<6)+xtile (index into tilemap and spotvis) 425 ; DI : yspot (xinttile<<6)+ytile (index into tilemap and spotvis) 426 ; BP : ytile 427 ; ES : screenseg 428 ; 429 ;--------------------------------------------------------------------------- 430 431 ;----------- 432 ; 433 ; check intersections with vertical walls 434 ; 435 ;----------- 436 437 EVEN 438 vertcheck: 439 cmp dx,bp 440 vertop: ; 0x7e = jle (ytilestep==-1) 441 jle horizentry ; 0x7d = jge (ytilestep==1) 442 vertentry: 443 test [BYTE tilemap+si],0ffh ; tilehit = *((byte *)tilemap+xspot); 444 jnz hitvert 445 passvert: 446 mov [BYTE spotvis+si],1 ; *((byte *)spotvis+xspot) = true; 447 add bx,[xtilestep] ; xtile+=xtilestep 448 mov ax,[WORD ystep] 449 add [WORD yintercept],ax ; yintercept += ystep 450 adc dx,[WORD ystep+2] 451 mov si,bx 452 shl si,6 453 add si,dx ; xspot = (xtile<<6)+yinttile 454 jmp vertcheck 455 456 EVEN 457 hitvert: 458 mov al,[BYTE tilemap+si] ; tilehit = *((byte *)tilemap+xspot); 459 mov [BYTE tilehit],al 460 or al,al ; set flags 461 jns notvertdoor 462 jmp vertdoor 463 notvertdoor: 464 mov [WORD xintercept],0 465 mov [WORD xintercept+2],bx 466 mov [xtile],bx 467 mov [WORD yintercept+2],dx 468 mov [ytile],dx 469 call FAR HitVertWall 470 jmp nextpix 471 472 473 ;----------- 474 ; 475 ; check intersections with horizontal walls 476 ; 477 ;----------- 478 EVEN 479 horizcheck: 480 cmp cx,bx 481 horizop: ; 0x7e = jle (xtilestep==-1) 482 jle vertentry ; 0x7d = jge (xtilestep==1) 483 horizentry: 484 test [BYTE tilemap+di],0ffh ; tilehit = *((byte *)tilemap+yspot); 485 jnz hithoriz 486 passhoriz: 487 mov [BYTE spotvis+di],1 ; *((byte *)spotvis+yspot) = true; 488 add bp,[ytilestep] ; ytile+=ytilestep 489 mov ax,[WORD xstep] 490 add [WORD xintercept],ax ; xintercept += xstep 491 adc cx,[WORD xstep+2] 492 mov di,cx 493 shl di,6 494 add di,bp ; yspot = (xinttile<<6)+ytile 495 jmp horizcheck 496 497 EVEN 498 hithoriz: 499 mov al,[BYTE tilemap+di] ; tilehit = *((byte *)tilemap+yspot); 500 mov [BYTE tilehit],al 501 or al,al ; set flags 502 js horizdoor 503 mov [WORD xintercept+2],cx 504 mov [xtile],cx 505 mov [WORD yintercept],0 506 mov [WORD yintercept+2],bp 507 mov [ytile],bp 508 call FAR HitHorizWall 509 jmp nextpix 510 511 ;--------------------------------------------------------------------------- 512 ; 513 ; next pixel over 514 ; 515 ;--------------------------------------------------------------------------- 516 517 nextpix: 518 mov ax,[pixx] 519 inc ax 520 mov [pixx],ax 521 cmp ax,[viewwidth] 522 jge done 523 jmp pixxloop 524 done: 525 pop bp 526 pop di 527 pop si 528 retf 529 530 ;=========================================================================== 531 532 ;============= 533 ; 534 ; hit a special horizontal wall, so find which coordinate a door would be 535 ; intersected at, and check to see if the door is open past that point 536 ; 537 ;============= 538 horizdoor: 539 mov [xtile],bx ; save off live register variables 540 mov [WORD yintercept+2],dx 541 542 test al,040h ; both high bits set == pushable wall 543 jnz horizpushwall 544 545 mov bx,ax 546 and bx,7fh ; strip high bit 547 shl bx,1 ; index into word width door table 548 549 mov ax,[WORD xstep] 550 mov dx,[WORD xstep+2] 551 sar dx,1 552 rcr ax,1 ; half a step gets to door position 553 554 add ax,[WORD xintercept] ; add half step to current intercept pos 555 adc dx,cx ; CX hold high word of xintercept 556 557 cmp cx,dx ; is it still in the same tile? 558 je hithmid 559 ; 560 ; midpoint is outside tile, so it hit the side of the wall before a door 561 ; 562 continuehoriz: 563 mov bx,[xtile] ; reload register variables 564 mov dx,[WORD yintercept+2] 565 jmp passhoriz ; continue tracing 566 ; 567 ; the trace hit the door plane at pixel position AX, see if the door is 568 ; closed that much 569 ; 570 hithmid: 571 cmp ax,[doorposition+bx] ; position of leading edge of door 572 jb continuehoriz 573 ; 574 ; draw the door 575 ; 576 mov [WORD xintercept],ax ; save pixel intercept position 577 mov [WORD xintercept+2],cx 578 579 mov [WORD yintercept],8000h ; intercept in middle of tile 580 mov [WORD yintercept+2],bp 581 582 call FAR HitHorizDoor 583 jmp nextpix 584 585 ;============ 586 ; 587 ; hit a sliding horizontal wall 588 ; 589 ;============ 590 591 horizpushwall: 592 mov ax,[WORD xstep+2] ; multiply xstep by pwallmove (0-63) 593 mul [pwallpos] 594 mov bx,ax 595 mov ax,[WORD xstep] 596 mul [pwallpos] 597 add dx,bx 598 599 sar dx,1 ; then divide by 64 to accomplish a 600 rcr ax,1 ; fixed point multiplication 601 sar dx,1 602 rcr ax,1 603 sar dx,1 604 rcr ax,1 605 sar dx,1 606 rcr ax,1 607 sar dx,1 608 rcr ax,1 609 sar dx,1 610 rcr ax,1 611 612 add ax,[WORD xintercept] ; add partial step to current intercept 613 adc dx,cx ; CX hold high word of xintercept 614 615 cmp cx,dx ; is it still in the same tile? 616 jne continuehoriz ; no, it hit the side 617 618 ; 619 ; draw the pushable wall at the new height 620 ; 621 mov [WORD xintercept],ax ; save pixel intercept position 622 mov [WORD xintercept+2],dx 623 624 mov [WORD yintercept+2],bp 625 mov [WORD yintercept],0 626 627 call FAR HitHorizPWall 628 jmp nextpix 629 630 631 632 ;=========================================================================== 633 634 ;============= 635 ; 636 ; hit a special vertical wall, so find which coordinate a door would be 637 ; intersected at, and check to see if the door is open past that point 638 ; 639 ;============= 640 vertdoor: 641 mov [xtile],bx ; save off live register variables 642 mov [WORD yintercept+2],dx 643 644 test al,040h ; both high bits set == pushable wall 645 jnz vertpushwall 646 647 mov bx,ax 648 and bx,7fh ; strip high bit 649 shl bx,1 ; index into word width doorposition 650 651 mov ax,[WORD ystep] 652 mov dx,[WORD ystep+2] 653 sar dx,1 654 rcr ax,1 ; half a step gets to door position 655 656 add ax,[WORD yintercept] ; add half step to current intercept pos 657 adc dx,[WORD yintercept+2] 658 659 cmp [WORD yintercept+2],dx ; is it still in the same tile? 660 je hitvmid 661 ; 662 ; midpoint is outside tile, so it hit the side of the wall before a door 663 ; 664 continuevert: 665 mov bx,[xtile] ; reload register variables 666 mov dx,[WORD yintercept+2] 667 jmp passvert ; continue tracing 668 ; 669 ; the trace hit the door plane at pixel position AX, see if the door is 670 ; closed that much 671 ; 672 hitvmid: 673 cmp ax,[doorposition+bx] ; position of leading edge of door 674 jb continuevert 675 ; 676 ; draw the door 677 ; 678 mov [WORD yintercept],ax ; save pixel intercept position 679 mov [WORD xintercept],8000h ; intercept in middle of tile 680 mov ax,[xtile] 681 mov [WORD xintercept+2],ax 682 683 call FAR HitVertDoor 684 jmp nextpix 685 686 ;============ 687 ; 688 ; hit a sliding vertical wall 689 ; 690 ;============ 691 692 vertpushwall: 693 mov ax,[WORD ystep+2] ; multiply ystep by pwallmove (0-63) 694 mul [pwallpos] 695 mov bx,ax 696 mov ax,[WORD ystep] 697 mul [pwallpos] 698 add dx,bx 699 700 sar dx,1 ; then divide by 64 to accomplish a 701 rcr ax,1 ; fixed point multiplication 702 sar dx,1 703 rcr ax,1 704 sar dx,1 705 rcr ax,1 706 sar dx,1 707 rcr ax,1 708 sar dx,1 709 rcr ax,1 710 sar dx,1 711 rcr ax,1 712 713 add ax,[WORD yintercept] ; add partial step to current intercept 714 adc dx,[WORD yintercept+2] 715 716 cmp [WORD yintercept+2],dx ; is it still in the same tile? 717 jne continuevert ; no, it hit the side 718 719 ; 720 ; draw the pushable wall at the new height 721 ; 722 mov [WORD yintercept],ax ; save pixel intercept position 723 mov [WORD yintercept+2],dx 724 725 mov bx,[xtile] 726 mov [WORD xintercept+2],bx 727 mov [WORD xintercept],0 728 729 call FAR HitVertPWall 730 jmp nextpix 731 732 733 734 ENDP 735 736 737 END 738 739