PAGE 80,132
TITLE - ACKASM.ASM - Assembly routines for 3D engine
.386P
;==============================================================================
; COMMAND LINE ASSEMBLY
;	MASM /B63 /Z /D_Mx FILENAME;
;
;  WHERE Mx SPECIFIES MODEL (l OR c) FOR LARGE OR COMPACT MODELS
;==============================================================================
	INCLUDE		ET.EQU
	INCLUDE		ET.MAC

	ANGLE_30    equ	    160
	ANGLE_360   equ	    1920

	extrn	_bMaps:DWORD
	extrn	_oMaps:DWORD
	extrn	_PageBegin:WORD
	extrn	_InvCosTable:DWORD
	extrn	_InvSinTable:DWORD
	extrn	_LongCosTable:DWORD
	extrn	_DistanceTable:WORD
	extrn	_AdjustTable:DWORD
	extrn	_CenterRow:WORD
	extrn	_MaxDistance:WORD
	extrn	_TopColor:WORD
	extrn	_BottomColor:WORD
	extrn	_WinStartX:WORD
	extrn	_WinEndX:WORD
	extrn	_WinWidth:WORD
	extrn	_WinColumnCount:WORD
	extrn	_WinStartY:WORD
	extrn	_WinEndY:WORD
	extrn	_WinStartOffset:WORD
	extrn	_WinLength:WORD
	extrn	_WinTopLength:WORD
	extrn	_WinBotLength:WORD
	extrn	_WinQuadTopLength:WORD
	extrn	_WinQuadBotLength:WORD
	extrn	_TopLongColor:DWORD
	extrn	_BotLongColor:DWORD
	extrn	_lowmask:BYTE
	extrn	_Walls:WORD
	extrn	_ScreenBuffer:DWORD
	extrn	_BkgdBuffer:DWORD
	extrn	_OverlayBuffer:DWORD
	extrn	_LightFlag:BYTE

	extrn	_WorkPalette:BYTE

	PEXTRN	_AckGetBitmapPtr
	PEXTRN	_AckLockPtr
	PEXTRN	_AckUnlockPtr


	PUBLIC		_AckSetVGAmode
	PUBLIC		_AckSetTextmode
	PUBLIC		_MakeCharLong
	PUBLIC		_AckDrawPage
	PUBLIC		_AckSetPalette
	PUBLIC		_AckBuildCeilingFloor
	PUBLIC		_AckReplaceBitmap
	PUBLIC		_AckOverlayBitmap

	PUBLIC		_draw_col2

SCREEN_SEG equ	0a000h	;segment of display memory in VGA mode 13h

_TEXT	segment byte public use16 'CODE'
DGROUP	group	_DATA,_BSS
	assume	cs:_TEXT,ds:DGROUP

_TEXT	ends
_DATA	segment word public use16 'DATA'
_d@	label	byte
_DATA	ends
_BSS	segment word public use16 'BSS'
_b@	label	byte
_BSS	ends


_TEXT	SEGMENT byte public use16 'CODE'
	ASSUME cs:_TEXT

;==============================================================================
; void AckSetVGAmode(void);
;==============================================================================
PBEGIN	_AckSetVGAmode
	push	bp
	mov	ax,13h
	int	10h		; Set 320x200x256
	pop	bp
	ret
_AckSetVGAmode endp

;==============================================================================
;
;==============================================================================
PBEGIN	_AckSetTextmode
	push	bp
	mov	ax,3
	int	10h
	pop	bp
	ret
_AckSetTextmode endp

;==============================================================================
; Fade the screen in from black to the palette specified
; Contributed by Mark Betz
;==============================================================================
AFIbeg	equ	[bp+ABASE]
AFIcnt	equ	[bp+ABASE+2]
AFIpal	equ	[bp+ABASE+4]

