	TITLE	egacopyconstant

	.286p

X	EQU	4

IBM_TEXT	SEGMENT  WORD PUBLIC 'CODE'
IBM_TEXT	ENDS
IBM_TEXT	SEGMENT
	ASSUME	CS: IBM_TEXT

; egacopyconstant(src, pdst, soff, doff, n, op)
; u_char src;
; u_char *pdst;	/* byte pointer to dst memory */
;			/* psrc points to 0 or 0xff */
; int soff;		/* if src is not 0 or 0xff, how much to shift */
; int doff;		/* offset into dst 0 <= doff <= 7 */
; int n;		/* number of bits to copy */
; int op;		/* VGA hardware rop */

; ES:DI:	pdst
; CX:		n
; BX		doff
; AX,DX		temporary registers

	PUBLIC	_egacopyconstant
_egacopyconstant	PROC NEAR
	push	bp
	mov	bp,sp
	push	di
	les	di,2[bp+X]	; pdst
	mov	bh,6[bp+X]	; soff
	mov	bl,8[bp+X]	; doff
	mov	cx,10[bp+X]	; n
	mov	ah,12[bp+X]	; op
	shl	ah,1
	shl	ah,1
	shl	ah,1		; shift for register
	sub	bh,bl		; soff - doff
	and	bh,7		; convert to right shift
	or	ah,bh		; merge with op
	xor	bh,bh		; convert bx back to word
	cld

	mov	dx,03ceh
	mov	al,3		; data rotate / function register
	out	dx,ax		; fix op

; set mask for first byte

	mov	dx,cx		; n
	mov	cx,bx		; doff
	not	ch		; ch = 0xff
	shr	ch,cl		; ch = 0xff >> doff
	mov	ah,ch

	; evaluate n -= (8 - doff)
	add	dx,bx		; n += doff
	sub	dx,8		; n -= 8
	jge	$L7		; if (n < 0)
	mov	cx,dx		; cl = -n, ch = 0xff
	neg	cl		; -n
	shl	ch,cl		; CH = 0xff << -n
	and	ah,ch		; mask (AH) &= CH
	xor	dx,dx		; let it be known that n = 0
$L7:
	; mask is in ah - put it into the E/VGA hardware
	mov	cx,dx		; save n
	mov	dx,03ceh
	mov	al,8		; mask register
	out	dx,ax

	mov	al,[bp+X]	; src
	mov	ah,es:[di]	; preload buffer
	stosb			; write data out

	jcxz	$L0

	mov	bh,al		; save src
	mov	bl,cl		; save LSB of n
	shr	cx,1
	shr	cx,1
	shr	cx,1		; CX = n >> 3;
	je	$L9		; while (cx--)

	mov	ah,0ffh
	mov	al,8		; mask register
	out	dx,ax		; set mask register
	mov	al,bh		; get src back
$L8:
	mov	ah,es:[di]	; preload
	stosb			; do the operation
	loop	$L8
$L9:
	; take care of last remaining byte
	and	bl,7		; we only need this part
	je	$L0

	mov	bh,al		; save src again
	; set up mask register for last bits
	not	ch		; CH = 0xff
	mov	al,8		; mask
	mov	cl,bl		; n & 7
	shr	ch,cl		; CH = 0xff >> (n & 7)
	not	ch
	mov	ah,ch
	out	dx,ax
$L21:
	mov	al,bh		; src
	mov	ah,es:[di]	; preload
	stosb

$L0:
	; put E/VGA hardware back to normal
	mov	al,3
	sub	ah,ah
	out	dx,ax		; set rotate register to 0
	mov	al,8
	not	ah		; restore mask to all 1's
	out	dx,ax
	pop	di
	pop	bp
	ret
_egacopyconstant	ENDP
IBM_TEXT	ENDS
	END
