; MyMouse, 16 colors, assembler source, Copr. 1993,94 Matthias Kppe
;
; mymo16.inf mymouse

		INCLUDE	mymodef.asm
		INCLUDE	grserv.asm

_CountShift	EQU	WORD PTR DrawData[0]
_OfsDest	EQU	WORD PTR DrawData[2]
_DrawCode	EQU	WORD PTR DrawData[4]
_SaveWidth	EQU	WORD PTR DrawData[6]
_Linear		EQU	DWORD PTR DrawData[8]

CODE		SEGMENT BYTE PUBLIC

		PUBLIC	ServiceTbl16, ServiceTbl16s

DrawMouse16	PROC NEAR			; actually far
		LOCAL	BytesPL: WORD, OfsSM: WORD, OfsPM: WORD, \
			CountShift: WORD, OfsDest: WORD, Color: BYTE: 2, \
			TheCode: WORD, CurOfs: WORD, ColDelta: WORD, \
			CurOfsDest: WORD, CurCode: WORD, \
			TheSegment: WORD, DataSegment: WORD = LocalSize
		enter	LocalSize, 0
		MOV     AX, RealBytesPerLine
		MOV	[BytesPL], AX
		MOV	AL, PointerColor
		MOV	[Color], AL

		LES	SI, CursorPtr
		MOV	BL, ES:[SI+2]		; Breite des Cursors
		MOV	BH, BYTE PTR MaxWidth
		CMP	BL, BH
		JBE	SHORT @@40
		MOV	BL, BH			; maximale Breite vorgeben
@@40:		XOR	BH, BH			; erstes Byte / "rechts"
		MOV     DI, MouseWhere.X
		SUB	DI, ES:[SI+4]
		SAR     DI, 3
		JNS	SHORT @@1
		MOV	AX, DI			; ber linken Rand hinaus
		SUB	BH, AL
		JMP	SHORT @@7
@@1:		MOV	AX, [BytesPL]		; rechts abschneiden
		SUB	AX, DI
		CMP	AL, BL
		JA	SHORT @@7
		MOV     BL, AL
		MOV	BH, 0FFH		; "rechts"
@@7:		MOV     AX, MouseWhere.Y
		SUB	AX, ES:[SI+6]
		jns	SHORT @@37

		mov	ch, al			; oben abschneiden
		mov	ax, di
		xor	dx, dx
		mov	cl, ch
		jmp	SHORT @@2

@@37:           mov	cx, ax
		ADD	cx, ES:[SI]
		SUB	cx, SizeY
		NEG	cx
		MOV	ch, cl
		MOV	cl, 0
		JS	SHORT @@99
		XOR	ch, ch

@@99:           MUL	[BytesPL]
		add     ax, di
		adc	dx, 0
@@2:		add	ax, WORD PTR MousePageLinear[0]
		adc	dx, WORD PTR MousePageLinear[2]
		mov	WORD PTR _Linear[0], ax
		mov	WORD PTR _Linear[2], dx	; DX:AX linear address
		call	MapLinear
		mov	di, ax			; DX:DI mapped address

		mov	ax, cx
		MOV	[TheCode], BX
		MOV	_DrawCode, BX

		MOV	[TheSegment], DX
		MOV	[OfsDest], DI
		MOV	_OfsDest, DI

		MOV     CX, MouseWhere.X
		SUB	CX, ES:[SI+4]
		AND     CX, 7
		MOV     CH, ES:[SI]		; Lnge des Cursors
		CMP	CH, BYTE PTR MaxLength
		JBE	SHORT @@41
		MOV	CH, BYTE PTR MaxLength	; maximale Lnge vorgeben
