	name	stipple

	.386p
;	copy stipple, no tiling
;	copy_stipple(dstx, dsty, dstwidth, dstheight, psrc, srcwidth,
;	    xoff, yoff, fgpixel, bgpixel);
;		int dstx;	/* EAX */
;		int dsty;	/* EDX */
;		int dstwidth;	/* EBX */
;		int dstheight;	/* ECX */
;		char *psrc;
;		int srcwidth, xoff, yoff;
;		u_char fgpixel, bgpixel;
s_dstheight =	-20
s_dstwidth =	-16
s_page	=	-12		; current page info
s_next_src_line =	-8	; number of bytes to next src line
s_next_scan_line =	-4	; number of bytes to next scan line
s_psrc =	8
s_srcwidth =	12
s_xoff =	16
s_yoff =	20
s_fgpixel =	24
s_bgpixel =	28
SVGA_BASE =	0a0000h

_DATA	segment dword public 'DATA'
	EXTRN	_svga_page_shift:BYTE
	EXTRN	_svga_width:DWORD
_DATA	ends
_BSS	segment dword public 'BSS'
_BSS	ends

DGROUP	group _DATA,_BSS

_TEXT	segment	dword public use32 'CODE'
	ASSUME	cs:_TEXT, ds:DGROUP

	EXTRN	VGASetPage_:NEAR

	PUBLIC	VGAstipple_
VGAstipple_	PROC	NEAR
	push	ebp
	mov	ebp,esp		; setup frame pointer
	add	esp,s_dstheight	; setup temp variables
	push	esi		; psrc
	push	edi		; pdst
	mov	esi,_svga_width

	mov	edi,eax		; save dstx
	mov	eax,edx		; get dsty in ax
	mul	si		; short multiply
	add	ax,di		; add dstx
	adc	dl,0
	mov	edi,SVGA_BASE
	mov	di,ax
	mov	s_page[ebp],dl
	; At this point the registers contain the following:
	; EAX:	(scratch) (saved in edi)
	; EBX:	dstwidth
	; ECX:	dstheight
	; EDX:	(scratch) (saved in s_page)
	; ESI:	screen width
	; EDI:	pdst

	mov	s_dstwidth[ebp],ebx
	mov	s_dstheight[ebp],ecx
	mov	ecx,ebx		; dstwidth
	sub	esi,ecx		; get number of bytes to next scan line
	mov	s_next_scan_line[ebp],esi		; save it

	mov	esi,s_psrc[ebp]	; get src buffer

	mov	al,dl		; page
	xor	ah,ah
	mov	cl,_svga_page_shift
	shl	eax,cl
	call	VGASetPage_

	; figure out how to get from the last byte of psrc that we use
	; to the next line of the stipple.
	; This number is simply (xoff + dstwidth + 7) >> 3
	mov	ecx,s_xoff[ebp]	; xoff
	mov	edx,ecx		; keep in ecx
	add	edx,ebx		; add dstwidth
	add	edx,7		; add 7
	shr	edx,3		; divide by 8 to get bytes

	; Now subtract this number from the width of src.
	mov	ebx,s_srcwidth[ebp]
	add	ebx,7
	shr	ebx,3		; convert srcwidth to bytes, rounding up
	mov	eax,ebx
	sub	eax,edx		; compute (srcwidth in bytes) - (xoff + dstw)
	; Now eax needs to have xoff added to it (below after xoff >> 3
	; computation).

	; increment psrc by xoff >> 3, and zero all but the last 3 bits of xoff
	mov	edx,ecx		; xoff from abore
	shr	ecx,3		; convert to bytes
	add	esi,ecx		; psrc += xoff >> 3
	and	edx,7
	mov	s_xoff[ebp],edx

	; now add this value to the next_src_line number
	add	eax,ecx
	mov	s_next_src_line[ebp],eax

	; increment psrc to point to the starting place (use xoff and yoff)
	mov	eax,ebx		; srcwidth in bytes
	mul	dword ptr s_yoff[ebp]	; srcwidth in bytes * yoff
	add	esi,eax		; psrc += srcwidth * yoff

	mov	bh,s_fgpixel[ebp]	; BH = foreground color
	mov	bl,s_bgpixel[ebp]	; BL = background color
$CS0:
	mov	cl,s_xoff[ebp]	; get xoff
	lodsb				; get source byte
	mov	dl,al
	shl	dl,cl		; get rid of any offsets
	mov	dh,8
	sub	dh,cl		; dh has number of bits left
	mov	ecx,s_dstwidth[ebp]	; get number of bytes in one line
same_src:
	shl	dl,1		; check bit
	jnc	short write_bg
	mov	[edi],bh	; write out foreground color
	jmp	short $CS1
write_bg:
	mov	[edi],bl	; write out background color
$CS1:
	inc	di
	jz	short page_it
cont_after_page:
	dec	ecx
	jecxz	short next_line
	dec	dh
	jnz	short same_src
	lodsb
	mov	dl,al
	mov	dh,8
	jmp	short same_src

page_it:
	mov	al,s_page[ebp]
	inc	al
	mov	s_page[ebp],al

	push	ecx
	xor	ah,ah
	mov	cl,_svga_page_shift
	shl	eax,cl
	pop	ecx

	call	VGASetPage_

	jmp	short cont_after_page

next_line:
	dec	word ptr s_dstheight[ebp]	; any more
	jz	short no_more
	add	esi,s_next_src_line[ebp]
	add	di,s_next_scan_line[ebp]
	jnc	short $CS0
	mov	al,s_page[ebp]
	inc	al
	mov	s_page[ebp],al

	xor	ah,ah
	mov	cl,_svga_page_shift
	shl	eax,cl
	call	VGASetPage_

	jmp	short $CS0
no_more:
	pop	edi
	pop	esi
	leave
	ret	24
VGAstipple_	ENDP
_TEXT	ENDS
	END
