; MyMouse, 256 colors SVGA, assembler source,
; Copr. 1993,97 Matthias K”ppe

		INCLUDE	mymodef.asm	; MyMouse Definitions
		INCLUDE	grserv.asm	; Gr Services

_Linear		EQU	DWORD PTR DrawData[0]
_VertCount	EQU	WORD PTR DrawData[4]
_VertStart	EQU	WORD PTR DrawData[6]
_LineDelta	EQU	WORD PTR DrawData[8]
_HorizCount	EQU	WORD PTR DrawData[10]
_HorizStart	EQU	WORD PTR DrawData[12]

CODE		SEGMENT BYTE PUBLIC

		PUBLIC	ServiceTbl256, ServiceTbl256s

	; CalcValues calculates commonly used parameters and stores them
	; in the data area.
	;
	; Out:  dx:ax	_Linear
	;	bx	_VertCount (zero if nothing to do)
	;	cx	_HorizCount

CalcValues	PROC NEAR
		les	di, CursorPtr

	; horizontal values

		mov	cx, es:[di+2]		; CX width in source bytes
		shl	cx, 3			; CX width in pixels
		mov	_HorizStart, 0
		mov	si, MouseWhere.X
		sub	si, es:[di+4]		; SI horiz start
		jae	SHORT @@4
		add	cx, si			; CX left-clipped width
		jle	SHORT @@0		; nothing to do
		neg	si
		mov	_HorizStart, si
		mov	si, 0
@@4:		mov	ax, SizeX
		sub	ax, si
		jbe	SHORT @@0		; nothing to do
		cmp	ax, cx
		jae	SHORT @@1
		mov	cx, ax			; CX right-clipped width
@@1:		mov	_HorizCount, cx
		mov	ax, RealBytesPerLine
		sub	ax, cx
		mov     _LineDelta, ax

	; vertical values

		mov	bx, es:[di]		; BX height
		mov	ax, MouseWhere.Y
		mov	_VertStart, 0
		sub	ax, es:[di+6]
		jns     SHORT @@7
		add	bx, ax			; BX top-clipped height
		js	SHORT @@0		; nothing to do
		neg	ax
		mov	_VertStart, ax
		jmp	SHORT @@8

@@7:		mov	dx, SizeY
		sub	dx, ax
		ja	@@9

@@0:		mov	_VertCount, 0		; nothing to do
		xor	bx, bx
		retn

@@9:		cmp	dx, bx
		jae	SHORT @@2
		mov	bx, dx			; BX bottom-clipped height
@@2:		mul     RealBytesPerLine
		add     si, ax
		adc	dx, 0			; DX:SI linear start
@@8:            mov	_VertCount, bx
		mov	ax, si
		add	ax, WORD PTR MousePageLinear[0]
		adc	dx, WORD PTR MousePageLinear[2]
		mov	WORD PTR _Linear[0], ax
		mov	WORD PTR _Linear[2], dx

		retn
CalcValues	ENDP

	; DrawMaskLoop draws one mask to the screen
	;
	; In:	es:si	Mask (source)
	;	ds:di	Screen address (dest)
	;	cl	Horizontal start (pixels)
	;	ch	Vertical count
	;	bl	Horizontal count
	;	dx	WindowSize
	;
	; Out:	ax, cx, si, di   destroyed
	;
	; Arg:	TheColor empty if to store 0, else value to xor
	;
	; DrawMaskLoop accesses variables on DrawMouse256s's stack frame.

DrawMaskLoop	MACRO	TheColor
		LOCAL	@@1, @@2, @@3, @@4, @@5, \
			@@6, @@7, @@8, @@9
@@6:		sub	cl, 16			; forward coloumns
		jb	SHORT @@5
		add	si, ColDelta
		jmp	@@6
@@5:		add	cl, 16
@@1:		MOV     AX, ES:[SI]		; get mask word
		SHL     AX, CL
		PushMapping DSeg, DestSeg
		push	di bx si cx
		sub	cl, 10h
		neg	cl
@@9:		cmp	cl, bl
		jb	SHORT @@8
		mov	cl, bl
