	page 60, 132
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   NAME:  ULTRASND.ASM $Revision: 1.2 $
;;  COPYRIGHT:
;;  "Copyright (c) 1994,1995 by e-Tek Labs"
;;
;;       "This software is furnished under a license and may be used,
;;       copied, or disclosed only in accordance with the terms of such
;;       license and with the inclusion of the above copyright notice.
;;       This software or any other copies thereof may not be provided or
;;       otherwise made available to any other person. No title to and
;;       ownership of the software is hereby transfered."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $Log: interwav.asm $
; Revision 1.2  1995/03/01 17:46:16  teckert
; Added file header
; Revision 1.1  1995/02/23 15:14:59  sdsmith
; Initial revision
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	.286

	.xlist
	include cmacros.inc                   
	include windows.inc
	include mmsystem.inc
	include mmddk.inc
	.list

	?PLM=1                          ; Pascal call convention
	?WIN=1                          ; Windows prolog/epilog code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   extrn declarations
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

	externA <__AHINCR>                  ; kernel

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   segmentation
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IFNDEF SEGNAME
	SEGNAME equ <_TEXT>
ENDIF

createSeg %SEGNAME, CodeSeg, word, public, CODE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   code segment
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

sBegin CodeSeg

	assumes cs, CodeSeg

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @doc INTERNAL 
;
; @asm LPVOID | MemCopySrc | Block memory copy.
;
; @parm LPVOID | lpDst | Destination.
;
; @parm LPVOID | lpSrc | Source.
;
; @parm WORD | cnt | Number of bytes to copy.
;
; @rdesc Returns the source pointer advanced by <p cnt> bytes.
;
; @comm This function handles segment crossings in the source *only*.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	assumes ds, nothing
	assumes es, nothing

cProc MemCopySrc <FAR, PASCAL, PUBLIC> <ds, si, di>
	ParmD   lpDst
	ParmD   lpSrc
	ParmW   wCount
cBegin

	lds     si, lpSrc             ; get source pointer
	mov     cx, wCount            ; cx is count of bytes
	jcxz    mcs_Exit              ; copy no bytes--return current pointer...

	cld                           ; let's not assume this
	les     di, lpDst             ; get dest pointer

	mov     ax, si                ; check for a segment cross in the source
	add     ax, cx
	sbb     bx, bx                ; if C BX=FFFF, NC BX=0000
	and     ax, bx                ;
	sub     cx, ax                ; CX contains amount to copy now, AX has
					  ; ...amount to copy later

mcs_Copy_It:

	jcxz    mcs_Exit
	shr     cx, 1                 ; copy the memory
	rep     movsw
	adc     cl, cl
	rep     movsb

	or      si, si                ; check for a segment wrap
	jnz     mcs_Exit

	mov     cx, ax
	mov     ax, ds
	add     ax, __AHINCR

;vvvvvvvv Fix from CIS vvvvvvvv
	jcxz    mcs_NoDS                ; if no bytes to copy in this segment
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	mov     ds, ax
	jmp     short mcs_Copy_It

;vvvvvvvv Fix from CIS vvvvvvvv

mcs_NoDS:

	mov     dx, ax                  ; just point to the new segment
	mov     ax, si
	jmp     mcs_Done

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

mcs_Exit:

	mov     dx, ds                ; DX:AX = advanced source pointer
	mov     ax, si

;vvvvvvvv Fix from CIS vvvvvvvv

mcs_Done:

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

cEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @doc INTERNAL 
;
; @asm LPVOID | MemCopyDest | Block memory copy.
;
; @parm LPVOID | lpDst | Destination.
;
; @parm LPVOID | lpSrc | Source.
;
; @parm WORD | wCount | Number of bytes to copy.
;
; @rdesc Returns the destination pointer advanced by <p wCount> bytes.
;
; @comm This function handles segment crossings in the destination *only*.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	assumes ds, nothing
	assumes es, nothing

cProc MemCopyDst <FAR, PASCAL, PUBLIC> <ds, si, di>
	ParmD   lpDst
	ParmD   lpSrc
	ParmW   wCount
cBegin

	cld                             ; let's not assume this

	lds     si, lpSrc               ; get source pointer
	les     di, lpDst               ; get dest pointer
	mov     cx, wCount              ; cx is count of bytes

	mov     ax, di                  ; check for a segment cross in the dest
	add     ax, cx
	sbb     bx, bx                  ; if C BX=FFFF, NC BX=0000
	and     ax, bx                  ;
	sub     cx, ax                  ; CX contains amount to copy now, AX has
					; ...amount to copy later
mcd_Copy_It:

	jcxz    mcd_Exit
	shr     cx, 1                   ; copy the memory
	rep     movsw
	adc     cl, cl
	rep     movsb

	or      di, di                  ; check for a segment wrap
	jnz     mcd_Exit

	mov     cx, ax                  ; cross huge boundary
	mov     ax, es
	add     ax, __AHINCR

;vvvvvvvv Fix from CIS vvvvvvvv
	jcxz    mcd_NoES                ; if no bytes to copy in this segment
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

	mov     es, ax
	jmp     short mcd_Copy_It

;vvvvvvvv Fix from CIS vvvvvvvv

mcd_NoES:

	mov     dx, ax                  ; just point to the new segment
	mov     ax, di
	jmp     mcd_Done

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


mcd_Exit:

	mov     dx, es                  ; DX:AX = advanced dest pointer
	mov     ax, di

;vvvvvvvv Fix from CIS vvvvvvvv

mcd_Done:

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

cEnd

sEnd CodeSeg

	end
