--- /dev/null
+ IDEAL\r
+ MODEL MEDIUM,C\r
+ P286\r
+\r
+SCREENSEG = 0a000h\r
+\r
+FINEANGLES = 3600\r
+DEG90 = 900\r
+DEG180 = 1800\r
+DEG270 = 2700\r
+DEG360 = 3600\r
+\r
+OP_JLE = 07eh\r
+OP_JGE = 07dh\r
+\r
+EXTRN finetangent:DWORD ; far array, starts at offset 0\r
+\r
+EXTRN HitHorizWall:FAR\r
+EXTRN HitVertWall:FAR\r
+EXTRN HitHorizDoor:FAR\r
+EXTRN HitVertDoor:FAR\r
+EXTRN HitHorizPWall:FAR\r
+EXTRN HitVertPWall:FAR\r
+\r
+\r
+DATASEG\r
+\r
+EXTRN viewwidth:WORD\r
+\r
+EXTRN tilemap:BYTE\r
+EXTRN spotvis:BYTE\r
+EXTRN pixelangle:WORD\r
+\r
+\r
+EXTRN midangle:WORD\r
+EXTRN angle:WORD\r
+\r
+EXTRN focaltx:WORD\r
+EXTRN focalty:WORD\r
+EXTRN viewtx:WORD\r
+EXTRN viewty:WORD\r
+EXTRN viewx:DWORD\r
+EXTRN viewy:DWORD\r
+\r
+EXTRN xpartialup:WORD\r
+EXTRN ypartialup:WORD\r
+EXTRN xpartialdown:WORD\r
+EXTRN ypartialdown:WORD\r
+\r
+EXTRN tilehit:WORD\r
+EXTRN pixx:WORD\r
+EXTRN wallheight:WORD ; array of VIEWWIDTH entries\r
+\r
+EXTRN xtile:WORD\r
+EXTRN ytile:WORD\r
+EXTRN xtilestep:WORD\r
+EXTRN ytilestep:WORD\r
+EXTRN xintercept:DWORD\r
+EXTRN yintercept:DWORD\r
+EXTRN xstep:DWORD\r
+EXTRN ystep:DWORD\r
+\r
+EXTRN doorposition:WORD ; table of door position values\r
+\r
+\r
+EXTRN pwallpos:WORD ; amound a pushable wall has been moved\r
+\r
+CODESEG\r
+\r
+;-------------------\r
+;\r
+; xpartialbyystep\r
+;\r
+; multiplies long [ystep] (possibly negative), by word [xpartial] (in BX)\r
+;\r
+; returns dx:ax\r
+; trashes bx,cx,di\r
+;\r
+;-------------------\r
+\r
+PROC xpartialbyystep NEAR\r
+;\r
+; setup\r
+;\r
+ mov ax,[WORD ystep]\r
+ mov cx,[WORD ystep+2]\r
+ or cx,cx ; is ystep negatice?\r
+ jns @@multpos\r
+;\r
+; multiply negative cx:ax by bx\r
+;\r
+ neg cx\r
+ neg ax\r
+ sbb cx,0\r
+\r
+ mul bx ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bx ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ ret\r
+;\r
+; multiply positive cx:ax by bx\r
+;\r
+EVEN\r
+@@multpos:\r
+ mul bx ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bx ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+\r
+ ret\r
+\r
+ENDP\r
+\r
+\r
+\r
+;-------------------\r
+;\r
+; ypartialbyxstep\r
+;\r
+; multiplies long [xstep] (possibly negative), by word [ypartial] (in BP)\r
+;\r
+; returns dx:ax\r
+; trashes cx,di,bp\r
+;\r
+;-------------------\r
+\r
+PROC ypartialbyxstep NEAR\r
+;\r
+; setup\r
+;\r
+ mov ax,[WORD xstep]\r
+ mov cx,[WORD xstep+2]\r
+ or cx,cx ; is ystep negatice?\r
+ jns @@multpos\r
+;\r
+; multiply negative cx:ax by bx\r
+;\r
+ neg cx\r
+ neg ax\r
+ sbb cx,0\r
+\r
+ mul bp ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bp ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ ret\r
+;\r
+; multiply positive cx:ax by bx\r
+;\r
+EVEN\r
+@@multpos:\r
+ mul bp ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bp ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+ ret\r
+\r
+ENDP\r
+\r
+\r
+;============================\r
+;\r
+; AsmRefresh\r
+;\r
+;\r
+;============================\r
+\r
+PROC AsmRefresh\r
+PUBLIC AsmRefresh\r
+\r
+ push si\r
+ push di\r
+ push bp\r
+\r
+ mov [pixx],0\r
+;---------------------------------------------------------------------------\r
+;\r
+; Setup to trace a ray through pixx view pixel\r
+;\r
+; CX : angle of the ray through pixx\r
+; ES : points to segment of finetangent array for this block of code\r
+;\r
+; Upon entrance to initialize block\r
+;\r
+; BX : xpartial\r
+; BP : ypartial\r
+;\r
+;---------------------------------------------------------------------------\r
+ EVEN\r
+pixxloop:\r
+ mov ax,SEG finetangent\r
+ mov es,ax\r
+ mov cx,[midangle] ; center of view area\r
+ mov bx,[pixx]\r
+ shl bx,1\r
+ add cx,[pixelangle+bx] ; delta for this pixel\r
+ cmp cx,0\r
+ jge not0\r
+;----------\r
+;\r
+; -90 - -1 degree arc\r
+;\r
+;----------\r
+ add cx,FINEANGLES ; -90 is the same as 270\r
+ jmp entry360\r
+\r
+not0:\r
+ cmp cx,DEG90\r
+ jge not90\r
+;----------\r
+;\r
+; 0-89 degree arc\r
+;\r
+;----------\r
+entry90:\r
+ mov [xtilestep],1 ; xtilestep = 1\r
+ mov [ytilestep],-1 ; ytilestep = -1\r
+ mov [BYTE cs:horizop],OP_JGE ; patch a jge in\r
+ mov [BYTE cs:vertop],OP_JLE ; patch a jle in\r
+ mov bx,DEG90-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = finetangent[DEG90-1-angle]\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = -finetangent[angle]\r
+\r
+ mov bx,[xpartialup] ; xpartial = xpartialup\r
+ mov bp,[ypartialdown] ; ypartial = ypartialdown\r
+ jmp initvars\r
+\r
+not90:\r
+ cmp cx,DEG180\r
+ jge not180\r
+;----------\r
+;\r
+; 90-179 degree arc\r
+;\r
+;----------\r
+ mov ax,-1\r
+ mov [xtilestep],ax ; xtilestep = -1\r
+ mov [ytilestep],ax ; ytilestep = -1\r
+ mov [BYTE cs:horizop],OP_JLE ; patch a jle in\r
+ mov [BYTE cs:vertop],OP_JLE ; patch a jle in\r
+\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx-DEG90*4]\r
+ mov dx,[es:bx+2-DEG90*4]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = -finetangent[angle-DEG90]\r
+ mov bx,DEG180-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = -finetangent[DEG180-1-angle]\r
+\r
+ mov bx,[xpartialdown] ; xpartial = xpartialdown\r
+ mov bp,[ypartialdown] ; ypartial = ypartialdown\r
+ jmp initvars\r
+\r
+not180:\r
+ cmp cx,DEG270\r
+ jge not270\r
+;----------\r
+;\r
+; 180-269 degree arc\r
+;\r
+;----------\r
+ mov [xtilestep],-1 ; xtilestep = -1\r
+ mov [ytilestep],1 ; ytilestep = 1\r
+ mov [BYTE cs:horizop],OP_JLE ; patch a jle in\r
+ mov [BYTE cs:vertop],OP_JGE ; patch a jge in\r
+\r
+ mov bx,DEG270-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = -finetangent[DEG270-1-angle]\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx-DEG180*4]\r
+ mov dx,[es:bx+2-DEG180*4]\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = finetangent[angle-DEG180]\r
+\r
+ mov bx,[xpartialdown] ; xpartial = xpartialdown\r
+ mov bp,[ypartialup] ; ypartial = ypartialup\r
+ jmp initvars\r
+\r
+\r
+not270:\r
+ cmp cx,DEG360\r
+ jge not360\r
+;----------\r
+;\r
+; 270-359 degree arc\r
+;\r
+;----------\r
+entry360:\r
+ mov ax,1\r
+ mov [xtilestep],ax ; xtilestep = 1\r
+ mov [ytilestep],ax ; ytilestep = 1\r
+ mov [BYTE cs:horizop],OP_JGE ; patch a jge in\r
+ mov [BYTE cs:vertop],OP_JGE ; patch a jge in\r
+\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx-DEG270*4]\r
+ mov dx,[es:bx+2-DEG270*4]\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = finetangent[angle-DEG270]\r
+ mov bx,DEG360-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = finetangent[DEG360-1-angle]\r
+\r
+ mov bx,[xpartialup] ; xpartial = xpartialup\r
+ mov bp,[ypartialup] ; ypartial = ypartialup\r
+ jmp initvars\r
+\r
+\r
+not360:\r
+;----------\r
+;\r
+; 360-449 degree arc\r
+;\r
+;----------\r
+ sub cx,FINEANGLES ; -449 is the same as 89\r
+ jmp entry90\r
+\r
+;---------------------------------------------------------------------------\r
+;\r
+; initialise variables for intersection testing\r
+;\r
+;---------------------------------------------------------------------------\r
+initvars:\r
+ call NEAR xpartialbyystep ; xpartial is in BX\r
+ add ax,[WORD viewy]\r
+ adc dx,[WORD viewy+2]\r
+ mov [WORD yintercept],ax\r
+ mov [WORD yintercept+2],dx\r
+\r
+ mov si,[focaltx]\r
+ add si,[xtilestep]\r
+ mov [xtile],si ; xtile = focaltx+xtilestep\r
+ ;begin 8086 hack\r
+ ;shl si,6\r
+ push cx\r
+ mov cl,6\r
+ shl si,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add si,dx ; xspot = (xtile<<6) + yinttile\r
+\r
+\r
+ call NEAR ypartialbyxstep ; ypartial is in BP\r
+ add ax,[WORD viewx]\r
+ adc dx,[WORD viewx+2]\r
+ mov [WORD xintercept],ax\r
+ mov cx,dx\r
+\r
+ mov bx,[focalty]\r
+ add bx,[ytilestep]\r
+ mov bp,bx ; ytile = focalty+ytilestep\r
+ mov di,dx\r
+ ;begin 8086 hack\r
+ ;shl di,6\r
+ push cx\r
+ mov cl,6\r
+ shl di,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add di,bx ; yspot = (xinttile<<6) + ytile\r
+\r
+ mov bx,[xtile]\r
+ mov dx,[WORD yintercept+2]\r
+ mov ax,SCREENSEG\r
+ mov es,ax ; faster than mov es,[screenseg]\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+;\r
+; trace along this angle until we hit a wall\r
+;\r
+; CORE LOOP!\r
+;\r
+; All variables are killed when a wall is hit\r
+;\r
+; AX : scratch\r
+; BX : xtile\r
+; CX : high word of xintercept\r
+; DX : high word of yintercept\r
+; SI : xspot (yinttile<<6)+xtile (index into tilemap and spotvis)\r
+; DI : yspot (xinttile<<6)+ytile (index into tilemap and spotvis)\r
+; BP : ytile\r
+; ES : screenseg\r
+;\r
+;---------------------------------------------------------------------------\r
+\r
+;-----------\r
+;\r
+; check intersections with vertical walls\r
+;\r
+;-----------\r
+\r
+ EVEN\r
+vertcheck:\r
+ cmp dx,bp\r
+vertop: ; 0x7e = jle (ytilestep==-1)\r
+ jle horizentry ; 0x7d = jge (ytilestep==1)\r
+vertentry:\r
+ test [BYTE tilemap+si],0ffh ; tilehit = *((byte *)tilemap+xspot);\r
+ jnz hitvert\r
+passvert:\r
+ mov [BYTE spotvis+si],1 ; *((byte *)spotvis+xspot) = true;\r
+ add bx,[xtilestep] ; xtile+=xtilestep\r
+ mov ax,[WORD ystep]\r
+ add [WORD yintercept],ax ; yintercept += ystep\r
+ adc dx,[WORD ystep+2]\r
+ mov si,bx\r
+ ;begin 8086 hack\r
+ ;shl si,6\r
+ push cx\r
+ mov cl,6\r
+ shl si,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add si,dx ; xspot = (xtile<<6)+yinttile\r
+ jmp vertcheck\r
+\r
+ EVEN\r
+hitvert:\r
+ mov al,[BYTE tilemap+si] ; tilehit = *((byte *)tilemap+xspot);\r
+ mov [BYTE tilehit],al\r
+ or al,al ; set flags\r
+ jns notvertdoor\r
+ jmp vertdoor\r
+notvertdoor:\r
+ mov [WORD xintercept],0\r
+ mov [WORD xintercept+2],bx\r
+ mov [xtile],bx\r
+ mov [WORD yintercept+2],dx\r
+ mov [ytile],dx\r
+ call FAR HitVertWall\r
+ jmp nextpix\r
+\r
+\r
+;-----------\r
+;\r
+; check intersections with horizontal walls\r
+;\r
+;-----------\r
+ EVEN\r
+horizcheck:\r
+ cmp cx,bx\r
+horizop: ; 0x7e = jle (xtilestep==-1)\r
+ jle vertentry ; 0x7d = jge (xtilestep==1)\r
+horizentry:\r
+ test [BYTE tilemap+di],0ffh ; tilehit = *((byte *)tilemap+yspot);\r
+ jnz hithoriz\r
+passhoriz:\r
+ mov [BYTE spotvis+di],1 ; *((byte *)spotvis+yspot) = true;\r
+ add bp,[ytilestep] ; ytile+=ytilestep\r
+ mov ax,[WORD xstep]\r
+ add [WORD xintercept],ax ; xintercept += xstep\r
+ adc cx,[WORD xstep+2]\r
+ mov di,cx\r
+ ;begin 8086 hack\r
+ ;shl di,6\r
+ push cx\r
+ mov cl,6\r
+ shl di,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add di,bp ; yspot = (xinttile<<6)+ytile\r
+ jmp horizcheck\r
+\r
+ EVEN\r
+hithoriz:\r
+ mov al,[BYTE tilemap+di] ; tilehit = *((byte *)tilemap+yspot);\r
+ mov [BYTE tilehit],al\r
+ or al,al ; set flags\r
+ js horizdoor\r
+ mov [WORD xintercept+2],cx\r
+ mov [xtile],cx\r
+ mov [WORD yintercept],0\r
+ mov [WORD yintercept+2],bp\r
+ mov [ytile],bp\r
+ call FAR HitHorizWall\r
+ jmp nextpix\r
+\r
+;---------------------------------------------------------------------------\r
+;\r
+; next pixel over\r
+;\r
+;---------------------------------------------------------------------------\r
+\r
+nextpix:\r
+ mov ax,[pixx]\r
+ inc ax\r
+ mov [pixx],ax\r
+ cmp ax,[viewwidth]\r
+ jge done\r
+ jmp pixxloop\r
+done:\r
+ pop bp\r
+ pop di\r
+ pop si\r
+ retf\r
+\r
+;===========================================================================\r
+\r
+;=============\r
+;\r
+; hit a special horizontal wall, so find which coordinate a door would be\r
+; intersected at, and check to see if the door is open past that point\r
+;\r
+;=============\r
+horizdoor:\r
+ mov [xtile],bx ; save off live register variables\r
+ mov [WORD yintercept+2],dx\r
+\r
+ test al,040h ; both high bits set == pushable wall\r
+ jnz horizpushwall\r
+\r
+ mov bx,ax\r
+ and bx,7fh ; strip high bit\r
+ shl bx,1 ; index into word width door table\r
+\r
+ mov ax,[WORD xstep]\r
+ mov dx,[WORD xstep+2]\r
+ sar dx,1\r
+ rcr ax,1 ; half a step gets to door position\r
+\r
+ add ax,[WORD xintercept] ; add half step to current intercept pos\r
+ adc dx,cx ; CX hold high word of xintercept\r
+\r
+ cmp cx,dx ; is it still in the same tile?\r
+ je hithmid\r
+;\r
+; midpoint is outside tile, so it hit the side of the wall before a door\r
+;\r
+continuehoriz:\r
+ mov bx,[xtile] ; reload register variables\r
+ mov dx,[WORD yintercept+2]\r
+ jmp passhoriz ; continue tracing\r
+;\r
+; the trace hit the door plane at pixel position AX, see if the door is\r
+; closed that much\r
+;\r
+hithmid:\r
+ cmp ax,[doorposition+bx] ; position of leading edge of door\r
+ jb continuehoriz\r
+;\r
+; draw the door\r
+;\r
+ mov [WORD xintercept],ax ; save pixel intercept position\r
+ mov [WORD xintercept+2],cx\r
+\r
+ mov [WORD yintercept],8000h ; intercept in middle of tile\r
+ mov [WORD yintercept+2],bp\r
+\r
+ call FAR HitHorizDoor\r
+ jmp nextpix\r
+\r
+;============\r
+;\r
+; hit a sliding horizontal wall\r
+;\r
+;============\r
+\r
+horizpushwall:\r
+ mov ax,[WORD xstep+2] ; multiply xstep by pwallmove (0-63)\r
+ mul [pwallpos]\r
+ mov bx,ax\r
+ mov ax,[WORD xstep]\r
+ mul [pwallpos]\r
+ add dx,bx\r
+\r
+ sar dx,1 ; then divide by 64 to accomplish a\r
+ rcr ax,1 ; fixed point multiplication\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+\r
+ add ax,[WORD xintercept] ; add partial step to current intercept\r
+ adc dx,cx ; CX hold high word of xintercept\r
+\r
+ cmp cx,dx ; is it still in the same tile?\r
+ jne continuehoriz ; no, it hit the side\r
+\r
+;\r
+; draw the pushable wall at the new height\r
+;\r
+ mov [WORD xintercept],ax ; save pixel intercept position\r
+ mov [WORD xintercept+2],dx\r
+\r
+ mov [WORD yintercept+2],bp\r
+ mov [WORD yintercept],0\r
+\r
+ call FAR HitHorizPWall\r
+ jmp nextpix\r
+\r
+\r
+\r
+;===========================================================================\r
+\r
+;=============\r
+;\r
+; hit a special vertical wall, so find which coordinate a door would be\r
+; intersected at, and check to see if the door is open past that point\r
+;\r
+;=============\r
+vertdoor:\r
+ mov [xtile],bx ; save off live register variables\r
+ mov [WORD yintercept+2],dx\r
+\r
+ test al,040h ; both high bits set == pushable wall\r
+ jnz vertpushwall\r
+\r
+ mov bx,ax\r
+ and bx,7fh ; strip high bit\r
+ shl bx,1 ; index into word width doorposition\r
+\r
+ mov ax,[WORD ystep]\r
+ mov dx,[WORD ystep+2]\r
+ sar dx,1\r
+ rcr ax,1 ; half a step gets to door position\r
+\r
+ add ax,[WORD yintercept] ; add half step to current intercept pos\r
+ adc dx,[WORD yintercept+2]\r
+\r
+ cmp [WORD yintercept+2],dx ; is it still in the same tile?\r
+ je hitvmid\r
+;\r
+; midpoint is outside tile, so it hit the side of the wall before a door\r
+;\r
+continuevert:\r
+ mov bx,[xtile] ; reload register variables\r
+ mov dx,[WORD yintercept+2]\r
+ jmp passvert ; continue tracing\r
+;\r
+; the trace hit the door plane at pixel position AX, see if the door is\r
+; closed that much\r
+;\r
+hitvmid:\r
+ cmp ax,[doorposition+bx] ; position of leading edge of door\r
+ jb continuevert\r
+;\r
+; draw the door\r
+;\r
+ mov [WORD yintercept],ax ; save pixel intercept position\r
+ mov [WORD xintercept],8000h ; intercept in middle of tile\r
+ mov ax,[xtile]\r
+ mov [WORD xintercept+2],ax\r
+\r
+ call FAR HitVertDoor\r
+ jmp nextpix\r
+\r
+;============\r
+;\r
+; hit a sliding vertical wall\r
+;\r
+;============\r
+\r
+vertpushwall:\r
+ mov ax,[WORD ystep+2] ; multiply ystep by pwallmove (0-63)\r
+ mul [pwallpos]\r
+ mov bx,ax\r
+ mov ax,[WORD ystep]\r
+ mul [pwallpos]\r
+ add dx,bx\r
+\r
+ sar dx,1 ; then divide by 64 to accomplish a\r
+ rcr ax,1 ; fixed point multiplication\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+\r
+ add ax,[WORD yintercept] ; add partial step to current intercept\r
+ adc dx,[WORD yintercept+2]\r
+\r
+ cmp [WORD yintercept+2],dx ; is it still in the same tile?\r
+ jne continuevert ; no, it hit the side\r
+\r
+;\r
+; draw the pushable wall at the new height\r
+;\r
+ mov [WORD yintercept],ax ; save pixel intercept position\r
+ mov [WORD yintercept+2],dx\r
+\r
+ mov bx,[xtile]\r
+ mov [WORD xintercept+2],bx\r
+ mov [WORD xintercept],0\r
+\r
+ call FAR HitVertPWall\r
+ jmp nextpix\r
+\r
+\r
+\r
+ENDP\r
+\r
+\r
+END\r
+\r
+\r