@@8:		sub	bl, cl
@@2:		shl     ax, 1
		jnc     SHORT @@3
	IFB <TheColor>
		mov	BYTE PTR [di], 0
	ELSE
		xor     BYTE PTR [di], TheColor
	ENDIF
@@3:		;jz      SHORT @@4
		add	di, 1
		MapNext	di, dx, SetDS
		dec     cl
		jnz	@@2

@@4:		or	bl, bl
		jz	SHORT @@7		; done
		mov	al, cl          	; skip remaining pixels
		xor	ah, ah
		add	di, ax
		MapNext	di, dx, SetDS

		add	si, ColDelta		; next coloumn
		mov	ax, es:[si]
		mov	cl, 10h
		jmp	@@9

@@7:		pop	cx si bx di
		PopMapping DSeg, DestSeg
		add     di, bpl
		MapNext	di, dx, SetDS
		add	si, 2
		DEC     CH
		JNZ     @@1
		ENDM

	;
	; DrawMouse256s routine
	;

DrawMouse256s	PROC NEAR			; actually FAR
		LOCAL	DSeg: WORD, DestSeg: WORD, bpl: WORD, \
			ColDelta: WORD, WidthBytes: WORD, \
			Color: BYTE = LocalSize
		cld
		enter	LocalSize, 0
		PushMapping
		mov	ax, RealBytesPerLine
		mov	bpl, ax
		mov	DSeg, ds
		mov	ch, BYTE PTR _VertCount
		or	ch, ch
		jz	@@23			; nothing to draw

	; prepare adaptor

		MOV     DX, 03CEH               ; GC
		MOV     AX, 0FF08H              ; Bit Mask Reg: Unmasked
		OUT     DX, AX
		MOV     AX, 0003H               ; Data Rotate Reg
		OUT     DX, AX
		MOV	AX, 4005H		; Graphics Mode Reg
		OUT	DX, AX
		MOV	AX, 0001H		; Enable Set/Reset Reg
		OUT	DX, AX

	; get params

		les	si, CursorPtr
		mov	ax, es:[si]
		push	ax
		shl	ax, 1
		mov	ColDelta, ax
		mov	ax, es:[si+2]
		mov     WidthBytes, ax
		add	si, 8			; si at screen mask
		mov	ax, _VertStart
		shl	ax, 1
		add	si, ax			; forward in mask
		mov	bx, _HorizCount
		mov	cl, BYTE PTR _HorizStart
		mov	ax, WORD PTR _Linear[0]
		mov	dx, WORD PTR _Linear[2]
		call	MapLinear		; DX:AX pointer to window
		mov	bh, PointerColor
		mov	Color, bh
		mov	di, ax			; dest offset
		pop	ax			; get height
		mov	ah, ch			; clipped height
		mov	DestSeg, dx
		push	si ax
		mov	ax, WindowSize
		mov	ds, dx			; dest segment
		mov	dx, ax
		PushMapping DSeg, DestSeg
		push	di

	; screen-mask loop

		mov	bh, 0
		push	cx
		DrawMaskLoop
		pop	cx

	; prepare for pixel mask

		pop	di
		PopMapping DSeg, DestSeg
		pop	ax si

		mul	BYTE PTR WidthBytes
		add     si, ax			; to pixel mask

		;push	dx
		;mov	dx, 03CEh		; GC
		;mov	ax, 1803h		; Data Rotate: XOR
		;out	dx, ax
		;pop	dx

	; pixel-mask loop

		mov	bh, Color
		DrawMaskLoop bh

	; done

@@23:           mov	ds, DSeg
		MOV	DX, 03CEH
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		PopMapping ,,ax
		leave
		retf
DrawMouse256s	ENDP

	;
	; SaveScreen256s routine uses main RAM to save the background.
	;

SaveScreen256s	PROC NEAR			; actually FAR
		call	CalcValues
		or	bx, bx
		jz	@@6
		PushMapping
		call	MapLinear
		push	ds bp
		mov	bp, _LineDelta
		les	di, MouseSavePtr	; main RAM save area
		mov	si, WindowSize
		mov	ds, dx
		mov	dx, si
		mov     si, ax
		cld

