;
;	copy1.asm
;
;	copies from video memory to video memory for VGA cards
;	that do not have a separate read & write video map.
;

	ASSUME	cs:_text, ds:nothing, es:nothing, ss:nothing

;	void far copy(srcx, srcy, dstx, dsty, width, height)
;
;	copy rectangles
;
c_buf	=	-1024		; 1024 bytes of stack buffer
c_srcx	=	6
c_srcy	=	8
c_dstx	=	10
c_dsty	=	12
c_width	=	14
c_height =	16
CCOPY	PROC FAR
ccopy640:
	mov	bx,640		; 640 bytes per scan line
	jmp	short ccopy_it

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

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

	IF	VESA EQ 1
	jmp	short ccopy_it
ccopy1280:
	mov	bx,1280		; 1280 bytes per scan line
	ENDIF

ccopy_it:
	push	bp
	mov	bp,sp
	add	sp,c_buf	; reserve bytes on the stack
	push	ds
	push	es
	push	si
	push	di

	mov	ax,VGA_SEG
	mov	es,ax		; es -> VGA_SEG

	mov	ax,c_srcy[bp]
	mul	bx		; multiply it by screen width
	add	ax,c_srcx[bp]	; srcy * screen_width + srcx
	adc	dl,0		; adjust page
	mov	si,ax
	mov	cl,dl		; save src page

	mov	ax,c_dsty[bp]	; destination
	mul	bx		; multiply it by screen width
	add	ax,c_dstx[bp]
	adc	dl,0		; adjust page
	mov	di,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	di,si		; overlap can occur
	ja	overlap		; if dst < src, no overlap
$C10:				; reverse it
	sub	bx,c_width[bp]	; bytes to next scan line
	jmp	no_overlap

overlap:
	mov	cx,dx		; save page info in cx
	mov	ax,c_height[bp]	; get height
	dec	ax
	mul	bx		; (height - 1) * screen_width
	add	bx,c_width[bp]	; bx = number of bytes to next scan line

	add	si,ax		; have src point to last scan line
	adc	ch,dl		; fixup src page number
	add	di,ax		; have dest point to last scan line
	adc	cl,dl		; fixup dst page number
	mov	dx,cx		; dx has the current page info

again:
	mov	ax,es
	mov	ds,ax		; ds -> VGA_SEG
	mov	ax,ss
	mov	es,ax		; es -> ss

	setpage	dh		; set src page

	push	di		; save dst
	lea	di,c_buf[bp]
	mov	cx,c_width[bp]
	mov	ax,si		; if (srcoff + width > 0xffffL)
	add	ax,cx
	jnc	$R20		; branch if no split page at src
	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

	inc	dh		; next src page
	setpage	dh

	shr	cx,1
	rep	movsw		; copy a scan line
	adc	cx,cx
	rep	movsb		; copy a scan line
	sub	si,bx		; always CY
	dec	dh
	jmp	short $R30
$R20:
	shr	cx,1
	rep	movsw		; copy a scan line
	adc	cx,cx
	rep	movsb		; copy a scan line

	sub	si,bx		; point to next scan line
	jnc	$R30
	dec	dh		; next page
$R30:
	pop	di
	mov	ax,ds
	mov	es,ax		; es -> VGA_SEG
	mov	ax,ss
	mov	ds,ax		; ds -> ss

	setpage	dl		; set dst page

	push	si		; save src
	lea	si,c_buf[bp]
	mov	cx,c_width[bp]
	mov	ax,di		; if (srcoff + width > 0xffffL)
	add	ax,cx
	jnc	$R40		; branch if no split page at src
	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

	inc	dl		; next dst page
	setpage	dl

	shr	cx,1
	rep	movsw		; copy a scan line
	adc	cx,cx
	rep	movsb		; copy a scan line
	sub	di,bx		; always CY
	dec	dl
	jmp	short $R50
$R40:
	shr	cx,1
	rep	movsw		; copy to end of page
	adc	cx,cx
	rep	movsb		; copy to end of page

	sub	di,bx		; point to next scan line
	jnc	$R50
	dec	dl		; next page
$R50:
	pop	si

	dec	word ptr c_height[bp]	; decrement the height
	jz	$R90
	jmp	again
$R90:				; were done, go home
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

no_overlap:			; bx = bytes to next scan line
	mov	ax,es
	mov	ds,ax		; ds -> VGA_SEG
	mov	ax,ss
	mov	es,ax		; es -> ss

	setpage	dh		; set src page

	push	di		; save dst
	lea	di,c_buf[bp]
	mov	cx,c_width[bp]
	mov	ax,si		; if (srcoff + width > 0xffffL)
	add	ax,cx
	jnc	$C20		; branch if no split page at src
	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

	inc	dh		; next src page
	setpage	dh

	shr	cx,1
	rep	movsw		; copy a scan line
	adc	cx,cx
	rep	movsb		; copy a scan line
	add	si,bx		; can't CY
	jmp	short $C30
$C20:
	shr	cx,1
	rep	movsw		; copy a scan line
	adc	cx,cx
	rep	movsb		; copy a scan line

	add	si,bx		; point to next scan line
	jnc	$C30
	inc	dh		; next page
$C30:
	pop	di
	mov	ax,ds
	mov	es,ax		; es -> VGA_SEG
	mov	ax,ss
	mov	ds,ax
;this line above ok
;recovered based on disassembly using ndisasm
	setpage	dl		; set dst page

	push 	si            
	lea	si,c_buf[bp]       	
	mov	cx,c_width[bp]   
	mov 	ax,di          
	add 	ax,cx          
	jnc 	$C40         
	mov 	cx,di          
	neg 	cx             

	shr 	cx,1           
	rep 	movsw          	
	adc 	cx,cx          
	rep 	movsb          
	mov 	cx,ax          

	inc 	dl             
	setpage	dl

	shr 	cx,1 	
	rep 	movsw
	adc 	cx,cx
	rep 	movsb
	add 	di,bx
	jmp 	short $C50
;this line below ok
$C40:
	shr	cx,1
	rep	movsw		; copy to end of page
	adc	cx,cx
	rep	movsb		; copy to end of page

	add	di,bx		; point to next scan line
	jnc	$C50
	inc	dl		; next page
$C50:
	pop	si

	dec	word ptr c_height[bp]	; decrement the height
	jz	$C90
	jmp	no_overlap
$C90:				; were done, go home
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret
CCOPY	ENDP