@@41:		ADD	CH, AH			; unten/oben abschneiden
		CBW
		MOV	[CountShift], CX
		MOV	_CountShift, CX
		SHL	AX, 1

		MOV	CX, SI
		SUB	CX, AX
		ADD	CX, 8
		MOV	[OfsSM], CX		; Screen Mask Offset
		MOV	[CurOfs], CX
		MOV	DX, ES:[SI]
		MOV	AX, ES:[SI+2]
		MUL	DX
		MOV	DX, ES:[SI]
		SHL	DX, 1
		MOV	[ColDelta], DX		; Column Delta Value
		ADD	AX, CX
		MOV	[OfsPM], AX		; Pixel Mask Offset

		PushMapping
		mov	[DataSegment], ds
		MOV	DS, [TheSegment]

		MOV     DX, 03CEH               ; GC
		MOV     AX, 0803H		; Data Rotate: AND
		OUT     DX, AX
		MOV     AX, 0FF08H		; Bit Mask Reg: Unmasked
		OUT	DX, AX
		MOV     AX, 0001H		; Enable Set/Reset: All from CPU
		OUT     DX, AX
		MOV	AX, 0005H		; Write Mode 0
		OUT	DX, AX
		MOV     DX, 03C4H		; SC
		MOV     AX, 0F02H		; Map Mask Reg: All Enabled
		OUT     DX, AX

		MOV	BX, 0FFFFH		; Data Mask
		CALL	DoDraw
		PopMapping DataSegment, TheSegment

		MOV     DX, 03CEH		; GC
		MOV     AX, 1803H		; Data Rotate Reg: XOR
		OUT     DX, AX
		MOV	DX, 03C4H
		MOV	AH, [Color]
		MOV     AL, 02H			; Map Mask Reg
		OUT     DX, AX

		MOV	SI, [OfsPM]		; Pixel Mask
		MOV	[CurOfs], SI

		MOV	BX, 0			; Data Mask
		CALL	DoDraw

@@10:   	mov	ds, [DataSegment]
		MOV	DX, 03CEH
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		leave
		retf
DrawMouse16	ENDP

	; DoDraw accesses variables on DrawMouse16's stack frame.

DoDraw		PROC NEAR

		MOV	DX, [BytesPL]
		MOV	AX, [TheCode]
		MOV	[CurCode], AX
		MOV	DI, [OfsDest]
		MOV	[CurOfsDest], DI

@@11:   	MOV	CX, [CountShift]
		MOV	SI, [CurOfs]

@@12:		OR	AL, AL
		JLE	SHORT @@14		; to RETN
		CMP     AX, 0FF01H
		JZ	SHORT @@1
		CMP	AX, 0FF02H
		JZ	SHORT @@3
		CMP	AH, 1
		JZ	SHORT @@5
		CMP	AH, 2
		JGE	SHORT @@8

@@10:		MOV     AX, ES:[SI]		; Standard: alles schreiben
		SHR     AX, CL
		XOR	AX, BX
		XCHG    [DI], AH
		XCHG	[DI+1], AL
		MOV     AH, ES:[SI]
		MOV     AL, 0
		SHR     AX, CL
		XOR	AL, BL
		XCHG	[DI+2], AL
		ADD     DI, DX
		ADD	SI, 2
		DEC     CH
		JNZ     @@10
		JMP	SHORT @@9

@@8:    	JZ	SHORT @@7
		ADD	SI, [ColDelta]		; links: fhrende Doppelquellspalten
		MOV	[CurOfs], SI
		SUB	AX, 0202H		; eigentlich sub ah, 2; sub al, 2
		MOV	[CurCode], AX		; aber es ist ah >= 3
		ADD	DI, 2
		MOV	[CurOfsDest], DI
		JMP	@@12

@@1:		MOV     AL, ES:[SI+1]		; rechts: 1 Quellbyte
		SHR     AL, CL
		XOR	AL, BL
		XCHG	[DI], AL		; XCHG fhrt Leseoperation aus
		ADD     DI, DX			; -> Latches werden gefllt
		ADD	SI, 2			; Danach fhrt es Schreiboperation
		DEC     CH			; aus -> Bild wird korrigiert
		JNZ     @@1
@@14:		retn

@@3:    	MOV     AX, ES:[SI]		; rechts: 2 Quellbyte
		SHR     AX, CL
		XOR	AX, BX
		XCHG	[DI], AH
		XCHG	[DI+1], AL
		ADD     DI, DX
		ADD	SI, 2
		DEC     CH
		JNZ     @@3
		retn

@@5:		MOV     AX, ES:[SI]		; links: erstes Byte nicht schreiben
		SHR     AX, CL
		XOR	AX, BX
		XCHG	[DI+1], AL
		MOV     AH, ES:[SI]
		MOV     AL, 0
		SHR     AX, CL
		XOR	AL, BL
		XCHG	[DI+2], AL
		ADD     DI, DX
		ADD	SI, 2
		DEC     CH
		JNZ     @@5
		JMP	@@9

@@7:		MOV     AH, ES:[SI]		; links: erste 2 Byte nicht schr.
		MOV     AL, 0
		SHR     AX, CL
		XOR	AL, BL
		XCHG	[DI+2], AL
		ADD     DI, DX
		ADD	SI, 2
		DEC     CH
		JNZ     @@7