PBEGIN	_AckFadeIn
	push	bp
	mov	bp,sp
	push	ds
	push	si
	push	di
	mov	cx,384
	xor	ax,ax
	push	ds
	pop	es
	mov	dx,offset DGROUP:_WorkPalette

	push	dx		  ; save offset of pal
	xor	bx, bx		  ; need to get the current palette into
	mov	cx, 100h	  ; pal using bios int 10h, 10h, 17h
	mov	ax, 1017h	  ; set up and generate the interrupt
	int	10h		  ; read the palette registers into pal
	pop	di		  ; offset of pal, was in dx!

	; get the palette pointer, then calculate the offset to the
	; first byte processed, based on start, and the number of
	; bytes to process based on count. Use the offset to adjust
	; the string pointers in si and di, and leave the byte
	; count in ax

	lds	si, AFIpal	  ; get address of target palette
	mov	ax, AFIbeg	  ; get offset of first palette byte to
	mov	bx, 3		  ; be processed
	mul	bx
	add	si, ax		  ; adjust di and si point first byte in the
	add	di, ax		  ; target and temporary palettes
	mov	ax, AFIcnt	  ; find the number of bytes to be processed
	mov	bx, 3
	mul	bx		  ; leave it in ax

	; clear the bytes in the triplets which will be operated on by
	; the fade. All other registers are unaffected

	push	di		  ; save the starting offset into pal
	push	ax		  ; save the number of bytes to process
	mov	cx, ax		  ; set up a loop counter
	xor	ax, ax		  ; clear ax
	rep	stosb		  ; fill relevant range of pal with 0's
	pop	ax		  ; restore the number of bytes to process
	pop	di		  ; restore the starting offset into pal
	mov	cx, 64		  ; 64 passes through fade loop

	; the fade loop will execute 64 times. On each pass the inner
	; loop adjusts the working palette, then waits for a blanking
	; interval, and loads the working palette into the DAC

fade_loop:
	push	cx		  ; save the fade loop counter
	push	di		  ; save offset of first byte processed in
	push	si		  ; temp and target palettes
	mov	bl, cl		  ; outer loop count into bl
	mov	cx, ax		  ; load number of bytes to process into cx

	; inner loop makes one pass through the palette for each pass
	; through the outer loop. Each byte is incremented if it's
	; target value is one greater than the outer loop count. Using
	; this logic ensures that all bytes arrive at their target values
	; on the same pass through the outer loop

pal_cmp_loop:
	cmp	bl, ds:[si]	  ; start incrementing when palette value
	jns	no_add		  ; is one greater than loop count
	inc	BYTE PTR es:[di]
no_add:
	inc	si		  ; point to the next byte in both palettes
	inc	di
	loop	pal_cmp_loop	  ; do the next byte

	; setup for palette load. As much as possible was moved above the
	; blanking interval wait, in order to maximize the amount of the
	; blanking interval remaining in which to do the palette loading

	mov	bx, sp
	mov	di, ss:[bx+02]	    ; restore offset into pal without popping
	mov	cx, AFIcnt	    ; number of triplets to process
	push	ax		    ; need to use ax for port i/o

	; monitor bit 1 of CRT controller's input status 1 register to
	; sense a vertical blanking interval. Wait for any current vbi
	; to end, then wait for the next full one to begin.

	    mov dx, 03DAh		; CRT controller input status 1 register
vbi_1:
		in al, dx		    ; watch vertical blanking bit
		test al,08h		    ; wait for it to clear to make sure
		jnz vbi_1		    ; we're not in a blanking interval
vbi_2:
		in al, dx		    ; now wait for the start of the
		test al,08h		    ; next blanking interval
		jz vbi_2

	; load the relevant triplets from pal into the VGA DAC palette

	mov	ah, BYTE PTR AFIbeg ; get first register to process into ah
	mov	dx, 03c8h	    ; DAC palette index register
pal_load_loop:
	mov	al, ah		    ; get next palette number to write
	out	dx, al		    ; write the register number to the dac
	inc	dx		    ; address dac data register
	mov	al, BYTE PTR es:[di] ; get first byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	di		     ; point to second byte
	mov	al, BYTE PTR es:[di] ; get second byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	di		     ; point to third byte
	mov	al, BYTE PTR es:[di] ; get third byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	di		     ; point to first byte of next triplet
	dec	dx		     ; address the dac index register
	inc	ah		     ; point to next palette register
	loop	pal_load_loop	     ; process next triplet

	; clean-up for the next pass through the fade loop

	pop	ax		  ; restore ax
	pop	si		  ; restore the offset into palette
	pop	di		  ; restore the offset into pal
	pop	cx		  ; restore the fade loop counter
	loop	fade_loop	  ; do the next pass through the fade loop

	pop	di
	pop	si
	pop	ds
	pop	bp
	ret
