;       SCCSID = @(#)bvfsubs.asm	6.1 90/11/16
;SCCSID = @(#)bvfsubs.asm	6.2 90/01/23
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
	PAGE	58,132
	TITLE	BvsSubs.Asm -- Base Video Subsystem Buffer Update Routines

;/*********************** START OF SPECIFICATIONS ***********************/
;/*									*/
;/* SOURCE FILE NAME:	 BvsSubs.Asm					*/
;/*									*/
;/* DESCRIPTIVE NAME:	 BVS Buffer Update Routines			*/
;/*									*/
;/* COPYRIGHT:	 na							*/
;/*									*/
;/* STATUS:	 na							*/
;/*									*/
;/* NOTES:	 Executes on level 3					*/
;/*									*/
;/*    DEPENDENCIES:	 none						*/
;/*									*/
;/*    RESTRICTIONS:	 none						*/
;/*									*/
;/*    PATCH LABEL:	 na						*/
;/*									*/
;/* ENTRY POINT: BvsReadXXX,BvsWriteXXX,BvsScrollXX			*/
;/*									*/
;/* EXTERNAL REFERENCES: RBufferUpdate					*/
;/*									*/
;/************************ END OF SPECIFICATIONS ************************/

BVSDSEG SEGMENT PARA PUBLIC 'DATA'
BVSDSEG ENDS

BVSNSEG SEGMENT PARA PUBLIC 'DATA'
BVSNSEG ENDS

	EXTRN	RBufferUpdate:FAR	;Retrace Buffer Routines

BVS3SEG SEGMENT BYTE PUBLIC 'CODE'
	ASSUME	CS:BVS3SEG

	.xlist
	INCLUDE bvfcb.inc		;BVS Data Structures
	INCLUDE error2.inc		;Error Equates
	INCLUDE struc.inc		;Structured Macros
	.list

;/*********************** START OF SPECIFICATIONS ***********************/
;/*									*/
;/* SUBROUTINE NAME:  BufferUpdate					*/
;/*									*/
;/* DESCRIPTIVE NAME:  Base Video Subsystem Buffer Update Controller	*/
;/*									*/
;/* FUNCTION:	Movement of data from the user's buffer to the          */
;/*		appropriate PVB, LVB, or both, depending on whether	*/
;/*		the current screen group is in the foreground or	*/
;/*		background and whether the LVB address has been exposed.*/
;/*									*/
;/* NOTES:  Executes on Level 3 and may call lower level routines	*/
;/*									*/
;/* ENTRY POINT:  BufferUpdate						*/
;/*   LINKAGE:	  Near Call from various modules as noted below 	*/
;/*									*/
;/* Subroutine Index:  MvBSSA	Move CX bytes Skip SI Attrs		*/
;/*			from BvsReadCharStr				*/
;/*									*/
;/* Subroutine Index:  MvBSDA	Move CX bytes Skip DI Attrs		*/
;/*			from BvsWrtCharStr				*/
;/*									*/
;/* Subroutine Index:  MvBWCA	Move CX bytes With AH Attr		*/
;/*			from BvsWrtCharStrAtt				*/
;/*									*/
;/* Subroutine Index:  MvWCSD	Move CX words from SI to DI		*/
;/*			from BvsScrollUp, BvsScrollDn,			*/
;/*			     BvsScrollLf, BvsScrollRt,			*/
;/*			     BvsReadCellStr, BvsWrtCellStr		*/
;/*									*/
;/* Subroutine Index:  StBCSD	Store CX bytes from SI at DI		*/
;/*			from BvsWrtNAttr, BvsWrtNChar			*/
;/*									*/
;/* Subroutine Index:  StWCSD	Store CX words from SI at DI		*/
;/*			from BvsScrollUp, BvsScrollDn,			*/
;/*			     BvsScrollLf, BvsScrollRt			*/
;/*									*/
;/* INPUT:	AL = Subroutine index (used in BX)			*/
;/*		AH = Constant attribute for BWCA			*/
;/*		CX = Length of string or number of times		*/
;/*		SI = Source offset or character/attr/cell		*/
;/*		DI = Destination offset 				*/
;/*		DS = BVSCB selector					*/
;/*		ES = User buffer selector				*/
;/*									*/
;/* EXIT-NORMAL:  AX destroyed; SI, DI, CX changed to reflect update	*/
;/*									*/
;/* EXIT-ERROR:  None							*/
;/*									*/
;/* EFFECTS:  None							*/
;/*									*/
;/* INTERNAL REFERENCES:  None						*/
;/*   ROUTINES:  MoveBSSA, MoveBSDA, MoveBWCA, MoveBCSD,		*/
;/*		 StoreBCSD, StoreWCSD, RBufferUpdate			*/
;/*									*/
;/* EXTERNAL REFERENCES:  None						*/
;/*   ROUTINES:  None							*/
;/*									*/
;/************************ END OF SPECIFICATIONS ************************/

;Bgnsub BufferUpdate
;: Get Selector of PVB
;: If Retrace
;: : Invoke appropriate MoveR/StoreR subroutine
;: Else
;: : Invoke appropriate Move/Store subroutine
;: Endif
;Endsub

BufferUpdate PROC NEAR
	PUBLIC	BufferUpdate

	.if	<nonzero cx> near	;Ignore null updates
	    push    bx
	    push    dx
	    push    bp

	    mov     dx,ax
	    sub     ah,ah
	    mov     bx,ax		;Get subroutine index in BX

	    push    si
	    push    di
	    push    cx			;Save regs for first half

	    mov     ax,ds:bvs_flags
	    pop     cx
	    pop     di
	    pop     si			;Restore regs from first half

	    push    ds
	    push    es
	    push    ax

	    mov     ax,bvsnseg
	    mov     ds,ax
	    mov     ax,ds:ppbvs_pvbsel	;Get PVB selector

	    mov     bp,bvsdseg
	    mov     ds,bp
	    sub     bp,bp		;Init TopView buffer offset
	    test    ds:cmn_devtypes,aioflag ;Check for TopView
	    .if     nz
		inc	bh
		push	es
		push	di
		mov	ah,0FEh
		int	10h		;ES:DI = TopView LVB
		mov	bp,di
		mov	ax,es
		pop	di
		pop	es
	    .endif

	    push    es
	    pop     ds			;Default moves to/from user space

	    cmp     bl,MvWCSDS
	    .if     le			;Read operation from PVB
		mov	ds,ax
		add	si,bp		;Get offset in TopView LVB
	    .endif
	    cmp     bl,MvWCSDS
	    .if     ge			;Write operation to PVB
		mov	es,ax
		add	di,bp		;Get offset in TopView LVB
	    .endif

	    pop     ax
	    .if     <bh eq 0>		;TopView not in system
		test	ax,bvs_f_retrace
		mov	ax,dx		;Restore constant attr
		.if	nz
		    Call    RBufferUpdate ;Perform retrace buffer update
		.else
		    Call    CS:SubTbl[BX] ;Invoke Move/Store routine
		.endif
	    .else
		sub	bh,bh		;Restore subroutine index
		push	di
		push	cx		;Save regs for TopView
		Call	CS:SubTbl[BX]	;Invoke Move/Store routine

		cmp	bl,MvWCSDS
		.if	ge		;Write to TopView LVB
		    mov     ax,di
		    mov     bx,cx	;Save regs for BVS
		    pop     cx		;Get offset in TopView LVB
		    pop     di
		    push    ax

		    pushf
		    pop     ax
		    and     ah,04h
		    .if     nz		;Decrement flag set
			sub	di,cx
			sub	di,cx
			inc	di
			inc	di	;Adjust for decrement flag
		    .endif

		    mov     ah,0FFh
		    int     10h 	;Request TopView redraw
		    mov     cx,bx
		    pop     di
		.else
		    pop     ax
		    pop     ax
		.endif

		cmp	bl,MvWCSDS
		.if	le		;Read operation from PVB
		    sub     si,bp	;Get offset in TopView LVB
		.endif
		.if	ge		;Write operation to PVB
		    sub     di,bp	;Get offset in TopView LVB
		.endif
	    .endif

	    pop     es
	    pop     ds

	    pop     bp
	    pop     dx
	    pop     bx
	.endif
	RET				;Return to caller
BufferUpdate ENDP

;Table of Update Subroutines
;   Index <= MvWCSDS ===> Source uses LVB/PVB
;   Index >= MvWCSDS ===> Destination uses LVB/PVB

SubTbl	dw	MoveBSSA		;Move Bytes and Skip Src Attrs
	dw	MoveWCSD		;Move Words from Src to Dest for Read
	dw	MoveWCSD		;Move Words from Src to Dest for Scroll
	dw	MoveWCSD		;Move Words from Src to Dest for Write
	dw	MoveBSDA		;Move Bytes and Skip Dest Attrs
	dw	MoveBWCA		;Move Bytes with Constant Attr
	dw	StoreBCSD		;Store Bytes and from SI to ES:DI
	dw	StoreWCSD		;Store Words from SI to ES:DI

MoveBSDA PROC	NEAR			;Move CX bytes skip DI attrs
	.repeat
	    movsb			;Move the first byte
	    inc     di			;Skip target attribute
	.loop
	RET
MoveBSDA ENDP

MoveBSSA PROC	NEAR			;Move CX bytes skip SI attrs
	.repeat
	    movsb			;Move the first byte
	    inc     si			;Skip source attribute
	.loop
	RET
MoveBSSA ENDP

MoveBWCA PROC	NEAR			;Move CX bytes with constant Attribute
	mov	al,ah
	.repeat
	    movsb			;Move one character
	    stosb			;Set the constant attr
	.loop
	RET
MoveBWCA ENDP

MoveWCSD PROC	NEAR			;Move CX words from DS:SI to ES:DI
	rep	movsw
	RET
MoveWCSD ENDP

StoreBCSD PROC	NEAR			;Store CX bytes from SI at ES:DI
	mov	ax,si
	.repeat
	    stosb			;Store character
	    inc     di			;Skip attribute
	.loop
	RET
StoreBCSD ENDP

StoreWCSD PROC	NEAR			;Store CX words from SI at ES:DI
	mov	ax,si
	rep	stosw			;Fill buffer with Cells
	RET
StoreWCSD ENDP

BVS3SEG ENDS
	END