@@9:		MOV	AX, [CurCode]
		CMP	AH, 0FFH
		JZ	@@13
		XOR	AH, AH
@@13:		SUB	AL, 2
		JB	@@0
		CMP	AX, 2
		JB	@@0
		MOV	[CurCode], AX
		MOV	DI, [CurOfsDest]
		add	di, 2
		MOV	[CurOfsDest], DI
		MOV	CX, [ColDelta]
		ADD	[CurOfs], CX
		JMP	@@11
@@0:		retn
DoDraw		ENDP

	;
	; SaveScreen16 routine
	;

SaveScreen16	PROC NEAR			; actually FAR
		PUSH    BP
		MOV     BP, RealBytesPerLine
		LES	DI, CursorPtr
		MOV     SI, MouseWhere.X
		SUB	SI, ES:[DI+4]
		SAR     SI, 3
		MOV     CX, ES:[DI]
		MOV     AX, MouseWhere.Y
		SUB	AX, ES:[DI+6]
		JS	SHORT @@4
		MUL     BP
		ADD     SI, AX
		XOR	AX, AX
@@4:		ADD	CX, AX
		MOV     DX, 03CEH		; GC
		MOV	AX, 0105H		; Write Mode 1
		OUT	DX, AX
		MOV     DX, 03C4H		; SC
		MOV     AX, 0F02H		; Map Mask Reg: All Enabled
		OUT     DX, AX
		MOV	DX, CX
		MOV	CX, ES:[DI+2]
		INC	CX
		MOV	_SaveWidth, CX
		LES	DI, DWORD PTR MouseSavePtr
		INC	DI

		ADD	SI, WORD PTR MousePagePtr
		PUSH	DS
		MOV	DS, WORD PTR MousePagePtr.2

		SUB	BP, CX
		MOV	BX, CX
		CLD
@@1:    	MOV	CX, BX
		REP	MOVSB
		ADD     SI, BP
		DEC	DX
		JNZ	@@1
		POP	DS
		MOV     DX, 03CEH		; GC
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		POP     BP
		retf
SaveScreen16	ENDP

	;
	; RestoreScreen16 routine
	;

RestoreScreen16	PROC NEAR			; actually FAR

		MOV	AL, BYTE PTR _DrawCode + 1	; nicht zu zeichnende Bytes
		MOV	CL, BYTE PTR _DrawCode	; Anzahl Quellbytes
		MOV	SI, 1
		MOV	DI, _OfsDest
		CMP	AL, 0FFH		; "rechts" ?
		JZ	SHORT @@1
		INC	CL
		SUB	CL, AL			; korrigieren
		MOV	AH, 0
		ADD	SI, AX
		ADD	DI, AX
@@1:    	OR	CL, CL
		JLE	SHORT @@4
		MOV     DX, 03CEH		; GC
		MOV	AX, 0105H		; Write Mode 1
		OUT	DX, AX
		MOV     DX, 03C4H		; SC
		MOV     AX, 0F02H		; Map Mask Reg: All Enabled
		OUT     DX, AX
		MOV	CH, 0
		MOV	BX, RealBytesPerLine
		SUB	BX, CX			; Dest Delta
		MOV	DX, _SaveWidth
		SUB	DX, CX			; Source Delta
		MOV	CH, BYTE PTR _CountShift + 1

	;	ADD	DI, WORD PTR MousePagePtr
		MOV	ES, WORD PTR MousePagePtr.2
		ADD	SI, MouseSavePOfs
		PUSH	DS
		MOV	DS, MouseSavePSeg
		CLD
		MOV	AX, CX
		MOV	CH, 0
@@2:		MOV	CL, AL
		REP	MOVSB
		ADD	SI, DX
		ADD	DI, BX
		DEC	AH
		JNZ	@@2

		POP	DS
		MOV	DX, 03CEH
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
@@4:		retf
RestoreScreen16	ENDP

	;
	; Saving/restoring the background to/from main memory.
	;

SaveScreen16m	PROC NEAR			; actually FAR
		LOCAL	bpl: WORD, rows: WORD = LocalSize
		enter	LocalSize, 0
		MOV	AX, RealBytesPerLine
		MOV	bpl, AX
		LES	DI, CursorPtr
		MOV     SI, MouseWhere.X
		SUB	SI, es:[DI+4]
		SAR     SI, 3
		MOV     CX, es:[DI]
		MOV     AX, MouseWhere.Y
		SUB	AX, es:[DI+6]
		JS	SHORT @@4
		MUL     bpl
		ADD     SI, AX
		XOR	AX, AX