_AckFadeIn endp

;==============================================================================
; void AckFadeOut(int Begin,int Count);
; Contributed by Mark Betz
;==============================================================================
AFObeg	equ	[bp+ABASE]
AFOcnt	equ	[bp+ABASE+2]

PBEGIN _AckFadeOut
	push	bp
	mov	bp,sp
	push	ds
	push	si
	push	di

	push	ds		  ; get data segment into es
	pop	es
	mov	dx, offset DGROUP:_WorkPalette
	push	dx		  ; save offset of opal
	xor	bx, bx
	mov	cx, 100h
	mov	ax, 1017h	  ; bios read dac registers function
	int	10h		  ; read the palette registers into opal
	pop	di		  ; offset of opal, was in dx!
	mov	ax, AFObeg	  ; get offset of first palette byte to
	mov	bx, 3		  ; be processed
	mul	bx
	add	di, ax		  ; adjust offset into opal
	mov	ax, AFOcnt	  ; find the number of bytes to be processed
	mov	bx, 3
	mul	bx		  ; leave it in ax
	mov	cx, 64		  ; 64 passes through fade loop
o_fade_loop:
	push	cx		  ; save the fade loop counter
	push	di		  ; save offset of first byte processed in
	mov	bl, cl		  ; we'll use the pass number as a threshold
	mov	cx, ax		  ; load number of bytes to process into cx
o_pal_cmp_loop:
	cmp	bl, es:[di]	  ; start decrementing when palette value
	jnz	o_no_dec	  ; is equal loop count (it will stay equal
	dec	BYTE PTR es:[di]  ; to loop count for the rest of this pass)
o_no_dec:
	inc	di
	loop	o_pal_cmp_loop	    ; do the next byte

	mov	bx, sp		    ; need the stack pointer for a moment
	mov	di, ss:[bx]	    ; restore offset into pal without popping
	mov	cx, AFOcnt	    ; number of triplets to process
	push	ax		    ; need to use ax for port i/o

	    mov dx, 03DAh		; CRT controller input status 1 register
o_vbi_1:
		in al, dx		    ; watch vertical blanking bit
		test al,08h		    ; wait for it to clear to make sure
		jnz o_vbi_1		    ; we're not in a blanking interval
o_vbi_2:
		in al, dx		    ; now wait for the start of the
		test al,08h		    ; next blanking interval
		jz o_vbi_2

	mov	ah, BYTE PTR AFObeg ; get first register to process into ah
	mov	dx, 03c8h	    ; DAC palette index register
o_pal_load_loop:
	mov	al, ah		    ; get next palette number to write
	out	dx, al		    ; write the register number to the dac
	inc	dx		    ; address dac data register
	mov	al, BYTE PTR es:[di] ; get first byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	di		     ; point to second byte
	mov	al, BYTE PTR es:[di] ; get second byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	di		     ; point to third byte
	mov	al, BYTE PTR es:[di] ; get third byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	di		     ; point to first byte of next triplet
	dec	dx		     ; address the dac index register
	inc	ah		     ; point to next palette register
	loop	o_pal_load_loop	     ; process next triplet

	pop	ax		  ; restore ax
	pop	di		  ; restore the offset into pal
	pop	cx		  ; restore the fade loop counter
	loop	o_fade_loop	  ; do the next pass through the fade loop



	pop	di
	pop	si
	pop	ds
	pop	bp
	ret
_AckFadeOut endp


;==============================================================================
;
;==============================================================================
MCLch	equ	[bp+ABASE]

PBEGIN	_MakeCharLong
	push	bp
	mov	bp,sp
	mov	ax,MCLch
	mov	ah,al
	mov	dx,ax
	pop	bp
	ret
_MakeCharLong endp

;==============================================================================
; void AckDrawOverlay(UCHAR far *Screen,UCHAR far *Overlay);
;==============================================================================
ADOscrn equ	[bp+ABASE]
ADOover equ	[bp+ABASE+4]

