
;	void far copy(srcx, srcy, dstx, dsty, width, height)
;
;	copy rectangles
;
c_srcx	=	8
c_srcy	=	12
c_dstx	=	16
c_dsty	=	20
c_width	=	24
c_height =	28
CCOPY	PROC NEAR
ccopy640:
	mov	eax,640		; 640 bytes per scan line
	jmp	short ccopy_it

ccopy800:
	mov	eax,800		; 800 bytes per scan line
	jmp	short ccopy_it

ccopy1024:
	mov	eax,1024		; 1024 bytes per scan line

	extrn	svgapriv:word
ccopy_it:
	push	ebp
	mov	ebp,esp
	push	ds
	push	es
	push	esi
	push	edi
	push	ebx
	mov	ebx,eax

	mov	ax,svgapriv+4	; point to video area
	mov	es,ax		; point to video area
	mov	ds,ax	

	movzx	eax,word ptr c_srcy[ebp]
	mul	bx		; multiply it by screen width
	add	ax,c_srcx[ebp]	; srcy * screen_width + srcx
	adc	dx,0
	movzx	esi,ax
	mov	cl,dl		; save src page

	movzx	eax,word ptr c_dsty[ebp]	; destination
	mul	bx		; multiply it by 640
	add	ax,c_dstx[ebp]
	adc	dx,0
	movzx	edi,ax
	mov	dh,cl		; dh = src page
				; dl = dst page
	;	reg DL has the dst page number
	;	reg DH has the src page number
	;	reg SI has the src data pointer
	;	reg DI has the dst data pointer

	cmp	dh,dl		; compare src and dst page numbers
	ja	$C10
	jb	overlap
	cmp	edi,esi		; overlap can occur
	ja	overlap		; if dst < src, no overlap
$C10:				; reverse it
	sub	ebx,c_width[ebp]	; bytes to next scan line
	setpage	dh,dl		; setup VGA paging register
	jmp	no_overlap

overlap:
	push	edx		; save src & dst pages

	mov	ecx,c_width[ebp]
	dec	ecx

	mov	eax,c_height[ebp]	; get height
	dec	eax
	mul	bx		; dx:ax = (height - 1) * screen_width
	add	ax,cx		; this is not a predecrement machine
	adc	dl,0
	mov	cl,dl
	pop	edx

	add	si,ax		; have source point to end
	adc	dh,cl		; fixup src page number
	add	di,ax		; have dest point to end
	adc	dl,cl		; fixup dst page number

	setpage	dh,dl

	sub	ebx,c_width[ebp]	; bx = number of bytes to next scan line
	std			; copy backwords