@@4:		ADD	CX, AX
		MOV	rows, CX
		MOV	CX, es:[DI+2]
		INC	CX
		MOV	_SaveWidth, CX

		LES	DI, MouseSavePtr
		ADD	SI, WORD PTR MousePagePtr
		PUSH	DS
		MOV	DS, WORD PTR MousePagePtr.2

		MOV	BX, CX
		CLD

		MOV     DX, 03CEH		; GC
		MOV     AX, 0005H		; graphics mode
		OUT     DX, AX

@@3:		MOV	AX, 0304H		; read map
@@1:    	OUT	DX, AX

		MOV	CX, BX
		PUSH	SI
		REP	MOVSB
		POP	SI

		DEC	AH
		JNS	@@1

		ADD     SI, bpl
		DEC	rows
		JNZ	@@3

		POP	DS
		MOV     DX, 03CEH		; GC
		MOV	AL, 05H			; Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		leave
		retf
SaveScreen16m	ENDP

RestoreScreen16m PROC NEAR			; actually FAR
		LOCAL	sode: WORD, dede: WORD = LocalSize
		enter	LocalSize, 0
		MOV	AL, BYTE PTR _DrawCode + 1	; nicht zu zeichnende Bytes
		MOV	CL, BYTE PTR _DrawCode	; Anzahl Quellbytes
		MOV	SI, 0
		MOV	DI, _OfsDest
		CMP	AL, 0FFH		; "rechts" ?
		JZ	SHORT @@1
		INC	CL
		SUB	CL, AL			; korrigieren
		MOV	AH, 0
		ADD	SI, AX
		ADD	DI, AX
@@1:    	OR	CL, CL
		JLE	SHORT @@4

		MOV     DX, 03CEH		; GC
		MOV     AX, 0005H		; graphics mode
		OUT     DX, AX
		MOV	AX, 0FF08H		; bit mask
		OUT	DX, AX
		MOV	AX, 0001H		; enable set/reset
		OUT	DX, AX
		MOV	AX, 0003H		; data rotate
		OUT	DX, AX

		MOV	CH, 0
		MOV	BX, RealBytesPerLine	; Dest Delta
		MOV	dede, BX
		MOV	DX, _SaveWidth
		SUB	DX, CX			; Source Delta
		MOV	sode, DX
		MOV	BL, BYTE PTR _CountShift + 1
		MOV	BH, CL

		ADD	DI, WORD PTR MousePagePtr
		MOV	ES, WORD PTR MousePagePtr.2
		ADD	SI, MouseSavePOfs
		PUSH	DS
		MOV	DS, MouseSavePSeg
		CLD

		MOV	DX, 03C4H		; GC
@@3:		MOV	AX, 0802H		; Map mask
@@2:    	OUT	DX, AX
		MOV	CL, BH
		PUSH	DI
		REP	MOVSB
		POP	DI
		ADD	SI, sode
		SHR	AH, 1
		JNZ	@@2
		ADD	DI, dede
		DEC	BL
		JNZ	@@3

		POP	DS
		MOV	DX, 03CEH
		MOV	AL, 05H			; Graphics mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
@@4:            leave
		retf
RestoreScreen16m ENDP

	;
	; Latches handling
	;

SaveLatches16	PROC NEAR			; actually FAR
		LES	DI, MouseSavePtr
		MOV     DX, 03CEH               ; GC
		MOV	AX, 0105H		; Write Mode 1
		OUT	DX, AX
		MOV	ES:[DI], AL
		MOV	AL, 05H			; reset Write Mode
		MOV	AH, BYTE PTR RegArea+GMReg
		OUT	DX, AX
		retf
SaveLatches16	ENDP

RestoreLatches16 PROC NEAR			; actually FAR
		LES	DI, DWORD PTR MouseSavePtr
		MOV	AL, ES:[DI]
		retf
RestoreLatches16 ENDP

	;
	; Dummy routine
	;

Dummy		PROC NEAR
		retf
Dummy		ENDP

	;
	; Service tables
	;

ServiceTbl16	PROC NEAR
		DW	DrawMouse16
		DW	SaveScreen16
		DW	RestoreScreen16
		DW	SaveLatches16
		DW	RestoreLatches16
ServiceTbl16	ENDP

ServiceTbl16s	PROC NEAR
		DW	DrawMouse16
		DW	SaveScreen16m
		DW	RestoreScreen16m
		DW	Dummy
		DW	Dummy
ServiceTbl16s	ENDP

CODE		ENDS

		END