PBEGIN	_AckDrawOverlay
	push	bp
	mov	bp,sp
	push	ds
	push	si
	push	di
	les	di,dword ptr ADOscrn
	lds	si,dword ptr ADOover
	mov	bx,di	;Save screen offset
	mov	ax,ds
	or	ax,ax
	jz	ado90

ado10:
	lodsw		;get length
	or	ax,ax
	jz	ado90	;no more data
	xchg	cx,ax

	lodsw		;get offset to move to
	add	di,ax
	shr	cx,1
  rep	movsw
	rcl	cx,1	; catch any odd byte
  rep	movsb		; move one if there is an odd byte

	mov	di,bx	;Restore original screen offset
	jmp	ado10

ado90:
	pop	di
	pop	si
	pop	ds
	pop	bp
	ret
_AckDrawOverlay endp

;==============================================================================
;
; 1. Take the compiled overlay buffer and moves the non-transparent portions
;    over the top of the screen buffer.
;
; 2. Copies the area of the viewing window from the screen buffer to the
;    actual screen.
;==============================================================================
DPWinStartOffset equ	[BP+ABASE]
DPWinLength	equ	[BP+ABASE+2]
DPScreenBuffer	equ	[BP+ABASE+4]
DPWinWidth	equ	[bp+ABASE+8]
DPWinHeight	equ	[bp+ABASE+10]
DPWinStartX	equ	[bp+ABASE+12]

PBEGIN	_AckDrawPage
	push	bp
	mov	bp,sp
	push	si
	push	di
	push	ds

	mov	cx,word ptr DPWinWidth;
	mov	bx,word ptr DPWinHeight;
	mov	di,word ptr DPWinStartOffset
	add	di,word ptr DPWinStartX
	mov	ax,SCREEN_SEG
	mov	es,ax
	lds	si,dword ptr DPScreenBuffer
	add	si,di		;Add starting offset to screen buffer

;------------------------------------------------------------------------------
; Removed for now, if flicker is noticed on faster machines, then it may have
; to be put back in.
;------------------------------------------------------------------------------
;	 mov	 dx,3dah

;fp030:
;	 in	 al,dx		 ;Wait until vertical retrace is off
;	 test	 al,8
;	 jnz	 fp030

;fp040:
;	 in	 al,dx		 ;Wait until vertical retrace resumes
;	 test	 al,8
;	 jz	 fp040

	mov	dx,cx		;Hold onto width
	mov	ax,320
	sub	ax,cx		;get bytes to next row
	dec	bx
	jz	fp060

fp050:
	shr	cx,1
  rep	movsw
	rcl	cx,1
  rep	movsb
	mov	cx,dx
	add	di,ax
	add	si,ax
	dec	bx
	jnz	fp050

fp060:
	pop	ds
	pop	di
	pop	si
	pop	bp
	ret
_AckDrawPage endp


;==============================================================================
; void AckSetPalette(unsigned char far *PalBuf);
;==============================================================================
SPbuf	equ	[bp+ABASE]

PBEGIN	_AckSetPalette
	push	bp
	mov	bp,sp
	push	ds
	push	si

	lds	si,dword ptr SPbuf
	mov	cx,256
	xor	bx,bx
	cld
	mov	dx,3C8H
sp010:
	mov	al,bl
	out	dx,al
	inc	dx
	lodsb
	out	dx,al
	lodsb
	out	dx,al
	lodsb
	out	dx,al
	dec	dx
	inc	bx
	loop	sp010

	pop	si
	pop	ds
	pop	bp
	ret
_AckSetPalette endp

;==============================================================================
;
;void AckBuildCeilingFloor(UCHAR far *,int,int,int,int,int,int);
;==============================================================================
CFBkgdBuffer	equ	[bp+ABASE]
CFLightFlag	equ	[bp+ABASE+4]
CFTopColor	equ	[bp+ABASE+6]
CFBottomColor	equ	[bp+ABASE+8]
CFWinStartY	equ	[bp+ABASE+10]
CFWinEndY	equ	[bp+ABASE+12]
CFCenterRow	equ	[bp+ABASE+14]