$again:
	mov	eax,c_width[ebp]	; width
	cmp	esi,eax		; if (srcoff < width)
	jb	$R70		; jmp if possible split page at src
	cmp	edi,eax		; if (dstoff < width) {
	jb	$R80		; jmp if possible split page at dst

	mov	ecx,eax
	rep	movsb		; copy a scan line minus 1

$R90:
	sub	si,bx		; goto next scan line
	jc	$R91		; need to fixup page number
	sub	di,bx
	jc	$R92
$R95:
	dec	word ptr c_height[ebp]	; decrement the height
	jnz	$again
$R99:				; were done, go home
	pop	ebx
	pop	edi
	pop	esi
	pop	es
	pop	ds
	leave
	cld
	ret

$R91:
	dec	dh		; fixup src page
	sub	di,bx
$R92:
	sbb	dl,0		; fixup dst page
	setpage	dh,dl
	jmp	short $R95

$R80:				; dstoff split page
	mov	ecx,edi		; get dstoff
	inc	ecx		; cx has bytes to copy
	sub	eax,ecx		; ax has rest of scan line

	rep	movsb		; copy to end of page
	movzx	edi,di
	mov	ecx,eax		; cx = rest of scan line, could be zero

	dec	dl
	setpage	dh,dl

	rep	movsb		; finish scan line

	sub	di,bx		; CY can't occur
	sub	si,bx
	jnc	$R95

	dec	dh		; fixup src page
	setpage	dh,dl

	jmp short $R95

$R70:				; split page at src
	cmp	edi,eax		; if (dstoff < width)
	jae	$R60		; jump if no dest overlap, just src
	cmp	edi,esi		; if (srcoff == dstoff)
	jb	$R50
;	ja	$R40		; break occurs twice, at srcoff and dstoff

	je	$R30
	jmp	$R40
$R30:

	dec	dl		; goto next dest page
$R60:				; break occurs only at srcoff
	mov	ecx,esi		; get srcoff
	inc	ecx		; cx has bytes to copy
	sub	eax,ecx		; ax has rest of scan line

	rep	movsb		; copy to end of page
	movzx	esi,si
	mov	ecx,eax		; ax has number of bytes left to copy

	dec	dh		; goto next src page
	setpage	dh,dl

	rep	movsb		; finish scan line

	sub	si,bx		; can't CY
	sub	di,bx
	jnc	$R65
	dec	dl
	setpage	dh,dl
$R65:
	jmp	$R95

$R50:
				; break occurs at dstoff first
	mov	ecx,edi		; get srcoff
	inc	ecx		; cx has bytes to copy
	sub	eax,ecx		; ax has rest of scan line

	rep	movsb		; copy to end of page
	movzx	edi,di
	mov	ecx,eax

	dec	dl		; goto next dst page
	setpage	dh,dl

	mov	eax,ecx		; setup count info
	mov	ecx,esi		; get srcoff
	inc	ecx		; cx has bytes to copy
	sub	eax,ecx		; ax has rest of scan line

	rep	movsb		; copy to end of page
	movzx	esi,si
	mov	ecx,eax		; ax has number of bytes left to copy

	dec	dh		; goto next src page
	setpage	dh,dl

	rep	movsb		; finish scan line

	sub	esi,ebx		; can't CY
	sub	edi,ebx		; can't CY
	jmp	$R95

$R40:				; break occurs at srcoff, then dstoff
	mov	ecx,esi		; get srcoff
	inc	ecx		; cx has bytes to copy
	sub	eax,ecx		; ax has rest of scan line

	rep	movsb		; copy to end of page
	movzx	esi,si
	mov	ecx,eax

	dec	dh		; goto next src page
	setpage	dh,dl

	mov	eax,ecx
	mov	ecx,edi		; get dstoff
	inc	ecx		; cx has bytes to copy
	sub	eax,ecx		; ax has rest of scan line

	rep	movsb		; copy to end of page
	movzx	edi,di
	mov	ecx,eax		; cx = rest of scan line, could be zero

	dec	dl		; next dst page
	setpage	dh,dl

	rep	movsb		; finish scan line

	sub	edi,ebx		; CY can't occur
	sub	esi,ebx		; can't CY
	jmp	$R95

no_overlap:			; bx = bytes to next scan line
	mov	ecx,c_width[ebp]
	mov	eax,esi		; if (srcoff + width > 0xffffL)
	add	ax,cx
	jc	$C70		; branch if split page at src
	mov	eax,edi		; if (dstoff + width > 0xffffL)
	add	ax,cx		; dx = dstoff + width
	jc	$C80		; branch if split page at dst

	shr	ecx,1
	rep	movsw		; copy a scan line
	adc	ecx,ecx
	rep	movsb		; copy a scan line

	add	si,bx		; goto next scan line
	jc	$C91		; need to fixup page number
	add	di,bx
	jc	$C92
$C95:
	dec	word ptr c_height[ebp]	; decrement the height
	jnz	no_overlap
				; were done, go home
	pop	ebx
	pop	edi
	pop	esi
	pop	es
	pop	ds
	leave
	ret

$C91:
	inc	dh		; fixup src page info
	add	di,bx
$C92:
	adc	dl,0		; fixup dst page
$C94:
	setpage	dh,dl
	jmp	short $C95

$C80:				; dstoff split page only, ax has what's left
	mov	ecx,edi		; get dstoff
	neg	cx

	movzx	ecx,cx

	shr	ecx,1
	rep	movsw		; copy to end of page
	adc	ecx,ecx
	rep	movsb		; copy to end of page
	mov	edi,ecx		; zero di
	mov	ecx,eax		; cx has number of bytes left to copy

	inc	dl		; goto next dest page
	setpage	dh,dl

	shr	ecx,1
	rep	movsw		; finish the scan line
	adc	ecx,ecx
	rep	movsb		; finish the scan line

	add	di,bx		; goto next scan line, can't CY
	add	si,bx
	jnc	$C95
	inc	dh		; goto next src page
	jmp	short $C94

$C70:				; split page at src
				; ax = # bytes in src page
	cmp	esi,edi		; if (srcoff == dstoff)
	je	$C40		; break occurs at the same place
	jb	$C50		; break occurs at maybe dstoff then srcoff
	jmp	$C60		; break occurs at srcoff then maybe at dstoff
$C40:				; ax has number of bytes after src page
	mov	ecx,edi
	neg	cx
	shr	ecx,1
	rep	movsw		; copy to end of page
	adc	ecx,ecx
	rep	movsb		; copy to end of page
	mov	edi,ecx		; zero dst
	mov	esi,ecx		; zero src
	mov	ecx,eax

	inc	dl		; goto next dst page
	inc	dh		; goto next src page
	setpage	dh,dl

	shr	cx,1
	rep	movsw		; finish the scan line
	adc	cx,cx
	rep	movsb		; finish the scan line

	add	si,bx		; can't cause a CY
	add	di,bx		; can't CY
	jmp	$C95

$C50:
				; ax = # bytes in src page
	add	cx,di		; if (dstoff + width > 0xffffL)
	jnc	$C55		; branch if split page at only srcoff
				; break occurs at dstoff first
	mov	cx,di
	neg	cx

	shr	cx,1
	rep	movsw		; copy to end of page
	adc	cx,cx
	rep	movsb		; copy to end of page
	mov	cx,ax		; cx has number of bytes left to copy

	inc	dl		; goto next dest page
	setpage	dh,dl

	mov	ax,cx
$C55:
	mov	cx,si
	neg	cx

	shr	cx,1
	rep	movsw		; copy to end of page
	adc	cx,cx
	rep	movsb		; copy to end of page
	mov	cx,ax		; cx has number of bytes left to copy

	inc	dh		; goto next src page
	setpage	dh,dl

	add	si,bx		; can't CY
	add	di,bx
	jnc	$C59
	inc	dl
	setpage	dh,dl
$C59:
	jmp	$C95

$C60:				; break occurs at srcoff then maybe dstoff
	mov	ecx,esi		; get srcoff
	neg	cx

	shr	ecx,1
	rep	movsw		; copy to end of page
	adc	ecx,ecx
	rep	movsb		; copy to end of page
	mov	esi,ecx		; zero si
	mov	ecx,eax		; cx has number of bytes left to copy

	inc	dh		; goto next src page
	setpage	dh,dl

	mov	eax,edi		; get dstoff
	add	ax,cx
	jnc	$C63		; jmp if no split page at dstoff
	mov	ecx,edi
	neg	cx

	shr	ecx,1
	rep	movsw		; copy to end of page
	adc	ecx,ecx
	rep	movsb		; copy to end of page
	mov	edi,ecx		; zero di
	mov	ecx,eax		; cx has number of bytes left to copy

	inc	dl		; goto next dst page
	setpage	dh,dl
$C63:
	shr	ecx,1
	rep	movsw		; copy to end of page
	adc	ecx,ecx
	rep	movsb		; copy to end of page

	add	si,bx		; can't CY
	add	di,bx
	jnc	$C65
	inc	dl
	setpage	dh,dl
$C65:
	jmp	$C95
CCOPY	ENDP
