;***********************************************************************
;
; __SpeedScn  Move a buffer to (or from) the screen directly
;
; procedure __SpeedScn(   SourcePtr,TargetPtr : Pointer;
;		       Count,Option,Attribute : word;
;				    WaitTrace : boolean);
;
;	      SourcePtr Pointer to buffer to be transferred.  For
;			Option 4 (see below), it is ignored.
;	      TargetPtr Pointer to location to which the buffer is
;			transferred.
;	      Count	The number of characters in the source buffer
;			that are to be transferred.
;	      Option	The source buffer may be transferred in five
;			ways:
;			Option	 Description
;			-------  -----------------------------------
;			  0	  The buffer contains just characters
;				  and the attributes are not altered.
;			  1	  The buffer contains just characters,
;				  but the characters are written with
;				  the specified attributes.
;			  2	  The buffer is made up of characters
;				  followed by attribute bytes.
;			  3	  This is like option 2, but to be
;				  used when moving data from the screen
;				  to a buffer.
;			  4	  The buffer is not transferred at all,
;				  but Count copies of the attribute are
;				  transferred without altering the
;				  characters on the screen.
;			Note that for options 2 and 3, Count refers to
;			the number of words, rather than bytes, moved
;			from the source buffer since there is an attri-
;			bute byte associated with each character.
;	      Attribute The attribute to use with option 1.  The value
;			is ignored for options 0, 2 and 3.
;	      WaitTrace If TRUE, items are not transferred from the
;			source to the target unless horizontal retrace
;			is active.  For option 3, data is not read from
;			the source unless horizontal retrace is active.
;
; Description This is a low-level routine designed to perform fast
;	      direct access to the video adapter.  It is called by
;	      __FastScn, and because any error checking is done there,
;	      it is recommended that __FastScn be used rather than
;	      __SpeedScn directly.  It is up to the calling program to
;	      make sure the parameters are reasonable and whether
;	      horizontal retrace must be detected (i.e., WaitTRACE is
;	      TRUE). Specifying an incorrect value for the parameters can
;	      cause unpredictable results.
;
;			     *** CAUTION ***
;	      __SpeedScn should only be called while in text mode.
;	      Accessing the video buffer directly while in graphics
;	      mode causes unpredicatable results.
;
; Version     4.00 (C)Copyright Blaise Computing Inc. 1987
;_______________________________________________________________________

code	 segment
	 assume    cs:code
	 public    __SpeedScn

; Parameter equates

stkoffset	   equ	 6	       ; Far call plus BP on the stack
SourcePtr	   equ	 dword ptr [bp + stkoffset + 12]
TargetPtr	   equ	 dword ptr [bp + stkoffset + 8]
Count		   equ	 word ptr  [bp + stkoffset + 6]
Option		   equ	 word ptr  [bp + stkoffset + 4]
Attribute	   equ	 word ptr  [bp + stkoffset + 2]
WaitTrace	   equ	 byte ptr  [bp + stkoffset + 0]
CrtAddr 	   equ	 03DAh	       ; 6845 register address

__SpeedScn	   proc  far

	 push	   bp		       ; Set up the stack frame
	 mov	   bp,sp	       ; and and retrieve the parameters.
	 push	   ds

	 ; If the wait flag is nonzero, transfer between buffers
	 ; occurs only during horizontal retrace, and at most two
	 ; bytes are moved at a time (using STOSB or STOSW string
	 ; operations).

	 lds	   si,SourcePtr
	 les	   di,TargetPtr
	 mov	   cx,Count
	 mov	   ax,Option
	 mov	   bl,WaitTrace
	 mov	   dx,CrtAddr
	 cld

	 ; Determine which option is chosen.  For each option, if
	 ; the WaitTrace flag is TRUE (i.e., BL is nonzero), we make sure
	 ; horizontal retrace is on before moving the byte (or word).
	 ; This is done by first waiting for horizontal retrace to
	 ; be inactive, and then waiting for it to start.  In this
	 ; way, we get a full retrace cycle to transfer the data.

	 cmp	   ax,0
	 jz	   option_0
	 dec	   ax
	 jz	   option_1
	 dec	   ax
	 jz	   option_2
	 dec	   ax
	 jz	   option_3
	 jmp	   option_4

option_0:			       ; Buffer contains just characters
	 cmp	   bl,0
	 jz	   nowait_0	       ; Waiting is not required
loop_0:
	 lodsb
	 mov	   bx,ax
endhz_0:
	 in	   al,dx
	 test	   al,1
	 jnz	   endhz_0
	 cli
starthz_0:
	 in	   al,dx
	 test	   al,1
	 jz	   starthz_0
	 mov	   ax,bx	       ; Finally can do the access
	 stosb
	 sti
	 inc	   di
	 loop	   loop_0
	 jmp	   end_speed
nowait_0:			       ; Just do a string move
	 lodsb
	 stosb
	 inc	   di
	 loop	   nowait_0
	 jmp	   end_speed

option_1:			       ; Write characters with the
	 xor	   ax,ax	       ; specified attribute
	 mov	   ax,Attribute
	 mov	   ah,al
	 cmp	   bl,0
	 jz	   nowait_1;
loop_1:
	 lodsb
	 mov	   bx,ax
endhz_1:
	 in	   al,dx
	 test	   al,1
	 jnz	   endhz_1
	 cli
starthz_1:
	 in	   al,dx
	 test	   al,1
	 jz	   starthz_1
	 mov	   ax,bx
	 stosw
	 sti
	 loop	   loop_1
	 jmp short end_speed
nowait_1:
	 lodsb
	 stosw
	 loop	   nowait_1
	 jmp short end_speed

option_2:			       ; Write characters and attributes
	 cmp	   bl,0
	 jz	   nowait_2
loop_2:
	 lodsw
	 mov	   bx,ax
endhz_2:
	 in	   al,dx
	 test	   al,1
	 jnz	   endhz_2
	 cli
starthz_2:
	 in	   al,dx
	 test	   al,1
	 jz	   starthz_2
	 mov	   ax,bx
	 stosw
	 sti
	 loop	   loop_2
	 jmp short end_speed
nowait_2:
	 lodsw
	 stosw
	 loop	   nowait_2
	 jmp short end_speed

option_3:
	 cmp	   bl,0
	 jz	   nowait_3
loop_3:
endhz_3:
	 in	   al,dx
	 test	   al,1
	 jnz	   endhz_3
	 cli
starthz_3:
	 in	   al,dx
	 test	   al,1
	 jz	   starthz_3
	 lodsw
	 sti
	 stosw
	 loop	   loop_3
	 jmp short end_speed
nowait_3:
	 lodsw
	 stosw
	 loop	   nowait_3
	 jmp short end_speed

option_4:			       ; Write attribute only
	 cmp	   bl,0
	 jz	   nowait_4	       ; Waiting is not required
	 mov	   bx,Attribute
loop_4:
	 in	   al,dx
	 test	   al,1
	 jnz	   loop_4
	 cli
starthz_4:
	 in	   al,dx
	 test	   al,1
	 jz	   starthz_4
	 mov	   ax,bx	       ; get Attribute ready for stosb
	 inc	   di
	 stosb
	 sti
	 loop	   loop_4
	 jmp short end_speed
nowait_4:			       ; Just do a string fill
	 mov ax,Attribute
nowait_41:
	 inc	   di		       ; skip over character
	 stosb
	 loop	   nowait_41

end_speed:
	 pop	   ds
	 pop	   bp
	 ret	   16

__SpeedScn	   endp
code		   ends
	 end