PBEGIN	_AckBuildCeilingFloor
	push	bp
	mov	bp,sp
	push	si
	push	di

	les	di,dword ptr CFBkgdBuffer
	test	byte ptr CFLightFlag,1		;Is shading on
	jz	bcf_normal			;nope
	jmp	bcf_shade			;else create shaded buffer

bcf_normal:
	mov	cx,word ptr CFCenterRow
	sub	cx,word ptr CFWinStartY
	inc	cx
	imul	cx,320
	mov	ax,word ptr CFTopColor
  rep	stosb					;no need to be fast here
	mov	cx,word ptr CFWinEndY
	sub	cx,word ptr CFCenterRow
	imul	cx,320
	mov	ax,word ptr CFBottomColor
  rep	stosb
	jmp	bcf_done			;exit routine

bcf_shade:
	mov	bx,word ptr CFCenterRow
	sub	bx,word ptr CFWinStartY	  ;Number of video rows
	inc	bx
	mov	cx,bx				;Hold onto total rows
	shr	bx,3				;Turn into 8 zones
	mov	ax,word ptr CFTopColor
	mov	ah,al				;Top color to use
	mov	dx,4000H			;set shading for next zone
	call	FillInZone
	mov	dx,4040H
	call	FillInZone
	mov	dx,8040H
	call	FillInZone
	mov	dx,8080H
	call	FillInZone
	mov	dx,0C080H
	call	FillInZone
	mov	dx,0C0C0H
	call	FillInZone
	mov	dx,0FFC0H
	call	FillInZone		;This takes care of top 8 zones
	mov	dx,0FFFFH
	call	FillInZone
	xchg	ax,bx			;ax has rows per zone
	xchg	cx,bx			;bx has total rows for top color
	shl	ax,3			;x 8 to get total rows
	sub	bx,ax			;get remaining rows if odd
	jz	bcf010			;no odd rows to fill
	mov	dx,0FFFFH
	call	FillInZone

bcf010:
	mov	bx,word ptr CFWinEndY
	sub	bx,word ptr CFCenterRow
	mov	cx,bx
	shr	bx,3
	mov	ax,bx
	shl	ax,3
	sub	cx,ax		;any odd rows to fill?
	jz	bcf020		;nope
	push	bx		;save rows per zone
	mov	bx,cx
	mov	dx,0FFFFH
	call	FillInZone
	pop	bx

bcf020:
	mov	ax,word ptr CFBottomColor
	mov	ah,al
	mov	dx,0FFFFH
	call	FillInZone
	mov	dx,0FFC0H
	call	FillInZone
	mov	dx,0C0C0H
	call	FillInZone
	mov	dx,0C080H
	call	FillInZone
	mov	dx,8080H
	call	FillInZone
	mov	dx,8040H
	call	FillInZone
	mov	dx,4040H
	call	FillInZone
	mov	dx,4000H
	call	FillInZone


bcf_done:
	pop	di
	pop	si
	mov	sp,bp
	pop	bp
	ret
_AckBuildCeilingFloor endp


;==============================================================================
; Local routine, called by BuildCeilingFloor
; Entry: BX = number of rows to fill
;	 DX = Shading values for odd/even rows
;	 AX = base color value
;
; Exit: Di advanced bx * 160 bytes, all other registers preserved
;
;==============================================================================
FillInZone proc near
	push	bx
	push	cx
	push	si
	mov	si,ax

fiz010:
	test	bx,1				;check odd/even row
	jz	fiz020
	or	ax,dx
	jmp	short fiz030
fiz020:
	or	al,dh				;swap which bytes are used
	or	ah,dl
fiz030:
	mov	cx,160				;move in one row
   rep	stosw
	mov	ax,si				;restore base color
	dec	bx				;bump number of rows
	jnz	fiz010

	pop	si
	pop	cx
	pop	bx
	ret
FillInZone endp