@@3:    	DoRepMovsb si, dx,, SetDS, WORD
		add     si, bp
		MapNext	si, dx, SetDS
		dec     bx
		jnz     @@3

		pop	bp ds
		PopMapping ,,ax
@@6:		retf
SaveScreen256s	ENDP

	;
	; RestoreScreen256s routine restores the background from main RAM.
	;

RestoreScreen256s	PROC NEAR		; actually FAR
		cmp	_VertCount, 0		; nothing saved
		jnz	SHORT @@1
		retf
@@1:		push	bp
		cld
		PushMapping
		MOV     DX, 03CEH               ; GC
		MOV     AX, 0FF08H              ; Bit Mask Reg: Unmasked
		OUT     DX, AX
		MOV     AX, 0003H               ; Data Rotate Reg
		OUT     DX, AX
		MOV	AX, 4005H		; Graphics Mode Reg
		OUT	DX, AX
		MOV	AX, 0001H		; Enable Set/Reset Reg
		OUT	DX, AX

		mov	ax, WORD PTR _Linear[0]
		mov	dx, WORD PTR _Linear[2]
		call	MapLinear		; DX:AX pointer to window

		mov	es, dx
		mov	di, ax
		mov	bx, _VertCount
		mov	bp, _LineDelta
		mov	cx, _HorizCount
		mov	dx, WindowSize
		push	ds
		lds	si, MouseSavePtr	; main RAM save area

@@3:    	DoRepMovsb di, dx,, SetDS, WORD
		add     di, bp
		MapNext	di, dx, SetDS
		dec     bx
		jnz     @@3

		pop	ds
		MOV	DX, 03CEH
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		PopMapping ,,ax

		pop	bp
@@6:		retf
RestoreScreen256s	ENDP

	;
	; SaveScreen256 routine uses rest video memory to save the
	; background. Only applicable in non-mapping modes.
	;

SaveScreen256	PROC NEAR			; actually FAR
		cld
		call	CalcValues
		or	bx, bx
		jz	SHORT @@0
		mov	si, ax
		les	di, MouseSavePtr
		mov	dx, cx			; HorizCount
		push	bp
		mov	bp, RealBytesPerLine
		sub	bp, cx
@@3:    	mov     cx, dx
		rep     seges movsb
		add     si, bp
		dec     bx
		jnz     @@3
		pop     bp
@@0:		retf
SaveScreen256	ENDP

	;
	; RestoreScreen256 routine restores the background from
	; the rest video memory
	;

RestoreScreen256	PROC NEAR		; actually FAR
		mov	bx, _VertCount
		or	bx, bx
		jz	SHORT @@0
		CLD
		MOV     DX, 03CEH               ; GC
		MOV     AX, 0FF08H              ; Bit Mask Reg: Unmasked
		OUT     DX, AX
		MOV     AX, 0003H               ; Data Rotate Reg
		OUT     DX, AX
		MOV	AX, 4005H		; Graphics Mode Reg
		OUT	DX, AX
		MOV	AX, 0001H		; Enable Set/Reset Reg
		OUT	DX, AX

		MOV	di, WORD PTR _Linear[0]
		les	si, MouseSavePtr
		mov	dx, _HorizCount
		push	bp
		mov	bp, _LineDelta
@@4:    	mov	cx, dx
		rep	seges movsb
		add	di, bp
		dec	bx
		jnz	@@4
		pop	bp
@@0:
		MOV	DX, 03CEH
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		retf
RestoreScreen256	ENDP

	;
	; Dummy routine
	;

Dummy		PROC NEAR
		retf
Dummy		ENDP

	;
	; Service tables
	;

ServiceTbl256	PROC NEAR
		DW	DrawMouse256s
		DW	SaveScreen256
		DW	RestoreScreen256
		DW	Dummy
		DW	Dummy
ServiceTbl256	ENDP

ServiceTbl256s	PROC NEAR
		DW	DrawMouse256s
		DW	SaveScreen256s
		DW	RestoreScreen256s
		DW	Dummy
		DW	Dummy
ServiceTbl256s	ENDP

CODE		ENDS

		END