;==============================================================================
; void AckReplaceBitmap(UCHAR far *xGrid,UCHAR far *yGrid,UCHAR OldBmp,UCHAR NewBmp);
; Replaces OldBmp numbers with NewBmp numbers in x and y grid arrays
;==============================================================================
ARBxGrid equ	[bp+ABASE]
ARByGrid equ	[bp+ABASE+4]
ARBold	 equ	[bp+ABASE+8]
ARBnew	 equ	[bp+ABASE+10]

PBEGIN	_AckReplaceBitmap
	push	bp
	mov	bp,sp
	push	ds
	push	si

	lds	si,ARBxGrid
	mov	cx,4160			;65x64
	mov	bl,byte ptr ARBold
	mov	bh,byte ptr ARBnew

arb010:
	lodsw				;get flags and bitmap
	cmp	al,bl			;old bitmap?
	jne	arb020			;nope
	mov	ds:[si-2],bh		;else plug in new bitmap
arb020:
	loop	arb010


	lds	si,ARByGrid
	mov	cx,4160			;65x64

arb030:
	lodsw				;get flags and bitmap
	cmp	al,bl			;old bitmap?
	jne	arb040			;nope
	mov	ds:[si-2],bh		;else plug in new bitmap
arb040:
	loop	arb030


	pop	si
	pop	ds
	pop	bp
	ret
_AckReplaceBitmap endp

;==============================================================================
; void AckOverlayBitmap(UCHAR far *dest,UCHAR far *src);
; Overlays non-transparent colors of source bitmap onto destination bitmap
;==============================================================================
AOBdest equ	[bp+ABASE]
AOBsrc	equ	[bp+ABASE+4]

PBEGIN	_AckOverlayBitmap
	push	bp
	mov	bp,sp
	push	ds
	push	si
	push	di

	push	word ptr AOBdest+2
	push	word ptr AOBdest
	call	_AckLockPtr
	add	sp,4
	or	dx,dx			;null segment?
	jz	aob090			;yep, not enough memory

	push	dx
	push	ax			;save destination ptr

	push	word ptr AOBsrc+2
	push	word ptr AOBsrc
	call	_AckLockPtr
	add	sp,4
	or	dx,dx			;error getting pointer?
	jnz	aob010			;nope, okay so far

	call	_AckUnlockPtr		;Unlock the DX:AX above
	add	sp,4
	jmp	short aob090


aob010:
	mov	fs,dx
	mov	si,ax			;Source
	mov	bx,ax			;Hold onto source offset

	pop	di
	pop	es			;Get destination from DX:AX above
	mov	dx,di			;hold onto destination offset

	mov	cx,4096			;64x64 bitmap

aob020:
	mov	al,fs:[si]		;get source pixel
	or	al,al
	jz	aob030
	mov	es:[di],al

aob030:
	inc	si
	inc	di
	loop	aob020

	push	es
	push	dx			;dest bitmap

	push	fs
	push	bx			;source bitmap
	call	_AckUnlockPtr
	add	sp,4

	call	_AckUnlockPtr		;now unlock destination
	add	sp,4

aob090:
	pop	di
	pop	si
	pop	ds
	pop	bp
	ret
_AckOverlayBitmap endp

;==============================================================================
; AckCopyBackground(UCHAR far *scrn,UCHAR far *bkgd,int len,int offset);
;==============================================================================
ACBscrn equ	[bp+ABASE]
ACBbkgd equ	[bp+ABASE+4]
ACBlen	equ	[bp+ABASE+8]
ACBoff	equ	[bp+ABASE+10]

PBEGIN _AckCopyBackground
	push	bp
	mov	bp,sp
	push	ds
	push	si
	push	di

;------------------------------------------------------------------------------
; Quickly transfer the pre-built background ceiling and floor to the screen.
;------------------------------------------------------------------------------
	les	di,dword ptr ACBscrn

	add	di,word ptr ACBoff
	mov	cx,word ptr ACBlen	      ;Number of DWORDS to move
	lds	si,dword ptr ACBbkgd	      ;Pre-built buffer
  rep	movsd

	pop	di
	pop	si
	pop	ds
	pop	bp
	ret
_AckCopyBackground endp


;==============================================================================
; draw_col2(int Col,int slice,int dist,int width,int ht,UCHAR far *Wall,
;	    UCHAR far *Screen,UCHAR far *Pal,int light,int offset);
; Contributed by Jaimi McEntire
;==============================================================================

DCcol	equ	[bp+ABASE]
DCslice equ	[bp+ABASE+2]
DCdist	equ	[bp+ABASE+4]
DCwidth equ	[bp+ABASE+6]
DCht	equ	[bp+ABASE+8]
DCwall	equ	[bp+ABASE+10]
DCscrn	equ	[bp+ABASE+14]
DCPal	equ	[bp+ABASE+18]
DClight equ	[bp+ABASE+22]
DChoff	equ	[bp+ABASE+24]

DCangle equ	[bp-2]

PBEGIN _draw_col2
	push	bp
	mov	bp,sp
	sub	sp,4
	push	ds
	push	si
	push	di

	mov	word ptr DCangle,0
	mov	edx,0
	mov	esi,0

	mov	ax,DCdist	 ; get distance to object
	shr	ax,6		 ; divide it by 64 to get zones.

	cmp	ax,15		 ; make sure zone doesn't go beyond 15
	jl	zoneokay
	mov	ax,15

zoneokay:
; Good place for light modifier to modify zone
	 shl ax,8		 ; mult by 256 to get offset into paltables.
	 lfs dx,dword ptr DCPal	 ; point FS:DX at PalTables
	 cmp	word ptr DClight,0
	 jz	zonelight
	 add dx,ax		 ; FS:DX points to corrected palette for zone.

zonelight:
	 les di,dword ptr DCscrn ; ES:DI point to area we are painting

;/	 mov ax,column
;/	 cmp ax,ViewX
;/	 jl  outtahere		 ; don't bother to draw a column we wont see.
;/	 cmp ax,ViewX2
;/	 jge outtahere
;/	 sub ax,ViewX
;/	 mov column,ax		 ; adjust column for offset into buffer.

	lds	si,DCwall	 ; DS:SI point to wall buffer

;;;	mov	bx,DCht		 ; center row.
;;;	imul	bx,word ptr DCwidth
	mov	bx,DChoff	 ; Pick up offset to center of viewport
	add	bx,word ptr DCcol
	add	di,bx		 ; es:di now point at starting area (top run)
	mov	bx,di
	add	bx,DCwidth	 ; es:bx points to 1 down (for bottom run)

	mov	cx,0		 ; ht.
	mov	ax,DCslice
	shl	ax,6		 ; mult slice by 64
	add	ax,si		 ; add in offset to wall bitmap
	mov	DCslice,ax	 ; save it
	mov	eax,0

looptop:
	movzx	ax,ch		 ; current ht
	mov	si,31		 ; base to start with
	sub	si,ax		 ; base - ht = row
	add	si,DCslice	 ; plus column start to point at the pixel.
	mov	al,ds:[si]	 ; mov al,offset slice[esi]
	or	al,al		 ; see if transparent
	jz	blank		 ; yes, don't draw this pixel
	mov	al,fs:[edx][eax] ; added this line to get correct shading.
	mov	es:[di],al

blank:
	movzx	si,ch		; use a cool 386 instruction to accomplish
	add	si,32		;  same as mov ax,cx; shr ax,8 !!
	add	si,DCslice	; add in starting column
	mov	al,ds:[si]
	or	al,al
	je	blank2
	mov	al,fs:[edx][eax]	 ; added this line to shade it.
	mov	es:[bx],al

blank2:
	mov	ax,DCwidth
	sub	di,ax			 ; point to the next two dest pixels.
	add	bx,ax			 ; point to the next two dest pixels.
	add	cx,word ptr DCdist	 ; add distance to ht adjuster.

	cmp	ch,32			 ; cmp to 32 (1 half our bm size)
	jge	outtahere		 ; get out if bitmap done.

;;;;	inc	word ptr DCangle
	mov	ax,DCangle
	inc	ax
	cmp	ax,word ptr DCht	 ; if half height,
	jge	outtahere		 ; then leave.
	mov	DCangle,ax
	jmp	looptop

outtahere:

	pop	di
	pop	si
	pop	ds
	mov	sp,bp
	pop	bp
	ret
_draw_col2 endp

_TEXT	ENDS
	END

