;Cute Mouse Driver v1.4 source
;Copyright 1997 Nagy Daniel

;The comments are missing somewhere, excuse me. If you have any comments
;or ideas for heavy optimization, please let me know.

;mailto:nagyd@almos.vein.hu
;mailto:heartwork@deathsdoor.com

;Remove the following semicolon before the 'PS2=1' line to assemble the
;driver for PS2 mice

;PS2=1

driverversion	equ	626h		; Microsoft driver version

.model tiny				; it is a COM file
.code
		org	100h

start:		jmp	real_start

;------ FAR pointer storage ------

old10offset	dw	0	; old INT 10h handler address
old10segment	dw	0
oldint33	dd	0	; old INT 33h handler address
newint10	dd	0	; new INT 10h handler address
oldIRQaddr	dd	0	; old IRQ handler address
newIRQaddr	dd	0	; new IRQ handler address
userproc	dw	0,0	; user handler address

mem_type	db	0	; 1 = DOS 5.0+ UMB
				; 2 = XMS UMB
				; 3 = end of conventional memory

;---- driver state begins here -----

int10pointer	dd	0	; pointer to INT 10 handler
Xmovement	dw	0
Ymovement	dw	0
disabled?	db	0	; indicates if driver disabled/enabled

nowdrawing?	db	0	; indicates if cursor drawing is in progress
userproc?	db	0	; indicates if user defined proc is in progress
regionchk?	db	0	; indicates if have to check region
callmask	dw	0	; user call mask
hrangemin	dw	0	; horizontal range min
vrangemin	dw	0	; vertical range min
hrangemax	dw	0	; horizontal range max
vrangemax	dw	0	; vertical range max
Xcalc		dw	0
Ycalc		dw	0
upleftx		dw	0	; upper left X for updating
uplefty		dw	0	; upper left Y fot updating
lowrightx	dw	0	; lower right X for updating
lowrighty	dw	0	; lower right Y for updating
mickeyX		dw	0
mickeyY		dw	0

newbuttstat	dw	0
buttstatus	dw	0	; button status
butt1press	dw	0	; pressed
butt1pc		dw	0	; column of pressing
butt1pr		dw	0	; row of pressing
butt1rel	dw	0	; released
butt1rc		dw	0	; column of releasing
butt1rr		dw	0	; row of releasing
butt3press	dw	0
butt3pc		dw	0
butt3pr		dw	0
butt3rel	dw	0
butt3rc		dw	0
butt3rr		dw	0
butt2press	dw	0
butt2pc		dw	0
butt2pr		dw	0
butt2rel	dw	0
butt2rc		dw	0
butt2rr		dw	0

cursortype	db	0	; hardware/software

column		dw	320
row		dw	64h
column2		dw	320
row2		dw	60h
Xcoord		dw	0		; X coord
Ycoord		dw	0		; Y coord

autores?	db	0		; indicates whether auto/man resolution
handmode	db	0		; 0 - right, 1 - left

Xcoordold	dw	320		; old X coordinate
Ycoordold	dw	60h		; hot Y coordinate
h8mickey	dw	8		; horizontal mickeys per 8 pixel
v8mickey	dw	10h		; vertical mickeys per 9 pixel
mul2indic	db	0
hspotcol	dw	0		; hot spot X in cursor bitmap
hspotrow	dw	0		; hot spot Y in cursor bitmap
treshspeed	dw	2		; double threshold speed
lightpen	db	1		; light pen emulation on/off
startscan	dw	0FFFFh		; cursor start scanline
endscan		dw	7700h		; cursor end scanline
restoreindic	db	1		; indicate to restore screen data (0)
Xcheck		db	0
screenmask	db	48 dup (0)	; user defined screen mask
cursormask	db	48 dup (0)	; user defined cursor mask
grbuf1		dw	72 dup (0)	; screen data
grbuf2		dw	72 dup (0)	; pointer data
activepage	db	0FFh		; active video page
vidmemoffs	dw	0
datav1		db	7 dup (0)
datav1b		db	0,0
mapmask		db	0
datav2		db	5 dup (0)
graphwritemod	db	1
datav3		db	0Fh,0FFh
graphsegindic	db	0		; inicates A000 graphics mode, else 0
VGAindicat	db	0		; is it a VGA card?
EGAport		dw	3D4h		; EGA port address
graphmodeseg	dw	0		; segment of video buffer
ptr2gbuf2	dw	offset grbuf2	; pointer data
ptr2gbuf1	dw	offset grbuf1	; screen data
cursorshown	db	0FFh		; visible? 0 - shown, FF - hidden
rowcheck	db	0

which10toset	db	0		; which INT 10 handler to set
mresolution	dw	0303h		; mouse resolution
IRQintnum	db	0Ch		; INT numer of selected IRQ

IFNDEF PS2
COM_incoming	dw	0		; indicates next incoming serial byte
IO_number	dw	3F8h		; IO port number
PICstate	db	10h		; indicates which bit to clear in PIC
forced		db	0		; Command line force mode?
MSCbuttstate	dw	0		; button state in MSC protocol
logitech?	dw	0		; 0 if no, 1 if yes
extrabyte	db	0		; extra byte of MouseMan protocol
LGbstat		db	0		; temporary for MouseMan
X_LO		db	0		; temporary for MouseMan

ELSE
newPS2data	db	0
ENDIF

mousetype	dw	2		; Mouse type

shape		db	0FFh,9Fh,0FFh,8Fh,0FFh,87h
		db	0FFh,83h,0FFh,81h,0FFh,80h
		db	7Fh,80h, 3Fh,80h,1Fh,80h
		db	0Fh,80h,0FFh,80h,7Fh,88h
		db	7Fh,98h, 3Fh,0FCh,3Fh,0FCh
		db	7Fh,0FEh,0,0,0,20h
		db	0,30h,0,38h,0,3Ch
		db	0,3Eh,0,3Fh,80h,3Fh
		db	0C0h,3Fh,0,3Eh,0,36h
		db	0,23h,0,3,80h,1
		db	80h,1,0,0

butpresstatus	dw	offset butt1press	; button 1 press status
		dw	offset butt2press	; button 2
		dw	offset butt3press	; button 3

butrelstatus	dw	offset butt1rel		; button 1 release status
		dw	offset butt2rel		; button 2
		dw	offset butt3rel		; button 3

crightmsg	db	'Cute Mouse Driver v1.4',0
msversion	db	6,26h

;-------------------------

funcsoffsets	dw	offset resetdriver
		dw	offset showcursor
		dw	offset hidecursor
		dw	offset status
		dw	offset setpos
		dw	offset buttpressdata
		dw	offset buttreldata
		dw	offset hrange
		dw	offset vrange
		dw	offset graphcursor
		dw	offset textcursor
		dw	offset readmcounter
		dw	offset intpar
		dw	offset lightpenon
		dw	offset lightpenoff
		dw	offset micperpixel
		dw	offset defregion
		dw	offset nullfunc		;11 - genius driver only
		dw	offset largeblock
		dw	offset doublespeed
		dw	offset exchangeint
		dw	offset storagereq
		dw	offset savestate
		dw	offset restorestate
		dw	offset nullfunc		;18 - set alternate handler
		dw	offset nullfunc		;19 - return alternate address
		dw	offset setsens
		dw	offset getsens
		dw	offset nullfunc		;1C - InPort mouse only
		dw	offset setpage
		dw	offset getpage
		dw	offset disabledriver
		dw	offset enabledriver
		dw	offset softreset
		dw	offset nullfunc		;22 - set language
		dw	offset nullfunc		;23 - get language
		dw	offset getversion
		dw	offset nullfunc		;25 - get general information
		dw	offset getmaxvirtual

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;				INT 33 handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

handler		proc	far

		test	ah,ah			; mouse func?
		jnz	@notmous		; jump if not
		cmp	al,4dh			; version string query?
		je	@msstr
		cmp	al,6dh			; ms version number?
		je	@msver
		cmp	al,26h			; is it implemented?
		ja	@notmous		; jump if not
		call	handle33
		iret

;----------- Version string

@msstr:		mov	di,offset crightmsg
@finemhand:	push	cs
		pop	es
		iret

;------------ Version number

@msver:		mov	di,offset msversion
		jmp	@finemhand

;------------ Old handler

@notmous:	cmp	cs:word ptr oldint33+2,0	; is there another
		je	end33int			; INT 33 handler?
		pushf
		cli
		call	cs:oldint33		; call it if there is

end33int:	iret

handler		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;   Handle valid request
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

handle33	proc	near

		push	ax
		push	bx
		push	cx
		push	dx
		push	ds
		push	es
		push	di
		push	si
		push	bp
		mov	bp,sp

		push	cs
		pop	ds

		sti
		cld
		cbw
		shl	ax,1
		push	bx
		mov	bx,ax
		mov	ax,funcsoffsets[bx]	; calculate func. offset
		pop	bx
		call	ax			; do called function

IFNDEF PS2
		cmp	disabled?,1
		je	@noen
		call	enableCOMint
ENDIF

@noen:		pop	bp
		pop	si
		pop	di
		pop	es
		pop	ds
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		ret

handle33	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 00                          Reset driver
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

resetdriver	proc

IFDEF PS2
		call	checkPS2
		jc	@pnoaval
ELSE
		call	disableCOMint
		call	chkcom
		jnz	@pnoaval		; jump if port not available
		call	setCOMparams
ENDIF

		call	enabledriver
		call	softreset

IFNDEF PS2
		mov	cursorshown,0FFh
ENDIF

		ret

@pnoaval:	mov	word ptr [bp+10h],0	; return error code
		ret

resetdriver	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 01                         Show mouse cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

showcursor	proc

		mov	regionchk?,0
		mov	ax,maxycoord
		add	ax,1Fh
		mov	lowrighty,ax
		cmp	cursorshown,0
		je	@shown			; jump if already shown
		cmp	cursorshown,0FFh
		jne	@showptr
		call	showpointer
@showptr:	inc	cursorshown

@shown:		ret

showcursor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 02                        Hide mouse cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

hidecursor	proc

		dec	cursorshown
		push	cs
		pop	es
		mov	nowdrawing?,1
		call	restorescreen
		mov	nowdrawing?,0
		ret

hidecursor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 03                  Return position and button status
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

status		proc	

		cli
		mov	ax,column2
		mov	[bp+0Ch],ax
		mov	ax,row2
		mov	[bp+0Ah],ax
		mov	ax,buttstatus
		cmp	handmode,1
		jne	@left
		xor	cx,cx
		mov	bx,ax
		and	ax,4
		shr	bx,1
		rcl	cx,1
		shr	bx,1
		rcl	cx,1
		or	ax,cx
@left:		mov	[bp+0Eh],ax
		sti
		ret

status		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 04                      Position mouse cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setpos		proc

;CX - column
;DX - row

		mov	ax,dx
		mov	si,vrangemin
		mov	di,vrangemax
		call	cmpmax
		push	ax
		mov	ax,cx
		mov	si,hrangemin
		mov	di,hrangemax
		call	cmpmax
		pop	bx

pcurs:		cli
		mov	column,ax
		mov	row,bx
		cwd
		div	colgranu
		mul	colgranu
		mov	column2,ax
		mov	ax,bx
		cwd
		div	rowgranu
		mul	rowgranu
		mov	row2,ax
		cmp	cursorshown,0
		jl	@notshcurs
		mov	cursortype,0
		mov	startscan,77FFh
		mov	endscan,7700h
		call	showpointer

@notshcurs:	sti
		ret

setpos		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 05                      Return button press data
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

buttpressdata	proc

;BX - button number

		and	bx,7
		shl	bx,1
		mov	si,butpresstatus[bx]
		call	retbuttstat
		ret

buttpressdata	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 06                    Return button release data
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

buttreldata	proc

;BX - botton number

		and	bx,7
		shl	bx,1
		mov	si,butrelstatus[bx]
		call	retbuttstat
		ret

buttreldata	endp

;-----------------------------------------

retbuttstat	proc

		cli
		xor	ax,ax
		xchg	[si],ax
		mov	[bp+0Eh],ax
		mov	ax,[si+2]
		mov	[bp+0Ch],ax
		mov	ax,[si+4]
		mov	[bp+0Ah],ax
		mov	ax,buttstatus
		cmp	handmode,1
		jne	@lhand
		xor	cx,cx
		mov	bx,ax
		and	ax,4
		shr	bx,1
		rcl	cx,1
		shr	bx,1
		rcl	cx,1
		or	ax,cx
@lhand:		mov	[bp+10h],ax
		sti
		ret

retbuttstat	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 07                   Define horizontal cursor range
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

hrange		proc

;CX - min column
;DX - max column

		cli
		cmp	dx,cx
		jb	@swminmaxh
		xchg	dx,cx
@swminmaxh:	mov	hrangemin,dx
		and	cx,07fffh
		mov	hrangemax,cx
		mov	cx,column
		mov	dx,row
		call	setpos
		ret

hrange		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 08                    Define vertical cursor range
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

vrange		proc

		cli
		cmp	dx,cx
		jb	@swminmaxv
		xchg	dx,cx

@swminmaxv:	mov	vrangemin,dx
		and	cx,07fffh
		mov	vrangemax,cx
		mov	cx,column
		mov	dx,row
		call	setpos
		ret

vrange		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 09                      Define graphics cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

graphcursor	proc

;BX - hot spot column
;CX - hot spot row
;ES:DX - pointer to bitmap

		mov	hspotrow,cx
		push	dx
		push	es
		mov	ax,bx
		cwd
		idiv	colgranu
		imul	colgranu
		mov	hspotcol,ax
		push	cs
		pop	es
		mov	nowdrawing?,1
		call	restorescreen
		mov	nowdrawing?,0
		pop	ds
		pop	si
		call	setusershape
		push	cs
		pop	ds
		cmp	cursorshown,0
		jne	@gcret
		call	showpointer

@gcret:		ret

graphcursor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 0A                        Define text cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

textcursor	proc

;CX - start scanline/screen mask
;DX - end scanline/cursor mask
;BL - hard cursor/soft cursor

		mov	cursortype,bl
		mov	startscan,cx
		mov	endscan,dx
		cmp	bl,1			; hardware cursor?
		je	@hwcurs

		cmp	cursorshown,0
		jne	@tcret			; jump if hidden
		call	showpointer		; else redisplay

@tcret:		ret

@hwcurs:	mov	ch,cl
		mov	cl,dl
		and	cx,0F0Fh
		mov	ah,1
		int	10h			; set cursor mode in cx
		ret

textcursor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 0B                     Read motion counters
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

readmcounter	proc

		cli
		xor	ax,ax
		xchg	mickeyX,ax
		mov	[bp+0Ch],ax
		xor	ax,ax
		xchg	mickeyY,ax
		mov	[bp+0Ah],ax
		sti
		ret

readmcounter	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 0C                Define interrupt subroutine parameters
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

intpar		proc

;CX - call mask
;ES:DX - FAR routine

		cli
		mov	word ptr userproc+2,es
		mov	userproc,dx
		cmp	handmode,1
		jne	@isright
		mov	dh,cl
		mov	dl,dh
		and	cl,1
		and	dl,6
		and	dh,18h
		shr	dl,1
		shl	dl,3
		shr	dh,3
		shl	dh,1
		or	cl,dl
		or	cl,dh
@isright:	mov	callmask,cx
		sti
		ret

intpar		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 0D                     Light pen emulation On
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

lightpenon	proc

		mov	lightpen,1
		ret

lightpenon	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 0E                    Light pen emulation Off
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

lightpenoff	proc

		mov	lightpen,0FFh
		ret

lightpenoff	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 0F                    Define Mickey/Pixel ratio
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

micperpixel	proc

;CX - number of mickeys per 8 pix horizontally
;DX - number of mickeys per 8 pix vertically

		mov	h8mickey,cx
		mov	v8mickey,dx
		ret

micperpixel	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 10                Define screen region for updating
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

defregion	proc

;CX, DX: upper left
;SI, DI: lower right

		cli
		cmp	si,cx
		jb	@nosw1
		xchg	si,cx
@nosw1:		mov	lowrightx,si
		mov	upleftx,cx
		cmp	di,dx
		jb	@nosw2
		xchg	di,dx
@nosw2:		mov	lowrighty,di
		mov	uplefty,dx
		mov	regionchk?,1
		sti
		cmp	cursorshown,0
		jne	@nosh
		call	showpointer

@nosh:		ret

defregion	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 12                  Set large graphics cursor block
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

largeblock	proc

		cli
		mov	ax,mousetype
		mov	[bp+0Ch],ax
		mov	word ptr [bp+0Ah],241h
		sti
		ret

largeblock	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 13                  Define double-speed threshold
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

doublespeed	proc

;DX - threshspeed

		mov	ax,dx
		cwd
		mov	bx,1Eh
		div	bx
		mov	treshspeed,ax
		ret

doublespeed	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 14                   Exchange interrupt subroutines
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

exchangeint	proc

;CX - call mask
;ES:DX - FAR routine

		cli
		mov	ax,callmask
		mov	[bp+0Ch],ax
		mov	ax,userproc
		mov	[bp+0Ah],ax
		mov	ax,word ptr userproc+2
		mov	[bp+6],ax
		and	cx,7Fh
		mov	callmask,cx
		mov	ax,es
		mov	word ptr userproc+2,ax
		mov	ax,dx
		mov	userproc,ax
		sti
		ret

exchangeint	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 15                Return driver storage requirements
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

storagereq	proc

		mov	word ptr [bp+0Eh],offset butpresstatus-offset int10pointer+1
		ret

storagereq	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 16                       Save driver state
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

savestate	proc

;BX - buffer size
;ES:DX - pointer to buffer

		cld
		push	cx
		mov	di,dx
		mov	si,offset cursorshown
		movsb
		mov	si,offset old10offset
		mov	cx,offset butpresstatus-offset int10pointer

		rep	movsb
		pop	cx
		ret

savestate	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 17                      Restore driver state
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

restorestate	proc

;BX - buffer size
;ES:DX - pointer to saved state

		cld
		push	cx
		push	bx
		push	ax
		mov	bx,ds
		mov	ax,es
		mov	ds,ax
		mov	es,bx
		mov	si,dx
		mov	di,offset cursorshown
		movsb
		mov	di,offset old10offset
		mov	cx,offset butpresstatus-offset int10pointer
		rep	movsb
		pop	ax
		pop	bx
		pop	cx
		ret

restorestate	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 1A                      Set mouse sensitivity
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setsens		proc

;BX - number of mickeys per 8 pix horizontally
;CX - number of mickeys per 8 pix vertically
;DX - threshspeed

		mov	h8mickey,bx
		mov	v8mickey,cx
		mov	ax,dx
		cwd
		mov	bx,1Eh
		div	bx
		mov	treshspeed,ax
		ret

setsens 	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 1B                     Return mouse sensitivity
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

getsens		proc

		cli
		mov	ax,h8mickey
		mov	[bp+0Eh],ax
		mov	ax,v8mickey
		mov	[bp+0Ch],ax
		mov	ax,treshspeed
		mov	bx,1eh
		mul	bx
		mov	[bp+0Ah],ax
		sti
		ret

getsens		endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 1D                   Define display page number
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setpage		proc

;BX - display page number

		and	bx,1Fh
		mov	activepage,bl
		xor	ax,ax
		mov	es,ax
		mov	ax,es:44ch
		mul	bx
		mov	vidmemoffs,ax
		ret

setpage		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 1E                   Return display page number
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

getpage		proc

		mov	bl,activepage
		cmp	bl,0FFh
		jne	@penab
		cli
		xor	ax,ax
		mov	es,ax
		mov	bl,es:462h
@penab:		xor	bh,bh
		mov	[bp+0Eh],bx
		ret

getpage		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 1F                       Disable mouse driver
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

disabledriver	proc

		cmp	disabled?,1
		je	@disabd			; jump if already disabled

IFDEF PS2
		call	disablePS2
ELSE
		call	disableCOMint
ENDIF

		call	setoldIRQh
		call	set10handler
		mov	disabled?,1

@disabd:	mov	ax,word ptr oldint33
		mov	[bp+0Eh],ax
		mov	ax,word ptr oldint33+2
		mov	[bp+06],ax
		ret

disabledriver	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 20                       Enable mouse driver
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

enabledriver	proc

IFDEF PS2
		call	disablePS2
ELSE
		call	disableCOMint
ENDIF
		cmp	disabled?,1
		jne	@enabd

IFNDEF PS2
		call	setCOMparams
ENDIF

		push	ds
		lds	dx,int10pointer
		mov	ax,2510h
		int	21h			; set new INT 10 handler
		pop	ds

@enabd:		call	setnewIRQh
		mov	disabled?,0

IFDEF PS2
		call	enablePS2
ELSE
		call	enableCOMint
ENDIF

		ret

enabledriver	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 21                        Software reset
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

softreset	proc

		mov	word ptr [bp+0Eh],2

IFNDEF PS2
		cmp	mousetype,3		; Mouse Systems mouse?
		jne	@no3but
		mov	word ptr [bp+0Eh],3
ENDIF

@no3but:	mov	word ptr [bp+10h],0FFFFh
		mov	ah,0Fh
		int	10h			; get state, al=mode, bh=page
						; ah=columns on screen
		call	setvidparams

		push	cs
		pop	es
		xor	al,al
		mov	di,offset nowdrawing?	; fill with 0 between these
@fillnext:	cmp	di,offset cursortype	; two adresses
		ja	@filled0
		stosb
		jmp	@fillnext

@filled0:	mov	startscan,77FFh
		mov	endscan,7700h
		mov	h8mickey,8
		mov	v8mickey,16
		mov	treshspeed,2
		push	ax
		mov	ax,maxycoord
		dec	ax
		mov	vrangemax,ax
		mov	ax,maxxcoord
		dec	ax
		cmp	mul2indic,0
		je	@nomul
		shl	ax,1

@nomul:		mov	hrangemax,ax
		pop	ax
		mov	cx,0FFFFh
		mov	bx,cx
		mov	dx,offset shape
		call	graphcursor
		mov	cursorshown,0
		call	hidecursor
		mov	bx,maxycoord
		mov	cx,bx
		add	cx,1Fh
		mov	lowrighty,cx
		mov	ax,maxxcoord
		shr	ax,1
		shr	bx,1
		call	pcurs
		mov	cursorshown,0FFh
		ret

softreset	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 24              Get software version, mouse type and IRQ
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

getversion	proc

		mov	ax,driverversion	; version number
		mov	[bp+0Eh],ax
		mov	ah,byte ptr mousetype

IFNDEF PS2
		cmp	ah,3
		jne	@only2
		dec	ah
@only2:		mov	al,IRQintnum
		sub	al,8
ELSE
		xor	al,al
ENDIF

		mov	[bp+0Ch],ax
		mov	word ptr [bp+0Ah],0
		ret

getversion	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 26                Get maximum virtual coordinates
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

getmaxvirtual	proc

		xor	ah,ah
		mov	al,disabled?
		mov	[bp+0Eh],ax
		mov	ax,maxxcoord
		dec	ax
		mov	[bp+0Ch],ax
		mov	ax,maxycoord
		dec	ax
		mov	[bp+0Ah],ax
		ret

getmaxvirtual	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; 11, 18, 19, 1C, 22, 23, 25  Null function for not implemented calls
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

nullfunc	proc

		ret

nullfunc	endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ END OF INT 33 SERVICES ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ



;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                         Set up INT 10 handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

set10handler	proc

		push	ds
		cli
		cmp	which10toset,1
		jne	@new10set
		lds	dx,dword ptr old10offset
		mov	ax,2510h
		int	21h			; set intrpt vector to old10
		jmp	@exit10set

@new10set:	lds	dx,cs:newint10
		mov	ax,2510h
		int	21h			; set intrpt vector to new10
@exit10set:	sti
		pop	ds
		ret

set10handler	endp

IFNDEF PS2
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;             Set communication parameters (speed, parity, etc.)
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setCOMparams	proc

		cli
		push	dx
		push	si
		mov	si,IO_number
		mov	al,80h
		mov	dx,si
		add	dx,3
		out	dx,al		; port 3FBh, set DLAB on
		jmp	$+2

		mov	al,60h
		mov	dx,si
		out	dx,al		; port 3F8h, speed LO byte
		jmp	$+2

		xor	al,al
		inc	dx
		out	dx,al		; port 3F9h, speed HI byte
		jmp	$+2

		mov	ax,mousetype
		cmp	logitech?,1
		jne	@nologicor
		dec	ax

@nologicor:	add	dx,2
		out	dx,al		; port 3FBh, set comm params
		jmp	$+2		; and DLAB=0

		mov	al,0Bh
		inc	dx
		out	dx,al		; port 3FCh, reset hardware
		jmp	$+2		; (Activate DTR, RTS and output 2)

		mov	al,1
		sub	dx,3
		out	dx,al		; port 3F9h, DR int enable
		jmp	$+2

		add	dx,4
		in	al,dx		; port 3FDh, read LSR thus
		jmp	$+2		; clearing error bits

		mov	dx,si
		in	al,dx		; port 3F8h, flush reveive buffer
		jmp	$+2

		pop	si
		pop	dx
		sti
		ret

setCOMparams	endp

ENDIF

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Set new IRQ handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setnewIRQh	proc

		cli
		push	ds
		mov	al,IRQintnum
		mov	ah,25h
		lds	dx,newIRQaddr
		int	21h			; set intrpt vector al to ds:dx
		pop	ds
		sti
		ret

setnewIRQh	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Restore old IRQ handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setoldIRQh	proc

		cli
		push	ds
		mov	al,IRQintnum
		mov	ah,25h
		lds	dx,oldIRQaddr
		int	21h			; set intrpt vector al to ds:dx
		pop	ds
		sti
		ret

setoldIRQh	endp

IFNDEF PS2
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                      Enable serial interrupt in PIC
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

enableCOMint	proc

		cli
		mov	ah,PICstate
		not	ah
		in	al,21h		; port 21h, int IMR
		jmp	$+2
		and	al,ah
		out	21h,al		; enable serial interrupt
		sti
		ret

enableCOMint	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                     Disable serial interrupt of PIC
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

disableCOMint	proc

		cli
		mov	ah,PICstate
		in	al,21h		; get PIC mask in al
		jmp	$+2
		or	al,ah
		out	21h,al		; disable serial port interrupt
		sti
		ret

disableCOMint	endp

ELSE
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                            Disable PS2
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

disablePS2	proc	near

		cli				; Disable interrupts
		push	bx
		push	dx
		push	es

		mov	ax,0C200h
		mov	bh,0
		int	15h			; set mouse off
		push	bx
		push	es
		mov	ax,0C207h
		xor	bx,bx			; Zero register
		mov	es,bx
		int	15h			; es:bx=ptr to handler
		pop	es
		pop	bx
		pop	es
		pop	dx
		pop	bx
		sti				; Enable interrupts
		ret

disablePS2	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                             EnablePS2
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

enablePS2	proc	near

		cli				; Disable interrupts
		push	ax
		push	bx
		push	dx
		push	es

		push	es
		push	cs
		pop	es
		mov	bx,offset IRQhandler
		mov	ax,0C207h
		int	15h			; es:bx=ptr to handler
		pop	es
		mov	ax,0C200h
		mov	bh,1
		int	15h			; set mouse on
		pop	es
		pop	dx
		pop	bx
		pop	ax
		sti				; Enable interrupts
		ret

enablePS2	endp
ENDIF

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                  Set segment registers equal to CS
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setsegs		proc

		push	cs
		push	cs
		pop	ds
		pop	es
		ret

setsegs		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                    Set up user defined graphics cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setusershape	proc

		push	bx
		push	di
		push	cs
		pop	es			; ES=CS
		mov	bx,0FFFFh
		lea	di,screenmask
		call	copybitmap		; copy screen mask

		xor	bx,bx
		mov	cs:Xcheck,bl
		lea	di,cursormask
		call	copybitmap		; copy cursor mask
		pop	di
		pop	bx
		ret

setusershape	endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;    Copies user defined graphics cursor bitmap
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

copybitmap	proc

;BL - either FF or 00
;SI - pointer to graphics cursor bitmap
;DI - where to copy

		push	cx
		mov	cx,10h

@loccp:		lodsw
		xchg	al,ah
		stosw
		mov	al,bl
		stosb
		loop	@loccp

		pop	cx
		ret

copybitmap	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                        Compare with maximum ranges
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

cmpmax		proc
;SI - minimum
;DI - maximum
;AX - current

		cmp	ax,si
		jl	@toosmall
		cmp	ax,di
		jle	@valueOK
		mov	ax,di
		ret

@toosmall:	mov	ax,si
@valueOK:	ret

cmpmax		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Draw mouse pointer
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

showpointer	proc

		cld
		cli
		mov	nowdrawing?,1		; indicate drawing
		sti
		cmp	rowgranu,1		; text mode?
		jne	@textshp		; jump if yes
		call	drawgraphcurs		; else draw graphics cursor
		jmp	@graphshp

@textshp:	call	drawtextcursor

@graphshp:	cli
		mov	nowdrawing?,0		; drawing stopped
		sti
		ret

showpointer	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                         Draw text mode cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

drawtextcursor	proc

		mov	ax,row2
		mov	bx,column2		; get coordinates
		cmp	cursortype,0
		je	@swcur			; jump if software cursor
		call	drawHWcursor		; else draw hardware text cursor
		jmp	@exitdwcurs		; and exit

@swcur:		call	softtextcurs		; draw software text cursor

@exitdwcurs:	cli
		mov	ax,Xcoord		; update hot spot params
		mov	Xcoordold,ax
		mov	ax,Ycoord
		mov	Ycoordold,ax
		sti
		ret

drawtextcursor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;             Draw hardware text mode cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

drawHWcursor	proc

		call	calcaddress
		shr	di,1
		mov	bx,di
		mov	dx,EGAport
		mov	al,0Fh
		out	dx,al			; al = 0Fh, cursor position lo
		inc	dx
		mov	al,bl
		out	dx,al
		dec	dx
		mov	al,0Eh
		out	dx,al			; al = 0Eh, cursor position hi
		mov	al,bh
		inc	dx
		out	dx,al
		ret

drawHWcursor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;               Draw software text mode cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

softtextcurs	proc

		cli
		mov	Ycoord,ax
		mov	Xcoord,bx
		sti
		call	restorescreen
		mov	ax,Ycoord
		mov	bx,Xcoord
		mov	cx,ax
		mov	dx,bx
		add	cx,pixboxwidth
		add	dx,pixboxheight
		call	checkregion		; out of update region?
		jc	@exitswcurs

		call	calcaddress
		cli
		call	wait_VRT
		mov	bx,es:[di]		; store char under cursor
		sti
		mov	grbuf1,bx
		and	bx,startscan
		xor	bx,endscan
		mov	es:[di],bx		; draw to new position
		mov	restoreindic,0		; we have to reastore later

@exitswcurs:	ret

softtextcurs	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Draw graphics cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

drawgraphcurs	proc

		cli
		mov	ax,row2
		sub	ax,hspotrow
		mov	Ycoord,ax		; Y calculated

		mov	bx,column2
		sub	bx,hspotcol
		cmp	mul2indic,0
		je	@nomul2
		shr	bx,1
@nomul2:	mov	Xcoord,bx		; X calculated

		sti
		cmp	regionchk?,0		; have to check region?
		je	@notout			; jump if not

		mov	cx,ax
		add	cx,10h
		sub	ax,8
		and	bl,0F8h
		mov	dx,bx
		add	dx,18h
		call	checkregion		; out of update region?
		jnc	@notout			; jump if not
		call	restorescreen
		ret

@notout:	call	graphportparams
		mov	ax,Ycoord
		mov	bx,Xcoord
		cmp	ax,Ycoordold
		jne	@moved
		cmp	bx,Xcoordold
		jne	@moved
		cmp	restoreindic,1
		jne	@nomoved

@moved:		mov	cx,Ycoordold
		cmp	cx,maxycoord
		jg	@dontrest
		call	restoreoldscr		; restore old screen content
@dontrest:	call	storeunder		; store bitmap under new pos
@nomoved:	call	trans			; transform
		call	setsegs			; CS=DS=ES
		cli
		mov	ax,Xcoord
		mov	Xcoordold,ax
		mov	si,Ycoord
		mov	Ycoordold,si
		sti
		mov	di,ptr2gbuf2
		call	spritecopy		; draw pointer
		mov	restoreindic,0
		call	restorevidport
		ret

drawgraphcurs	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;              Wait for VRT in text modes
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

wait_VRT	proc

		mov	ax,es
		cmp	ax,0B800h
		jne	@notextmod

		push	ds
		xor	ax,ax
		mov	ds,ax
		mov	dx,ds:463h		; video port
		pop	ds
		add	dx,6

;---- Wait for vertical retrace ----

@vrt1:		in	al,dx
		test	al,1
		jnz	@vrt1

@vrt2:		in	al,dx
		test	al,1
		jz	@vrt2

@notextmod:	ret

wait_VRT	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

restorescreen	proc

		call	graphportparams
		call	restoreoldscr
		call	restorevidport
		ret

restorescreen	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Restore old screen contents
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

restoreoldscr	proc

		cmp	restoreindic,1		; do we have to restore
		je	@norestor		; jump if not
		cld
		mov	restoreindic,1		; clear indicator
		cmp	rowgranu,1		; text mode?
		jne	@textmod		; jump if yes

		mov	di,ptr2gbuf1
		mov	ax,Xcoordold
		mov	si,Ycoordold		; restore graphic mode
		call	spritecopy		;  screen data
		ret

@textmod:	cmp	cursortype,0		; HW/SW cursor?
		jne	@norestor		; exit if hardware

		mov	ax,Ycoordold
		mov	bx,Xcoordold
		call	calcaddress
		mov	bx,grbuf1
		cli
		call	wait_VRT
		mov	es:[di],bx		; restore old text char attrib
		sti
		push	cs
		pop	es
@norestor:	ret

restoreoldscr	endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                        Copy sprite back and forth
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

spritecopy	proc

		call	retvidmem
		xchg	di,si
		mov	dx,Ycoordold
		mov	rowcheck,1
		mov	es,videoseg
		mov	ds,graphmodeseg
		call	copyscrmap
		call	setsegs
		ret

spritecopy	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;           Store bitmap under new pointer pos
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

storeunder	proc

		mov	ax,Xcoord
		mov	si,Ycoord
		call	retvidmem
		mov	di,ptr2gbuf1
		mov	dx,Ycoord
		mov	rowcheck,0
		mov	es,graphmodeseg
		mov	ds,videoseg
		call	copyscrmap
		call	setsegs
		ret

storeunder	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;  Copies pointer or under-pointer sprites back and forth
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

copyscrmap	proc

		cmp	dx,cs:maxycoord
		jge	@maxed
		mov	ax,cs:nextrowoffset
		mov	bx,cs:nextpagoffset
		mov	cx,10h
		add	cx,dx
		cmp	cx,cs:maxycoord
		jl	@nomaxx
		mov	cx,cs:maxycoord

@nomaxx:	sub	cx,dx

@dwrow:		call	drawrow
		cmp	cs:rowcheck,1
		jne	@norowck
		add	di,ax
		cmp	di,bx
		jb	@nosubr
		sub	di,bx
@nosubr:	jmp	@looprow

@norowck:	add	si,ax
		cmp	si,bx
		jb	@looprow
		sub	si,bx
@looprow:	loop	@dwrow

@maxed:		ret

copyscrmap	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                   Draws a row of graphics cursor
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

drawrow		proc

		push	cx
		mov	cx,3
		cmp	byte ptr cs:videomode,13h
		jne	@not13m
		mov	cx,10h

@not13m:	rep	movsb
		pop	cx
		ret

drawrow		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

trans		proc

		cmp	byte ptr videomode,13h
		je	@tvid13
		call	trans2

@tvid13:	mov	si,ptr2gbuf1		; copy saved buffer to
		mov	di,ptr2gbuf2		;  buffer 2 because we will
		push	di			;  transform there
		push	ds
		cmp	byte ptr ds:videomode,13h
		je	@tvid13_2
		mov	cx,30h
		jmp	@notvid13
@tvid13_2:	mov	cx,100h
@notvid13:	mov	es,ds:graphmodeseg
		mov	ds,ds:graphmodeseg
		rep	movsb
		pop	ds
		pop	di

		mov	dx,Ycoord
		mov	si,Xcoord
		cmp	byte ptr cs:videomode,13h
		je	@tvid13_3
		and	si,0FFF8h
@tvid13_3:	xor	bx,bx
		call	setvidpar
		call	transform
		call	resvidpar
		ret

trans		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

setvidpar	proc

		push	dx
		cmp	cs:graphsegindic,0
		je	@nogrv
		mov	dx,3CEh
		mov	ax,5
		cmp	byte ptr cs:videomode,14h
		jae	@ta14h
		mov	ah,graphwritemod
		and	ah,0FEh
		out	dx,ax			; set write mode
		mov	al,3
		out	dx,al			; set data rotate mode
		mov	dx,Ycoord
		jmp	@nogrv

@ta14h:		out	dx,ax			; set graphics mode
		mov	al,8
		out	dx,al			; set data bit mask
@nogrv:		pop	dx
		ret

setvidpar	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

resvidpar	proc

		push	dx
		cmp	cs:graphsegindic,0
		je	@resnogr
		mov	dx,3CFh
		xor	al,al
		out	dx,al
		dec	dx
		mov	al,5
		mov	ah,graphwritemod
		out	dx,al			; select mode
		inc	dx
		mov	al,ah
		out	dx,al			; set write mode

@resnogr:	pop	dx
		ret

resvidpar	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

transform	proc

		mov	cx,10h			; 16 rows

@loopytr:	test	dx,dx
		jl	@noloopdx
		cmp	dx,maxycoord		; exit if out of screen
		jg	@moreymax

		push	bx
		push	cx
		push	di
		push	si
		mov	cx,3
		cmp	byte ptr cs:videomode,13h
		jne	@noloop13
		dec	cx

@nextx13tr:	call	mode13trans
		inc	bx
		loop	@nextx13tr

		jmp	@nextytr

@noloop13:	call	modeno13curs
		inc	bx
		loop	@noloop13

@nextytr:	pop	si
		pop	di
		pop	cx
		pop	bx

@noloopdx:	mov	ax,3
		cmp	byte ptr cs:videomode,13h
		jne	@no13lo
		mov	ax,10h

@no13lo:	add	di,ax
		add	bx,3
		inc	dx
		loop	@loopytr

@moreymax:	ret

transform	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;        Transform the pointer mask to screen content
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

mode13trans	proc

		push	cx
		push	dx
		mov	dh,screenmask[bx]
		mov	dl,cursormask[bx]
		mov	cx,8			; 2*8 bytes per row

@nextrb:	test	si,si
		jl	@maxxskip
		cmp	si,maxxcoord
		jge	@maxxskip
		mov	al,es:[di]
		shl	dh,1
		jc	@pthere
		xor	al,al
@pthere:	shl	dl,1
		jnc	@nopthere
		xor	al,0Fh
@nopthere:	mov	es:[di],al
@maxxskip:	inc	di
		inc	si
		loop	@nextrb

		pop	dx
		pop	cx
		ret

mode13trans	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                 Display cursor in other than mode 13 modes
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

modeno13curs	proc

		push	dx
		test	si,si
		jl	@skipn13x
		cmp	si,maxxcoord
		jge	@skipn13x

		cmp	cs:graphsegindic,0
		jne	@textn13
		mov	al,es:[di]
		and	al,screenmask[bx]
		xor	al,cursormask[bx]
		mov	es:[di],al
		jmp	@skipn13x

@textn13:	mov	dx,3CFh
		cmp	byte ptr cs:videomode,14h
		jb	@b14tr
		mov	al,screenmask[bx]
		out	dx,al
		mov	al,es:[di]
		mov	al,cursormask[bx]
		mov	es:[di],al
		jmp	@skipn13x

@b14tr:		mov	al,8			; data ANDed with latched data
		out	dx,al
		mov	al,es:[di]
		mov	al,screenmask[bx]
		mov	es:[di],al
		mov	al,18h			; data XORed with latched data
		out	dx,al
		mov	al,es:[di]
		mov	al,cursormask[bx]
		mov	es:[di],al

@skipn13x:	inc	di
		add	si,8
		pop	dx
		ret

modeno13curs	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

trans2		proc

		mov	al,byte ptr Xcoord
		and	al,7
		mov	bl,Xcheck
		mov	Xcheck,al
		sub	al,bl
		jz	@noscroll
		jl	@scrleft
		lea	si,cursormask
		call	scrollright
		lea	si,screenmask
		call	scrollright
		ret

@scrleft:	neg	al
		mov	si,offset cursormask
		call	scrolleft
		mov	si,offset screenmask
		call	scrolleft

@noscroll:	ret

trans2		endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

scrollright	proc

		push	di
		mov	bl,al

@scrn:		mov	di,si
		mov	cx,30h

@scrloop:	rcr	byte ptr [di],1
		inc	di
		loop	@scrloop

		jnc	@scrc
		or	byte ptr [si],80h
		jmp	@scrnc

@scrc:		and	byte ptr [si],7Fh
@scrnc:		dec	bl
		jnz	@scrn
		pop	di
		ret

scrollright	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

scrolleft	proc
		push	di
		mov	bl,al
		add	si,30h

@scln:		mov	di,si
		mov	cx,30h

@sclloop:	dec	di
		rcl	byte ptr [di],1
		loop	@sclloop

		mov	di,si
		jnc	@sclc
		or	byte ptr [di-1],1
		jmp	@sclnc

@sclc:		and	byte ptr [di-1],0FEh
@sclnc:		dec	bl
		jnz	@scln
		pop	di
		ret

scrolleft	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

retvidmem	proc

		xor	bx,bx
		xchg	si,ax
		cmp	graphsegindic,0
		jne	@cvidmem
		cmp	byte ptr videomode,13h
		je	@cvidmem
		mov	bx,ax
		cmp	byte ptr videomode,14h
		jg	@m14cvid
		and	bx,1
		sar	ax,1
		jmp	@cvidmem

@m14cvid:	and	bx,3
		sar	ax,1
		sar	ax,1
@cvidmem:	call	calcvidmem
		mov	cl,3
		ror	bx,cl
		add	si,bx
		ret

retvidmem	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

calcvidmem	proc

		mov	cx,numocolumns
		imul	cx
		cmp	byte ptr videomode,13h
		je	@m13calc
		mov	cl,3
		sar	si,cl

@m13calc:	add	si,ax
		cmp	activepage,0FFh
		jne	@pageyes
		push	es
		push	ax
		xor	ax,ax
		mov	es,ax
		mov	ax,es:44eh
		add	si,ax
		pop	ax
		pop	es
		ret

@pageyes:	add	si,vidmemoffs
		ret

calcvidmem	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

calcaddress	proc

		div	byte ptr pixboxwidth
		mov	cx,numocolumns
		shl	cx,1
		mul	cx
		mov	di,ax
		mov	ax,bx
		div	byte ptr pixboxheight
		shl	ax,1
		add	di,ax
		cmp	activepage,0FFh
		jne	@pageno

		push	es
		push	ax
		xor	ax,ax
		mov	es,ax
		mov	ax,es:44eh
		add	di,ax
		pop	ax
		pop	es
		jmp	@caddrok

@pageno:	add	di,vidmemoffs
@caddrok:	mov	es,videoseg
		ret

calcaddress	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                      Check update region
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

checkregion	proc

		dec	cx
		dec	dx
		cmp	ax,uplefty
		jg	@regexit
		cmp	bx,upleftx
		jg	@regexit
		cmp	cx,lowrighty
		jl	@regexit
		cmp	dx,lowrightx
		jl	@regexit
		stc
		ret

@regexit:	clc
		ret

checkregion	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                    Updates graphics card port values
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

graphportparams	proc

		cmp	graphsegindic,0		; A000 graphics segment?
		je	@nogrparam		; jump if not

		push	ax
		push	bx
		push	cx
		push	dx
		push	es
		push	cs
		pop	es

		mov	cx,9
		mov	dx,10h			; reads all graphics controller
		mov	bx,offset datav1	; regs (3CEh) to ES:BX
		mov	ah,0F2h
		int	10h

		mov	bx,2			; read register 2 of sequencer
		mov	dx,8			; (3C4h) - map mask register
		mov	ah,0F0h
		int	10h
		mov	mapmask,bl		; store it

		mov	bx,0F02h		; write 0Fh to 2nd register
		mov	dx,8			; of sequencer (3C4h):
		mov	ah,0F1h			; Enable all maps
		int	10h

		mov	cx,6			; write 6 values from ES:BX
		mov	dx,10h			; to graphics controller
		mov	bx,offset datav2	; regs (3CEh)
		mov	ah,0F3h
		int	10h

		mov	ch,7
		mov	cl,2			; write 7th and 8th regs of
		mov	dx,10h			; 3CEh from ES:BX
		mov	bx,offset datav3	; Enable all maps and color
		mov	ah,0F3h			; don't care
		int	10h

		pop	es
		pop	dx
		pop	cx
		pop	bx
		pop	ax

@nogrparam:	ret

graphportparams	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                     Restore video adapter port values
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

restorevidport	proc

		cmp	graphsegindic,0		; A000 graphics mode?
		je	@noresparam		; jump if not

		push	ax
		push	bx
		push	cx
		push	dx

		mov	bl,2
		mov	dx,8			; restore map mask register
		mov	bh,mapmask
		mov	ah,0F1h
		int	10h

		mov	cx,6
		mov	dx,10h
		mov	bx,offset datav1
		mov	ah,0F3h
		int	10h			; write register range
		mov	ch,7
		mov	cl,2
		mov	dx,10h
		mov	bx,offset datav1b
		mov	ah,0F3h
		int	10h			; write register range
		pop	dx
		pop	cx
		pop	bx
		pop	ax

@noresparam:	ret

restorevidport	endp

;-------------------------------------------------------------

videomode	db	7		; video mode number
videoseg	dw	0B000h		; video mode seg
maxxcoord	dw	640		; max X coordinate
maxycoord	dw	200		; max Y coordinate
nextpagoffset	dw	3FB0h
nextrowoffset	dw	1FFDh		; add this to reach next row
pixboxheight	dw	8
pixboxwidth	dw	8
colgranu	dw	8		; column gran
rowgranu	dw	8		; row gran
numocolumns	dw	80		; number of columns

vmodeparams	db	0
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	16,8,16,8
		dw	40

		db	1
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	16,8,16,8
		dw	40

		db	2
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,8,8
		dw	80

		db	3
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,8,8
		dw	80

		db	4
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,2,1
		dw	80

		db	5
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,2,1
		dw	80

		db	6
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,1,1
		dw	80

		db	7
		dw	0B000h,640,200,3FB0h,1FFDh
		dw	8,8,8,8
		dw	80

		db	8
		dw	0B800h,640,200,7FB0h,1FFDh
		dw	8,8,4,1
		dw	80

		db	9
		dw	0B800h,1280,200,7F60h,1FFDh
		dw	8,8,1,1
		dw	160

		db	0Ah
		dw	0B800h,1280,200,7F60h,1FFDh
		dw	8,8,1,1
		dw	160

		db	0Bh
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,1,1
		dw	80

		db	0Ch
		dw	0B800h,640,200,3FB0h,1FFDh
		dw	8,8,1,1
		dw	80

		db	0Dh
		dw	0A000h,320,200,0,25h
		dw	8,8,2,1
		dw	40

		db	0Eh
		dw	0A000h,640,200,0,4Dh
		dw	8,8,1,1
		dw	80

		db	0Fh
		dw	0A000h,640,350,0,4Dh
		dw	8,14,1,1
		dw	80

		db	10h
		dw	0A000h,640,350,0,4Dh
		dw	8,14,1,1
		dw	80

		db	11h
		dw	0A000h,640,480,0,4Dh
		dw	9,16,1,1
		dw	80

		db	12h
		dw	0A000h,640,480,0,4Dh
		dw	9,16,1,1
		dw	80

		db	13h
		dw	0A000h,320,200,0,130h
		dw	8,8,2,1
		dw	320

		db	14h
		dw	0A000h,640,200,0,13Dh
		dw	8,8,1,1
		dw	320

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;			Set parameters for current video mode
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setvidparams	proc

;AL - current video mode

		push	ax
		push	bx
		push	cx
		push	dx
		push	es
		push	ds
		push	si
		push	di
		cld
		cli
		xchg	bl,al
		push	cs
		pop	ds
		cmp	bl,13h
		jbe	@l13set
		mov	bl,14h		; if bigger than standard, then be 14h

@l13set:	xor	ah,ah
		mov	al,bl			; AL=BL=videomode
		mov	cx,15h
		imul	cx
		mov	si,ax
		lea	si,vmodeparams[si]
		lea	di,videomode		; copy params from table
		push	cs
		pop	es
		rep	movsb

		mov	videomode,bl

		mov	ax,maxycoord		; set ranges for current mode
		dec	ax
		mov	vrangemax,ax
		mov	ax,maxxcoord
		dec	ax
		shl	ax,1
		mov	hrangemax,ax
		mov	mul2indic,0

		mov	ptr2gbuf1,offset grbuf1
		mov	ptr2gbuf2,offset grbuf2
		mov	graphmodeseg,cs
		mov	graphsegindic,0
		cmp	bl,0Dh			; is videmode below 0Dh?
		jb	@otherset		;  jump if yes
		cmp	bl,13h			; is videomode bigger than 13h?
		ja	@otherset		;  jump if yes
		jnz	@d13set

		mov	graphmodeseg,0A000h	; do these if vidmode=13h
		mov	ptr2gbuf1,0FA00h	; first free byte in vidmem
		mov	ptr2gbuf2,0FB80h	; we'll be storing the pointer
		inc	mul2indic		;  shape and the hided screen
		jmp	@otherset		;  contents here to save mem

@d13set:	cmp	bl,0Dh
		jne	@nod13set
		inc	mul2indic		; inc if videomode=0Dh

@nod13set:	call	firstfreevid		; call if 0Ch < videomode < 13h
@otherset:	sti
		pop	di
		pop	si
		pop	ds
		pop	es
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		ret

;-------------

firstfreevid:	mov	graphwritemod,1
		mov	ptr2gbuf1,3E82h		; 0D, 0E
		mov	ptr2gbuf2,3F12h		; 16002
		mov	graphmodeseg,0A000h
		mov	graphsegindic,bl
		cmp	bl,0Eh
		jle	@l11set

		add	ptr2gbuf1,4000h		; 0F, 10h, 11h, 12h
		add	ptr2gbuf2,4000h		; 32386
		cmp	bl,11h
		jl	@l11set

		add	ptr2gbuf1,2000h		; 11h, 12h
		add	ptr2gbuf2,2000h		; 40578

@l11set:	mov	ah,0F0h			; 0Dh - 12h
		mov	bx,5
		mov	dx,10h
		int	10h			; read mode register

		test	bl,2
		jz	@svidex
		mov	graphwritemod,10h

@svidex:	ret

setvidparams	endp

;----------------- Adapter port numbers and commands for RIL -----------------

RD1		dw	0,0
		db	0
RD2		db	0
d121		db	0
		db	24 dup (0)
d125		db	21 dup (0)
d122		db	8 dup (0)
RD3		db	0
RD4		db	0
RD123	db	0
RD124	db	0
RD125	db	0
		db	0,0,0,0
RD126	db	0
d127		db	0
		db	24 dup (0)
d126		db	21 dup (0)
d128		db	8 dup (0)
RD127	db	0
RD128	db	0
RD129	db	0
RD130	db	0


CRTCbase	dw	3D4h			; CRTC
RD132	dw	offset d121
RD133	dw	offset d127
RD134	db	19h
RD135	db	0

		dw	3C4h			; sequencer
		dw	offset RD1
		dw	offset RD125
		db	5
RD136	db	0

		dw	3CEh			; graphics controller
		dw	offset d122
		dw	offset d128
		db	9
RD137	db	0

		dw	3C0h			; VGA attrib controller
		dw	offset d125
		dw	offset d126
VGAmoncol	db	15h
RD139	db	0

		dw	3C2h			; VGA misc output and input
		dw	offset RD2
		dw	offset RD126
		db	1
		db	0

STATbase	dw	3DAh			; VGA status
		dw	offset RD4
		dw	offset RD128
		db	1
		db	0

		dw	3CCh			; VGA misc output read
datapro		dw	offset RD123
		dw	offset RD129
		db	1
		db	0

		dw	3CAh			; VGA feature control
		dw	offset RD124
		dw	offset RD130
		db	1
		db	0


RD142	db	0
RD143	db	0
		dw	0101h
		db	0

RILfuncs	dw	offset RIL_F0		; RIL functions. F0
		dw	offset RIL_F1		; F1
		dw	offset RIL_F2		; F2
		dw	offset RIL_F3		; F3
		dw	offset RIL_F4		; F4
		dw	offset RIL_F5		; F5
		dw	offset RIL_F6		; F6
		dw	offset RIL_F7		; F7
RD152		dw	offset orig10func
		dw	offset orig10func
		dw	offset RIL_FA		; func FA
		dw	offset orig10func
		dw	offset orig10func
		dw	offset orig10func
		dw	offset orig10func
		dw	offset orig10func

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          RIL functions
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

RIL_F0		proc

		mov	si,dx
		mov	si,RD132[si]
		cmp	dx,20h
		jge	@R0
		mov	bl,[bx+si]
		ret

@R0:		mov	bl,[si]
		ret

RIL_F0		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F1		proc

		mov	ax,bx
		mov	si,dx
		cmp	dx,20h
		mov	dx,CRTCbase[si]
		mov	RD135[si],1
		mov	si,RD132[si]
		jge	@R4
		xor	bh,bh
		mov	[bx+si],ah
		cmp	dl,0C0h
		jne	@R1
		push	ax
		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	ax
		mov	dl,0C0h

@R1:		cmp	dl,0C0h
		jne	@R2
		out	dx,al			; port 3C0h, EGA attributes
		push	ax
		mov	al,ah
		out	dx,al			; port 3C0h, EGA attributes
		pop	ax
		jmp	@R3

@R2:		out	dx,ax			; port 3C0h, EGA attributes

@R3:		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		ret

@R4:		mov	RD142,1
		mov	[si],al
		out	dx,al			; port 3DAh, VGA feature contrl
		ret

RIL_F1		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F2		proc

		cmp	dx,20h
		jge	@Rex1
		sti
		cld
		push	di
		mov	di,bx
		mov	si,dx
		mov	si,RD132[si]
		xor	ax,ax
		xchg	al,ch
		add	si,ax
		shr	cx,1
		jnc	@R5
		movsb

@R5:		rep	movsw
		pop	di

@Rex1:		ret

RIL_F2		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F3		proc

		sti
		cld
		push	di
		push	es
		mov	si,bx
		mov	di,dx
		mov	dx,CRTCbase[di]
		mov	RD135[di],1
		mov	di,RD132[di]
		mov	ax,es
		mov	bx,ds
		mov	es,bx
		mov	ds,ax
		xor	ax,ax
		xchg	al,ch
		add	di,ax
		push	cx
		shr	cx,1
		jnc	@R6

		movsb
@R6:		rep	movsw
		mov	ds,bx
		pop	cx
		sub	di,cx
		cmp	dl,0C0h
		jne	@setREGA
		push	ax
		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	ax
		mov	dl,0C0h

@setREGA:	mov	ah,[di]
		cmp	dl,0C0h
		jne	@R7
		out	dx,al			; port 3C0h, EGA attributes
		push	ax
		mov	al,ah
		out	dx,al			; port 3C0h, EGA attributes
		pop	ax
		jmp	@R8

@R7:		out	dx,ax			; port 3C0h, EGA attributes

@R8:		inc	di
		inc	ax
		loop	@setREGA

		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	es
		pop	di
		ret

RIL_F3		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F4		proc

		sti
		cld
		push	di
		mov	di,bx

@RILoo1:	mov	si,es:[di]
		mov	si,RD132[si]
		mov	al,es:[di+2]
		cbw
		add	si,ax
		add	di,3
		movsb
		loop	@RILoo1

		pop	di
		ret

RIL_F4		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F5		proc

		sti
		cld
		push	di
		push	dx
		mov	di,bx

@RILoo2:	mov	si,es:[di]
		mov	dx,CRTCbase[si]
		mov	RD135[si],1
		mov	si,RD132[si]
		mov	ax,es:[di+2]
		cbw
		add	si,ax
		mov	ah,es:[di+3]
		mov	[si],ah
		cmp	dl,0C0h
		jne	@R9
		push	ax
		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	ax
		mov	dl,0C0h

@R9:		cmp	dl,0C0h
		jne	@R10
		out	dx,al			; port 3C0h, EGA attributes
		push	ax
		mov	al,ah
		out	dx,al			; port 3C0h, EGA attributes
		pop	ax
		jmp	@R11

@R10:		out	dx,ax			; port 3C0h, EGA attributes
@R11:		add	di,4
		loop	@RILoo2

		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	dx
		pop	di
		ret

RIL_F5		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F6		proc

		sti
		cld
		push	bx
		push	cx
		push	dx
		push	es
		push	di
		mov	ax,ds
		mov	es,ax
		lea	bx,CRTCbase
		mov	cx,cx
@R12:		cmp	byte ptr [bx+7],0
		je	@R18
		mov	byte ptr [bx+7],0
		mov	cl,[bx+6]
		mov	si,[bx+4]
		mov	di,[bx+2]
		mov	dx,[bx]
		mov	dx,cx
		shr	cx,1
		jnc	@R13
		movsb
@R13:		rep	movsw
		mov	cx,dx
		sub	si,dx
		mov	dx,[bx]
		mov	al,ch
		cmp	dl,0C0h
		jne	@RILoo3
		push	ax
		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	ax
		mov	dl,0C0h

@RILoo3:	mov	ah,[si]
		cmp	dl,0C4h
		jne	@R14
		cmp	al,1
		je	@R17
@R14:		cmp	dl,0CEh
		jne	@R15
		cmp	al,6
		je	@R17
@R15:		cmp	dl,0C0h
		jne	@R16
		out	dx,al			; port 3C0h, EGA attributes
		push	ax
		mov	al,ah
		out	dx,al			; port 3C0h, EGA attributes
		pop	ax
		jmp	@R17
@R16:		out	dx,ax			; port 3C0h, EGA attributes
@R17:		inc	si
		inc	ax
		loop	@RILoo3

@R18:		add	bx,8
		cmp	bx,offset datapro+1
		jl	@R12
		cmp	RD142,0
		je	@R19
		mov	RD142,0
		mov	dx,[bx+8]
		mov	al,RD128
		mov	RD4,al
		out	dx,al			; port 3CEh, EGA graphic index
						;  al = 0, set/reset bit
		mov	dl,0C2h
		mov	al,RD126
		mov	RD2,al
		out	dx,al			; port 3C2h, EGA misl out reg
		mov	al,20h
		mov	dx,3C0h
		out	dx,al			; port 3C0h, EGA attributes
		cmp	VGAindicat,1
		je	@R19
		mov	dl,0CCh
		mov	al,RD129
		mov	RD123,al
		out	dx,al			; port 3CCh, EGA graphics 1 pos
		mov	dl,0CAh
		mov	al,RD130
		mov	RD124,al
		out	dx,al			; port 3CAh, EGA graphics 2 pos
@R19:		mov	dl,byte ptr STATbase
		in	al,dx			; port 3DAh, CGA/EGA vid status
		pop	di
		pop	es
		pop	dx
		pop	cx
		pop	bx
		ret

RIL_F6		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_F7		proc

		sti
		push	cx
		push	di
		mov	si,bx
		mov	di,dx
		xor	ch,ch
		mov	cl,RD134[di]
		mov	RD135[di],1
		cmp	cl,1
		jne	@R20
		mov	RD142,1
@R20:		mov	di,RD133[di]

@RILoo4:	mov	ah,es:[si]
		mov	[di],ah
		inc	di
		inc	si
		loop	@RILoo4

		pop	di
		pop	cx
		ret

RIL_F7		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

RIL_FA		proc

		push	ds
		pop	es
		mov	bx,offset RD152
		ret

RIL_FA		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;        Called if not a valid RIL function requested (ah=Fx, INT 10h)
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

orig10func	proc

		push	bp
		mov	bp,sp
		mov	ax,[bp+8]
		mov	ds,ax
		mov	si,[bp+6]
		mov	ax,[bp+4]
		pop	bp
		pushf
		call	dword ptr cs:old10offset
		push	bp
		mov	bp,sp
		mov	[bp+4],ax
		mov	[bp+6],si
		mov	ax,dx
		mov	[bp+8],ax
		pop	bp
		ret

orig10func	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           INT 10 handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

int10handler	proc

		cli
		cmp	ah,4			; light pen func?
		jne	@nolpen			; jump if not
		cmp	cs:lightpen,1
		je	@lightpen

@nolpen:	test	ah,ah			; set video mode?
		jz	setmodreq		; jump if yes

		cmp	ah,0F0h			; RIL func requested?
		jae	RILreq			; jump if yes
		jmp	dword ptr cs:old10offset ; else call original habdler

;------------- RIL

RILreq:		cmp	ah,0FBh
		jae	@exitRIL
		push	ax
		push	ds
		push	si
		push	di
		push	cs
		pop	ds
		mov	al,ah
		and	ax,0Fh
		shl	ax,1
		mov	si,ax
		call	word ptr RILfuncs[si]
		pop	di
		pop	si
		pop	ds
		pop	ax
@exitRIL:	iret

;------------ Lightpen

@lightpen:	call	emulightpen
		iret

;------------ Set video mode

setmodreq:	push	ax
		mov	cs:cursorshown,0
		mov	ax,2
		int	33h			; mouse driver, hide cursor
		pop	ax

		call	setvidparams

		push	ax
		pushf
		call	dword ptr cs:old10offset
		pop	ax

		mov	cs:RD143,al
		call	monoorcolor		; set up proper color mode

		iret

int10handler	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                             Emulate lightpen
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

emulightpen	proc

		cmp	cs:buttstatus,0
		jne	@lightbutt
		xor	ah,ah
		jmp	@lightbutt

@lightbutt:	sti
		mov	ax,cs:row2
		cmp	cs:videomode,0Fh
		jb	@lpenbf
		mov	cx,ax
		jmp	@lpenaf

@lpenbf:	mov	ch,al
@lpenaf:	div	cs:pixboxwidth
		mov	dh,al
		mov	ax,cs:column2
		mov	bx,ax
		cwd
		div	cs:colgranu
		xchg	bx,ax
		div	cs:pixboxheight
		mov	dl,al
		mov	ah,1
		ret

emulightpen	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;            Determines and sets up mono or color monitor operation
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

monoorcolor	proc

		push	ds
		xor	ax,ax
		mov	ds,ax
		mov	al,ds:410h		; get equipment byte
		and	al,30h			; get initial video mode
		test	byte ptr ds:487h,2	; color or mono monitor?
		jz	@cmon			; jump if color
		cmp	al,30h			; initial vmode is 80x25 mono?
		jne	@80mon			; jump if not

		mov	ah,cs:RD143		; setup mono operation
		and	ah,7Fh
		mov	byte ptr cs:CRTCbase,0B4h
		mov	byte ptr cs:STATbase,0BAh
		cmp	ah,0Fh
		je	@skipcol
		mov	ah,7
		jmp	@skipcol

@cmon:		cmp	al,30h			; initial vmode is 80x25 mono?
		je	@80mon			; jump if yes

		mov	ah,cs:RD143		; setup color operation
		and	ah,7Fh
		mov	cs:byte ptr CRTCbase,0D4h
		mov	cs:byte ptr STATbase,0DAh

@skipcol:	call	displayports		; setup display port funcs
@80mon:		pop	ds
		ret

monoorcolor	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;     Determine display adapter and set up ports
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

displayports	proc

;AH - current videomode

		push	cx
		push	di
		push	si
		push	es
		pushf
		cld
		cli
		xor	cx,cx
		mov	ds,cx
		les	si,dword ptr ds:4a8h
		les	si,dword ptr es:[si]
		test	byte ptr ds:487h,60h
		jz	@noRAM			; jump if no RAM on adapter

		cmp	ah,0Fh			; is videomode 640x350 mono?
		jne	@nogmono

		add	si,440h
		jmp	@disdet

@nogmono:	cmp	ah,10h			; is videomode 640x350x16?
		jne	@noRAM

		add	si,480h
		jmp	@disdet

@noRAM:		cmp	ah,3			; is videomode 80x25x16?
		ja	@noMDAEGA

		mov	al,ds:488h		; get display combination
		and	al,0Fh
		cmp	al,3			; MDA+EGA?
		je	@MDAEGA
		cmp	al,9			; EGA+MDA?
		je	@MDAEGA
		jmp	@noMDAEGA

@MDAEGA:	add	si,4c0h

@noMDAEGA:	cmp	ah,11h			; is videomode 640x480 mono?
		jl	@noVmono
		add	ah,9
@noVmono:	xor	al,al
		shr	ax,1
		shr	ax,1
		add	si,ax

@disdet:	push	es
		pop	ds
		push	cs
		pop	es
		lea	di,RD1
		mov	al,3
		stosb
		add	si,5
		mov	cx,3Ch
		shr	cx,1
		rep	movsw
		mov	cx,3Ch
		sub	si,cx
		lea	di,RD125
		mov	al,3
		stosb
		shr	cx,1
		rep	movsw
		push	cs
		pop	ds
		std
		lea	di,RD3
		mov	cl,9
		mov	si,di
		dec	si
		rep	movsb
		lea	di,RD127
		mov	cl,9
		mov	si,di
		dec	si
		rep	movsb
		cmp	cs:VGAindicat,1
		jne	@nommon
		mov	VGAmoncol,14h

@nommon:	mov	cx,0100h
		mov	RD123,cl
		mov	RD129,cl
		mov	RD124,ch
		mov	RD130,ch
		mov	RD142,cl
		mov	RD136,cl
		mov	RD135,cl
		mov	RD139,cl
		mov	RD137,cl
		popf
		pop	es
		pop	si
		pop	di
		pop	cx
		sti
		ret

displayports	endp

IFNDEF PS2
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                       Check if COM port available
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

chkcom		proc

		mov	si,IO_number
		xor	al,al
		mov	dx,si
		add	dx,3
		out	dx,al		; port 3FBh, reset communication params
		jmp	$+2

		sub	dx,2
		in	al,dx		; port 3F9h, get int enable register
		and	al,0F0h
		mov	bl,al		; store reserved bits

		add	dx,3
		in	al,dx		; port 3FCh, get modem control reg
		and	al,0E0h		; get reserved bits
		or	al,bl		; AL must be 0 if port exists
		ret

chkcom		endp

ELSE
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                         Check for PS/2
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

checkPS2	proc

		cli
		mov	ax,0C205h
		mov	bh,3
		int	15h			; initialize mouse, bh=datasize
		jc	@noPSdet
		cmp	ah,0
		jne	@noPSdet		; Jump if not equal
		mov	ax,0C201h
		int	15h			; reset mouse, returns bh=ID
		jc	@noPSdet
		cmp	ah,0
		jne	@noPSdet
		mov	cx,2

@try2:		push	es
		push	cs
		pop	es
		mov	bx,offset IRQhandler
		mov	ax,0C207h
		int	15h			; mouse, es:bx=ptr to handler
		pop	es
		jnc	@PSokyet
		cmp	ah,4
		jne	@noPSdet
		dec	cx
		jnz	@try2
		jmp	@noPSdet

@PSokyet:	mov	bh,3
		mov	ax,0C203h
		int	15h			; set mouse resolution bh
		jc	@noPSdet
		cmp	ah,0
		jne	@noPSdet
		mov	ax,0C200h
		mov	bh,1
		int	15h			; set mouse on
		jc	@noPSdet
		cmp	ah,0
		jne	@noPSdet
		xor	dl,dl
		xor	bx,bx
		mov	ax,0C206h
		int	15h			; mouse,bh=0 status,1-2=scaling
		jc	@noPSdet
		cmp	ah,0
		jne	@noPSdet
		test	bl,20h
		jz	@noPSdet
		or	dl,dl
		jz	@noPSdet
		mov	mousetype,4
		clc
		sti
		ret

@noPSdet:	stc
		sti
		ret

checkPS2	endp
ENDIF

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                  Update button status regs to new values
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

updatebuttstat	proc

		mov	cx,buttstatus
		mov	di,row2
		mov	si,column2
		mov	newbuttstat,0
		xor	cl,al
		mov	byte ptr buttstatus,al

		test	cl,1			; 1 pressed?
		jz	@chk2press		; jump if not
		test	al,1			; 1 released?
		jz	@rel1			; jump if yes

		or	newbuttstat,2		; indicate that 1 is pressed
		mov	butt1pc,si
		mov	butt1pr,di
		inc	butt1press
		jmp	@chk2press

@rel1:		or	newbuttstat,4		; indicate that 1 is released
		mov	butt1rc,si
		mov	butt1rr,di
		inc	butt1rel

@chk2press:	test	cl,2			; 2 pressed?
		jz	@chk3press		; jump if not
		test	al,2			; 2 released?
		jz	@rel2			; jump if yes

		or	newbuttstat,8		; indicate that 2 is pressed
		mov	butt2pr,di
		mov	butt2pc,si
		inc	butt2press
		jmp	@chk3press

@rel2:		or	newbuttstat,10h		; indicate that 2 is released
		mov	butt2rc,si
		mov	butt2rr,di
		inc	butt2rel

IFNDEF PS2
		cmp	mousetype,3		; 3 button mouse?
		jne	@nomorebutt		; jump if not
ELSE
		ret
ENDIF

@chk3press:	test	cl,4			; 3 pressed?
		jz	@nomorebutt		; quit if not
		test	al,4			; 3 released?
		jz	@rel3			; jump if yes

		or	newbuttstat,20h		; indicate that 3 is pressed
		mov	butt3pc,si
		mov	butt3pr,di
		inc	butt3press
		ret

@rel3:		or	newbuttstat,40h		; indicate that 3 is released
		mov	butt3rc,si
		mov	butt3rr,di
		inc	butt3rel

@nomorebutt:	ret

updatebuttstat	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                             IRQ handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ


IRQhandler	proc	far

IFNDEF PS2
		cli
		push	bp
		push	ax
		push	bx
		push	cx
		push	dx
		push	ds
		push	es
		push	di
		push	si
		cld
		mov	ax,cs
		mov	ds,ax
		mov	es,ax

		mov	dx,cs:IO_number
		add	dx,5
		in	al,dx			; 3FDh, check for overrun
		sub	dx,5
		test	al,2
		jz	@nooverrun		; jump if no overrun occured

		in	al,dx			; else flush receive buffer,
		mov	COM_incoming,0		;  zero counter,
		jmp	@exitIRQh		;  and exit

@nooverrun:	test	al,1			; check if data ready
		jnz	@dataready		; jump if yes
		in	al,dx			; else flush receive buffer,
		jmp	@exitIRQh		;  and exit

@dataready:	in	al,dx			; get that bastard
		cmp	cs:mousetype,2		; Microsoft mouse?
		je	@MSproc			; process that way if yes

		cmp	cs:logitech?,1		; Logitech?
		je	@proclogi		; process that way

		call	msystemsproc		; else treat as MSM mode
		jmp	@exitIRQh

@MSproc:	call	microsoftproc
		jmp	@exitIRQh

@proclogi:	call	logiproc

@exitIRQh:	mov	al,20h
		out	20h,al			; port 20h,  end of interrupt
		pop	si
		pop	di
		pop	es
		pop	ds
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	bp
		sti
		iret
ELSE
		push	bp		; this is for PS2
		mov	bp,sp
		push	ax
		push	bx
		push	cx
		push	dx
		push	ds
		push	es
		push	di
		push	si
		cld
		call	setsegs
		mov	ax,[bp+0Ch]
		test	ah,ah
		jnz	@invPS2data
		and	al,3
		call	updatebuttstat
		mov	ax,[bp+0Ch]
		mov	bx,[bp+0Ah]
		mov	cx,[bp+8]
		test	al,10h
		jz	@PSxneg
		mov	bh,0FFh

@PSxneg:	test	cx,cx
		jz	@noymov
		neg	cl
		test	al,20h
		jnz	@noymov
		mov	ch,0FFh

@noymov:	add	Ymovement,cx
		add	Xmovement,bx
		mov	newPS2data,1

@invPS2data: 	pop	si
		pop	di
		pop	es
		pop	ds
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	bp
		retf
ENDIF

IRQhandler	endp

IFNDEF PS2
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                   Process mouse bytes the Microsoft way
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

microsoftproc	proc

		cbw
		cmp	COM_incoming,0		; first byte?
		jne	@MSsecond		; jump if not

		cmp	al,40h			; synchro check
		jb	@nosync1		; jump if out of synchro

		xor	cx,cx
		mov	Xmovement,cx
		mov	Ymovement,cx
		shr	al,1			; bit 0 - X increment HI
		rcr	byte ptr Xmovement,1
		shr	al,1			; bit 1 - X increment HI
		rcr	byte ptr Xmovement,1
		shr	al,1			; bit 2 - Y increment HI
		rcr	byte ptr Ymovement,1
		shr	al,1			; bit 3 - Y increment HI
		rcr	byte ptr Ymovement,1
		and	al,3
		sar	al,1			; bit 4 - right button?
		jnc	@MSrrel			; jump if not pressed
		or	al,2			; set bit 1 if pressed

@MSrrel:	call	updatebuttstat
		mov	COM_incoming,1		; request second byte
		ret

@MSsecond:	cmp	COM_incoming,1		; second byte?
		jne	@MSthird		; jump if not
		mov	COM_incoming,2		; request third byte
		and	al,3Fh
		or	byte ptr Xmovement,al	; set X increment LO
		ret

@MSthird:	cmp	COM_incoming,2		; third byte?
		jne	@nosync1		; jump if not
		mov	COM_incoming,0		; request new triad
		and	al,3Fh
		or	al,byte ptr Ymovement	; set Y increment LO

		cbw
		mov	cx,ax
		mov	al,byte ptr Xmovement
		cbw
		mov	bx,ax
		call	movepointer

		ret

@nosync1:	mov	COM_incoming,0
		ret

microsoftproc	endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                   Process mouse bytes the Logitech way
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

logiproc	proc

		mov	cx,COM_incoming		; CL = which byte is it
		test	al,40h			; first?
		jz	@3f47			; jump if not
		test	cx,cx			; CX = 0?
		jz	@3f47			; jump if yes
		cmp	cx,3
		jz	@3f35  			; jump if CX = 3
		xor	cx,cx
		mov	COM_incoming,cx		; request new triad
		jmp	@3f54

@3f35:		xor	cx,cx			; request new 3/4
		mov	COM_incoming,cx
		test	byte ptr extrabyte,4	; middlepressed?
		jz	@3f54			; jump if yes
		and	byte ptr extrabyte,0FBh
		jmp	@3f54

@3f47:		test	al,40h			; first?
		jnz	@3f54			; jump if yes
		test	cx,cx			; first?
		jnz	@3f54			; jump if not

@endLGproc:	ret

@3f54:		test	cx,cx			; first?
		jnz	@3f5e			; jump if not
		mov	LGbstat,al		; store it
		jmp	@3f67

@3f5e:		cmp	cx,1			; second?
		jnz	@3f67			; jump if not
		mov	X_LO,al 	   	; store it
@3f67:		inc	COM_incoming		; req next byte
		cmp	CX,2			; third?
		jb	@endLGproc		; jump if below
		ja	@LG4th			; jump if fourth

		mov	bl,X_LO
		shl	bl,2
		mov	bh,LGbstat
		shr	bx,2
		mov	dl,bl			; DL = Xmovement

		mov	bl,al
		shl	bl,2
		shr	bx,2
		mov	dh,bl			; DH = Ymovement

		ror	bx,1
		ror	bh,1
		shl	bl,1
		rcl	bh,2
		and	bh,3
		mov	bl,bh			; BL = Left/Right status

		mov	bh,extrabyte
		test	bh,4
		jz	@3faa
		or	bl,4
@3faa:		mov	extrabyte,bl		; BL = Button status
		mov	al,dl
		cbw
		mov	Xmovement,ax
		mov	al,dh
		cbw
		mov	Ymovement,ax
		jmp	@3fed

@LG4th:		mov	COM_incoming,0		; req next 3/4
		mov	bl,extrabyte
		and	bl,4
		mov	cl,3
		and	al,20h
		shr	al,cl
		xor	bl,al
		jnz	@3fd9
		jmp	@endLGproc

@3fd9:		xor	bl,extrabyte
		mov	extrabyte,bl
		xor	bx,bx
		mov	Ymovement,bx
		mov	Xmovement,bx

@3fed:		mov	al,extrabyte
		call	updatebuttstat
		mov	cx,Ymovement
		mov	bx,Xmovement
		call	movepointer
		ret

logiproc	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                  Process mouse bytes the Mouse Systems way
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

MSMoffsets	dw	offset MSM1		; funcs for each 5 msm bytes
		dw	offset MSM24
		dw	offset MSM3
		dw	offset MSM24
		dw	offset MSM5

msystemsproc	proc
		cbw
		mov	si,COM_incoming
		shl	si,1
		jmp	word ptr MSMoffsets[si]

;ÄÄÄÄÄÄÄ 1st MSM byte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

MSM1:		push	ax
		and	al,0F8h
		cmp	al,80h			; synchro check
		jne	@nosync2		; jump if out of synchron
		pop	ax

		not	ax
		and	ax,7
		mov	COM_incoming,1		; request next byte
		mov	MSCbuttstate,ax		; save button state
		xor	ax,ax
		mov	Xmovement,ax
		mov	Ymovement,ax		; clear movement regs
		ret

@nosync2:	xor	ax,ax
		mov	COM_incoming,ax		; restart receiving
		mov	Xmovement,ax
		mov	Ymovement,ax		; clear movement regs
		pop	ax
		ret

;ÄÄÄÄÄ 2nd and 4th MSM bytes ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

MSM24:		add	Xmovement,ax
		inc	COM_incoming
		ret

;ÄÄÄÄÄ 3rd MSM byte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

MSM3:		mov	Ymovement,ax
		inc	COM_incoming
		ret

;ÄÄÄÄÄ 5th MSM byte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

MSM5:		add	Ymovement,ax
		mov	COM_incoming,0

;--- process new info

		mov	ax,MSCbuttstate
		mov	cl,0Eh
		shl	ax,cl
		rcl	ax,1
		mov	cl,3
		rcl	ah,cl
		or	al,ah
		call	updatebuttstat
		mov	bx,Xmovement
		mov	cx,Ymovement
		neg	cx
		call	movepointer

		ret

msystemsproc	endp

ELSE

handleIRQ	proc

		cli
		pushf
		call	cs:oldIRQaddr
		cmp	cs:newPS2data,0
		je	@noPSdata
		push	bp
		push	ax
		push	bx
		push	cx
		push	dx
		push	ds
		push	es
		push	di
		push	si
		cld
		call	setsegs
		mov	newPS2data,0
		mov	cx,Ymovement
		mov	bx,Xmovement
		call	movepointer
		xor	ax,ax
		mov	Ymovement,ax
		mov	Xmovement,ax
		pop	si
		pop	di
		pop	es
		pop	ds
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	bp

@noPSdata:	sti			; enable interrupts
		iret			; interrupt return

		endp
ENDIF

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Move pointer to position
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

movepointer	proc

;BX - X movement
;CX - Y movement

		mov	ax,cx
		or	ax,bx		; was there any movement?
		jnz	@itsmoved	; jump if yes
		jmp	@buttonly

;---- calculate X mickey ----

@itsmoved:	mov	ax,bx
		cmp	byte ptr autores?,1
		jne	@noautor
		sar	ax,2
		push	ax
		and	ax,0Fh
		cmp	ax,0Ah
		jle	@leax
		mov	ax,0Ah

@leax:		mov	ah,al
		mov	mresolution,ax
		pop	ax

@noautor:	xor	bx,bx
		call	resolute
		add	mickeyX,ax

;---- calculate Y mickey ----

		push	ax
		mov	ax,cx
		cmp	byte ptr autores?,1
		jne	@noautor2
		sar	ax,2
		push	ax
		and	ax,0Fh
		cmp	ax,0Ah
		jle	@leax2
		mov	al,0Ah

@leax2:		mov	ah,al
		mov	mresolution,ax
		pop	ax

@noautor2:	mov	bx,1
		call	resolute
		add	mickeyY,ax

		mov	cx,ax		; CX - Y mickey movement
		pop	bx		; BX - X mickey movement

;---- calculate X movement in pixels ----

		test	bx,bx		; is X movement 0?
		jz	@xmov0		;  jump if yes
		shl	bx,3
		mov	ax,Xcalc
		add	ax,bx
		cwd
		idiv	h8mickey
		add	ax,column
		mov	Xcalc,dx
		mov	si,hrangemin
		sub	si,10h
		mov	di,hrangemax
		add	di,10h
		call	cmpmax
		mov	column,ax
		cmp	ax,hrangemin
		jl	@xsmall
		cmp	ax,hrangemax
		jle	@xgood
		mov	ax,hrangemax
		jmp	@xgood

@xsmall:	mov	ax,hrangemin

@xgood:		cwd
		div	colgranu
		mul	colgranu
		mov	column2,ax		; the new column is ready
		sub	ax,Xcoordold
		mov	bx,ax			; BX - hot spot column

;---- calculate Y movement in pixels ----

@xmov0:		test	cx,cx			; is Y movement 0?
		jz	@ymov0			; jump if yes
		shl	cx,3
		mov	ax,Ycalc
		add	ax,cx
		cwd
		idiv	v8mickey
		add	ax,row
		mov	Ycalc,dx
		mov	si,vrangemin
		sub	si,10h
		mov	di,vrangemax
		add	di,10h
		call	cmpmax
		mov	row,ax
		cmp	ax,vrangemin
		jl	@ysmall
		cmp	ax,vrangemax
		jle	@ygood
		mov	ax,vrangemax
		jmp	@ygood

@ysmall:	mov	ax,vrangemin

@ygood:		cwd
		idiv	rowgranu
		imul	rowgranu
		mov	row2,ax			; the new row is ready
		sub	ax,Ycoordold
		mov	cx,ax			; CX - hot spot row

@ymov0:		or	cx,bx			; if both are 0
		jz	@buttonly		; then no movement -> jump
		or	newbuttstat,1		; indicate movement

@buttonly:	mov	ax,newbuttstat
		cmp	userproc?,0		; user proc running?
		jne	@exitmove		;  exit if yes
		call	calluserproc		; call user proc if available
		test	al,1			; was there movement?
		jz	@exitmove		;  exit if not
		mov	al,nowdrawing?
		or	al,cursorshown		; is drawing in progress?
		jnz	@exitmove		;  exit if yes
		sti
		call	showpointer		; else draw pointer
		cli

@exitmove:	ret

movepointer	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Use selected resolution
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

resolute	proc

;AX - mouse movement

		mov	bl,byte ptr [mresolution+bx]
		cmp	bx,1		; is resolution 1 or 0?
		jle	@res01		;   exit if yes

		cmp	ax,3		; was movement smaller than +3?
		jb	@res01		;   exit if yes
		cmp	ax,-3		; was movement larger than -3?
		ja	@res01		;   exit if yes

		cmp	ax,8		; was movement between +3 and +8?
		jb	@resother	;   jump if yes
		cmp	ax,-8		; was movement between -3 and -8?
		ja	@resother	;   jump if yes

		cwd
		imul	bx		; else multiply it with resolution
;		shr	ax,1		; divide by 2
		ret			; and exit

@resother:	shl	ax,1		; small movement -> multiply with 2

@res01:		ret

resolute	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                       Call User Defined Handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

calluserproc	proc

		mov	userproc?,1
		push	ax
		and	ax,callmask		; is there a user call mask?
		jz	@nocmask		; exit if not

IFNDEF PS2
		push	ax
		mov	al,20h
		out	20h,al			; port 20h, end of interrupt
		pop	ax
ENDIF

		mov	si,mickeyX
		mov	di,mickeyY
		mov	bx,buttstatus
		mov	cx,column2
		mov	dx,row2
		sti
		call	dword ptr userproc
		cli
		call	setsegs
@nocmask:	pop	ax
		mov	userproc?,0
		ret

calluserproc	endp


;==========================================================================

;------------------------ Below is not resident --------------------------

IRQ_number	db	0		; mouse IRQ
indicator	db	0		; 1 - show help, 2 - unload driver

IFNDEF PS2
cutestring	db	'Cute Mouse Driver v1.4',0dh,0ah
		db	'Copyright (C) Nagy Daniel. All Rights Reserved',0dh,0ah
		db	'Type ctmouse /h for help',0dh,0ah,'$'
MSMStr		db	'Driver Mode: Mouse Systems', 0Dh, 0Ah, '$'
MSStr		db	'Driver Mode: Microsoft', 0Dh, 0Ah, '$'
datalogi	db	'Driver Mode: Logitech MouseMan',0dh,0ah,'$'
ELSE
cutestring	db	'Cute Mouse Driver v1.4 for PS/2 mice',0dh,0ah
		db	'Copyright (C) Nagy Daniel. All Rights Reserved',0dh,0ah
		db	'Type ctmousep /h for help',0dh,0ah,'$'
drivmod		db	'Driver Mode: PS/2',0dh,0ah,'$'
ENDIF

relStr		db	'Current Mouse Driver has been released from '
		db	'memory', 0Dh,0Ah, '$'
mnsStr		db	'Mouse driver is not installed!',0Dh,0Ah, '$'

IFNDEF PS2
ncfStr		db	'Error: Cannot find COM port',0Dh, 0Ah, '$'
ps2not		db	'Error: PS/2 not supported',0dh,0ah,'$'
ENDIF

dnfStr		db	'Cannot find pointer device', 0Dh,'$'
alrStr		db	'Mouse already installed',0dh,0ah,'$'
instStr		db	'Installed on: COM $'
resol		db	'Resolution: $'
auto		db	'Auto',0dh,0ah,'$'
times		db	'3/3 times horizontally/vertically',0dh,0ah,'$'
badswstring	db	0Ah, 0Dh, 'Error: Invalid parameter',0Ah, 0Dh
		db	'Enter /h on command line for help',0dh,0ah,'$'
com_port	db	0,0dh,0ah,'$'

IFNDEF PS2
CMDStr		db	'Cute Mouse Driver v1.4',0dh,0ah
		db	'Copyright (C) Nagy Daniel', 0Dh,0ah
		db	'Options:',0dh,0ah
		db	'  /n   - where n is the COM port number',0dh,0ah
		db	'  /R0  - Auto hardware resolution',0dh,0ah
		db	'  /Rnm - n,m=1-9 resolution horizontally/vertically. Default is R33',0dh,0ah
		db	'  /M   - Force Microsoft mode (2 buttons)',0dh,0ah
		db	'  /T   - Force Logitech MouseMan mode (3 buttons)',0dh,0ah
		db	'  /S   - Force Mouse Systems mode (3 buttons)',0dh,0ah
		db	'  /In  - Force IRQ number (n is in hex: n=3...F)',0dh,0ah
		db	'  /L   - Left hand mode. Default is right hand mode',0dh,0ah
		db	'  /U   - Release driver',0dh,0ah
		db	'  /H   - Show help',0dh,0ah,'$'
microsoft?	db	0		; reg for detection
ELSE
CMDStr		db	'Cute Mouse Driver v1.4 for PS/2 mice',0dh,0ah
		db	'Copyright (C) Nagy Daniel', 0Dh,0ah
		db	'Options:',0dh,0ah
		db	'  /R0  - Auto hardware resolution',0dh,0ah
		db	'  /Rnm - n,m=1-9 resolution horizontally/vertically. Default is R33',0dh,0ah
		db	'  /L   - Left hand mode. Default is right hand mode',0dh,0ah
		db	'  /U   - Release driver',0dh,0ah
		db	'  /H   - Show help',0dh,0ah,'$'
ENDIF

noemem		db	'Not enough memory!$'
ctstr		db	'CTMOUSE '

paragraphs	dw	0
dest_seg	dw	0

label		xms	dword
xms_ofs		dw	0
xms_seg		dw	0

;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ  Real Start ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ


real_start:	mov	ah,4Ah			; free all the conv memory
		mov	bx,15+(offset endProgram); that the prog will not use
		shr	bx,4
		int	21h

		call	commandline		; examine command line
		jnc	@goodparam
		jmp	@badparam

IFNDEF PS2
@goodparam:	cmp	indicator,1		; show help?
		jne	@noshowhelp
		call	printhelp		; print help and exit

@noshowhelp:	lea	dx,cutestring
		mov	ah,9
		int	21h			; display 'Cute driver'
		cmp	indicator,2		; release driver?
		jne	@dontrel
		call	reldriver		; release driver and quit

@dontrel:	cmp	com_port,0		; COM port number forced?
		jne	@COMforce		; jump if yes
		cmp	forced,0		; mode is forced?
		jnz	@dontchps2		; jump if yes
		call	checkps2		; check for PS2
@dontchps2:	mov	com_port,31h		; '1'

@COMforce:	cmp	forced,0
		jz	@detit			; jump if mode not forced
		call	chkcom
		jnz	@comnotfound		; jump if not found
		call	instexam		; test if driver is installed
		jnz	@notinstyet
		call	changeparam		; change params and quit

@detit:		call	detmoustype		; is mouse present?
		jc	@comnotfound		; jump if not found

@notinstyet:	call	allochmem		; allocate memory
		call	saveoldIRQ		; save old IRQ handler address

ELSE

@goodparam:	lea	dx,cutestring
		mov	ah,9
		int	21h			; display 'Cute driver'

		call	checkPS2		; check PS2
		jc	@devnotfound

		call	instexam		; check if driver installed
		jnz	@notinstalled
		call	changeparam		; if yes, then change params
						;   and exit
@notinstalled:	call	allochmem		; allocate memory
		mov	IRQintnum,74h
		call	saveoldIRQ		; save old IRQ handler address
ENDIF
		call	newvideohandler		; set up new video handler
		call	saveold33		; save old INT 33h handler

		call	relocate		; relocate resident portion

		cli				; do not disturb until we
						;  install the handlers

		call	setnewIRQ		; setup new IRQ handler

		lds	dx,int10pointer
		mov	ax,2510h
		int	21h			; setup new 10 handler

		push	es
		pop	ds
		lea	dx,handler
		mov	ax,2533h
		int	21h			; setup new 33 handler
		sti

		push	cs
		pop	ds

		xor	ax,ax
		int	33h			; Reset driver

		call	printmod&res		; print mode and resolution

IFNDEF PS2
		call	printport		; print port number
ENDIF

		mov	ax,4c00h
		int	21h			; exit with no errorlevel

;---------------------------

@devnotfound:	lea	dx,dnfStr		; 'Cannot find pointer device'
		jmp	@printexit

;--------------------------
IFNDEF PS2
@comnotfound:	lea	dx,ncfStr		; 'Cannot find COM: port...'
		jmp	@printexit
ENDIF
;-------------------------

@badparam:	lea	dx,badswstring		; 'Invalid parameter'
@printexit:	mov	ah,9
		int	21h
		mov	ax,4CFFh		; exit with errorlevel
		int	21h

IFNDEF PS2
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                  Check if requested mouse type available
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

checktype	proc

		cmp	mousetype,2	; microsoft Mouse?
		je	@Mavail
		cmp	mousetype,3	; mouse systems mouse?
		jne	@Mnotavail

@Mavail:	call	disableCOMint
		call	chkcom		; check COM port
		jnz	@Mnotavail	; jump if not available

		mov	si,IO_number
		call	mouseHWreset
		cmp	mousetype,2	; microsoft mouse?
		jne	@notMSm
		call	detmicrosoft
		jc	@Mnotavail
		jmp	@setMSm

@notMSm:	mov	al,8
		cmp	logitech?,0
		je	@write8
		add	al,3
@write8:	mov	dx,si
		add	dx,4
		out	dx,al		; port 3FCh, clear RTS and DTR,
		jmp	$+2		; set output 2

@setMSm:	mov	al,1
		mov	dx,si
		inc	dx
		out	dx,al		; port 3F9h, DR int enable
		jmp	$+2
		clc
		ret

@Mnotavail:	stc
		ret

checktype	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                        Reset mouse hardware
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

mouseHWreset	proc

		mov	al,80h
		mov	dx,si
		add	dx,3
		out	dx,al		; port 3FBh, set DLAB on
		jmp	$+2

		mov	al,60h
		mov	dx,si
		out	dx,al		; port 3F8h, speed LO byte
		jmp	$+2

		xor	al,al
		inc	dx
		out	dx,al		; port 3F9h, speed HI byte
		jmp	$+2

		mov	ax,mousetype
		add	dx,2
		out	dx,al		; port 3FBh, set comm params
		jmp	$+2		; and DLAB=0

		xor	al,al
		sub	dx,2
		out	dx,al		; port 3F9h, all interrupts off
		jmp	$+2

		mov	al,1
		add	dx,3
		out	dx,al		; port 3FCh, activate DTR and
		jmp	$+2		; clear RTS

		xor	cx,cx
@loopwait:	loop	@loopwait

		inc	dx
		in	al,dx		; port 3FDh, clear error bits
		jmp	$+2
		ret

mouseHWreset	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                      Detect if Microsoft Mouse present
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

detmicrosoft	proc

		mov	al,0Bh
		mov	dx,si
		add	dx,4
		out	dx,al		; port 3FCh, activate DTR, RTS and
		jmp	$+2		; output 2

		mov	dx,si
		in	al,dx		; port 3F8h, flush receive buffer
		jmp	$+2
		xor	bx,bx

getM:		xor	cx,cx
chkDTR:		mov	dx,si
		add	dx,5
		in	al,dx		; port 3FDh, get line stat reg
		jmp	$+2
		and	al,1		; check if data ready
		jnz	DTRok		; jump if yes
		loop	chkDTR		; if not, try again
		jmp	DTRnotok	; if no data received, exit with error

DTRok:		mov	dx,si
		in	al,dx		; port 3F8h, get that bastard byte
		cmp	al,33h		; '3' received?
		jne	@not3
		mov	logitech?,1
@not3:		cmp	al,4Dh		; 'M' received?
		jne	@notM		; jump if not
		mov	microsoft?,1
@notM:		inc	bx
		cmp	bx,4		; if there is no 'M' within 4 received
		jb	getM		;  bytes, then exit with error

DTRnotok:	cmp	microsoft?,0
		je	@setdeterror
		cmp	logitech?,1
		je	@setdeterror
		clc
		ret

@setdeterror:	stc
		ret

detmicrosoft	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                              Set Mouse Port
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

comport		proc

		cmp	al,31h			; '1'
		jne	notcom1
		mov	cs:com_port,al
		mov	cs:IO_number,3F8h
		mov	cs:PICstate,10h		; PIC interrupt enabler (COM1)
		mov	cs:IRQ_number,4
		mov	cs:IRQintnum,0Ch
		jmp	endportset

notcom1:	cmp	al,32h			; '2'
		jne	notcom2
		mov	cs:com_port,al
		mov	cs:IO_number,2F8h
		mov	cs:PICstate,8		; PIC interrupt enabler (COM2)
		mov	cs:IRQ_number,3
		mov	cs:IRQintnum,0Bh
		jmp	endportset

notcom2:	cmp	al,33h			; '3'
		jne	notcom3
		mov	cs:com_port,al
		mov	cs:IO_number,3E8h
		mov	cs:PICstate,10h
		mov	cs:IRQ_number,4
		mov	cs:IRQintnum,0Ch
		jmp	endportset

notcom3:	cmp	al,34h			; '4'
		jne	notCOM
		mov	cs:com_port,al
		mov	cs:IO_number,2E8h
		mov	cs:PICstate,8
		mov	cs:IRQ_number,3
		mov	cs:IRQintnum,0Bh

endportset:	clc
		ret

notCOM:		stc
		ret

comport		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                              Print COM port number
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

printport	proc

		lea	dx,instStr		; 'Installed on: COM '
		mov	ah,9
		int	21h

		lea	dx,com_port		; 'COM x'
		mov	ah,9
		int	21h			; display string
		ret

printport	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                            Set Manual IRQ num
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setIRQ  	proc

		cmp	al,'I'
		jne	endsetIRQ
		lodsb
		cmp	al,33h
		jb	endsetIRQ
		cmp	al,40h
		jb	numa
		and	al,0dfh
		cmp	al,'F'
		ja	endsetIRQ
		sub	al,7
numa:		sub	al,30h
		mov	cs:IRQ_number,al
		cmp	al,8
		jb	numa2
		add	al,60h
numa2:		add	al,8
		mov	cs:IRQintnum,al
		jmp	oksetIRQ

endsetIRQ:	stc
		ret

oksetIRQ:	clc
		ret

setIRQ  	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                         Check for PS/2
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

checkps2	proc

		int	11h
		test	al,4			; PS/2?
		jz	notPS2			; Jump if not

		lea	dx,ps2not
		mov	ah,9			;print error and exit
		int	21h
		mov	ax,4cffh
		int	21h

notPS2:		ret

checkps2	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Determine Mouse Type
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

detmoustype	proc

		mov	mousetype,2		; Set Microsoft mouse type
		call	checktype
		jnc	microinst
		mov	mousetype,3		; Set Mouse systems mode
		call	checktype
		jc	nomice

microinst:	call	instexam		; already installed?
		jnz	notyetinst		; if no, jump
		call	changeparam		; else change params and exit

notyetinst:	clc
nomice:		ret

detmoustype	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                   Change IRQ handler to new IRQ number
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

changeIRQ	proc

		push	cs
		pop	ds
		cli
		call	setIRQparams
		mov	al,PICstate
		mov	es:PICstate,al
		mov	ax,IO_number
		mov	es:IO_number,ax
		mov	al,IRQ_number
		mov	es:IRQ_number,al
		mov	ah,25h
		lds	dx,oldIRQaddr
		int	21h			; restore handler for old IRQ

		call	setnewIRQ		; install handler for new IRQ
		mov	al,cs:IRQintnum
		mov	es:IRQintnum,al
		sti
		ret

changeIRQ	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                            Set IRQ params
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setIRQparams	proc

		push	dx
		push	si
		mov	si,es:IO_number
		xor	al,al
		mov	dx,si
		inc	dx
		out	dx,al		; port 3F9h, disable all interrupts
		jmp	$+2

		add	dx,3
		in	al,dx		; port 3FCh, modem ctrl
		jmp	$+2
		and	al,0F3h		; disable auxilary outputs
		out	dx,al
		jmp	$+2

		inc	dx
		in	al,dx		; port 3FDh, clear error bits
		jmp	$+2

		mov	dx,si
		in	al,dx		; port 3F8h, flush receive buffer
		jmp	$+2
		pop	si
		pop	dx
		ret

setIRQparams	endp

ENDIF

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                            Print Help and Quit
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

printhelp	proc

		lea	dx,CMDStr
		mov	ah,9
		int	21h			; display char string at ds:dx

		mov	ax,4C00h
		int	21h			; terminate with al=return code

printhelp	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                            Examine if installed
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

instexam	proc

		mov	ax,3533h
		int	21h			; get intrpt vector al in es:bx
		lea	ax,handler
		cmp	ax,bx
		ret

instexam	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                              Examine Command Line
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

commandline	proc

		mov	si,81h
		cld
newopt:		call	parsecmdl
		lodsb
		cmp	al,0Dh			; ENTER?
		je	noswit
		cmp	al,0Ah			; ENTER?
		je	noswit
		test	al,al			; NULL?
		je	noswit
		cmp	al,2Fh			; '/'
		jne	noslash

		lodsb
		cmp	al,3Fh			; '?'
		jne	nohelp
		jmp	shelp			; '/?' -> print help
nohelp:
IFNDEF PS2
		call	comport
		jnc	newopt
ELSE
		and	al,0dfh
ENDIF

		call	resolution
		jnc	newopt
		call	whichhand
		jnc	newopt

IFNDEF PS2
		call	setIRQ
		jnc	newopt

noslash:	and	al,0dfh
ELSE
noslash:
ENDIF

		cmp	al,'H'
		je	shelp			; then print help

IFDEF PS2
		cmp	al,'U'
		jne	badswitch
		call	reldriver
shelp:		call	printhelp
noswit:		clc
		ret
badswitch:	stc
		ret
ELSE
		jmp	ftyp

noswit:		jmp	noswitch

ftyp:		cmp	al,'M'			; force microsoft
		jne	nofmi
		mov	mousetype,2
		mov	logitech?,0
		jmp	force

nofmi:		cmp	al,'T'			; force logitech
		jne	noflog
		mov	mousetype,3
		mov	logitech?,1
		jmp	force

noflog:		cmp	al,'S'			; force mouse systems
		jne	nofsys
		mov	mousetype,3
		mov	logitech?,0
force:		mov	forced,1
		jmp	noswitch

nofsys:		cmp	al,'U'			; release driver?
		jne	badswitch
		mov	cs:indicator,2		; indicate release driver
		jmp	noswitch
shelp:		mov	cs:indicator,1		; indicate help request
noswitch:	clc
		ret
badswitch:	stc
		ret
ENDIF
commandline	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

parsecmdl	proc

pars_st:	lodsb
		cmp	al,20h			;space?
		je	pars_st
		cmp	al,9			;tab?
		je	pars_st
		dec	si
		ret

parsecmdl	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                              Set hand mode
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

whichhand	proc

		cmp	al,4Ch			; 'L'
		jne	righthand
		mov	handmode,1		; set left handed mode
		clc
		ret

righthand:	mov	handmode,0		; set right handed mode
		stc
		ret

whichhand	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                            Set Resolution
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

resolution	proc

IFNDEF PS2
		and	al,0DFh
ENDIF
		cmp	al,52h			; 'R'
		jne	@endsetres

		lodsb
		cmp	al,30h			; '0'
		je	@autores
		cmp	al,31h			; smaller than 1?
		jb	@endsetres
		cmp	al,39h			; bigger than 9?
		ja	@endsetres
		mov	byte ptr times,al	; 'x/x  Times  Resolution '
		sub	al,31h
		mov	byte ptr mresolution,al
		lodsb
		cmp	al,30h
		je	@autores
		cmp	al,31h
		jb	@no2ndres
		cmp	al,39h
		ja	@no2ndres
@store2nd:	mov	byte ptr times+2,al
		sub	al,31h
		mov	byte ptr mresolution+1,al
		mov	autores?,0
		jmp	@oksetres

@no2ndres:	mov	al,byte ptr times
		dec	si			; fixup for command line
		jmp	@store2nd

@autores:	mov	autores?,1
		mov	word ptr mresolution,0
@oksetres:	clc
		ret

@endsetres:	stc
		ret

resolution	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Release driver and quit
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

reldriver	proc

		call	instexam
		jnz	notinst

		push	es			; store segment of handler
		lea	dx,relStr		; 'Current Mouse Driver...'
		mov	ah,9
		int	21h			; display char string
		mov	ax,1Fh
		int	33h			; disable driver
		pop	es

		push	ds
		mov	dx,word ptr es:oldint33
		mov	ax,word ptr es:oldint33+2
		mov	ds,ax
		mov	ax,2533h
		int	21h			; set intrpt vector al to ds:dx

		mov	ax,es
		mov	bx,ax
		dec	bx
		mov	ds,bx
		mov	ah,62h
		int	21h
		mov	ds:[1],bx		; modify MCB
		pop	ds
		call	FreeMem
		jc	notinst

		mov	ax,4C00h
		int	21h			; terminate with al=return code

notinst:	lea	dx,mnsStr		; 'Mouse Driver Not Installed'
		mov	ah,9
		int	21h			; display char string at ds:dx
		mov	ax,4CFFh
		int	21h			; terminate with al=return code

reldriver	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                If already installed, change params and exit
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

changeparam	proc

		mov	al,handmode
		mov	es:handmode,al
		mov	ax,mresolution
		mov	es:mresolution,ax
		mov	al,autores?		; set up new params
		mov	es:autores?,al
		call	printmod&res		; print new params

		push	es
		mov	ax,1Fh
		int	33h			; disable driver
		pop	es

		mov	ax,mousetype
		mov	es:mousetype,ax		; setup new type

IFNDEF PS2
		mov	ax,logitech?
		mov	es:logitech?,ax
ENDIF
		mov	ax,20h
		int	33h			; enable driver

IFNDEF PS2
		call	printport
ENDIF

		call	printalready

IFNDEF PS2
		mov	al,IRQintnum		; check if we have to change
		cmp	al,es:IRQintnum		;  interrupt number
		je	nointch			; jump if not
		call	changeIRQ		; else change
ENDIF

nointch:	mov	ax,4C00h
		int	21h			; terminate with al=return code

changeparam	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß

newvideohandler	proc

		call	detVGA			; detect VGA card
		xor	ax,ax
		mov	ds,ax
		mov	ah,ds:449h		; AH - current videomode
		call	displayports		; set up display port funcs
		push	cs
		pop	ds
		mov	which10toset,1		; indicate new handler

		push	es
		mov	ax,3510h
		int	21h			; save old 10 handler
		mov	old10offset,bx
		mov	old10segment,es
		pop	es
		mov	word ptr newint10,offset int10handler
		mov	word ptr newint10+2,es
		mov	word ptr int10pointer,offset int10handler
		mov	word ptr int10pointer+2,es

		ret

newvideohandler	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Detect VGA card
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

detVGA		proc

		mov	ax,1A00h
		xor	bx,bx
		int	10h		; get display type in bx
		cmp	al,1Ah
		jne	@itsnotVGA

		cmp	bl,7		; VGA with monochrome?
		je	@itsaVGA
		cmp	bl,8		; Color VGA?
		jne	@itsnotVGA

@itsaVGA:	mov	VGAindicat,1

@itsnotVGA:	ret

detVGA		endp



;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Save old IRQ handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

saveoldIRQ	proc

IFNDEF PS2
		lea	dx,IRQhandler
ELSE
		lea	dx,handleIRQ
ENDIF

		mov	word ptr newIRQaddr,dx
		mov	word ptr newIRQaddr+2,es

		push	es
		mov	al,IRQintnum
		mov	ah,35h
		int	21h			;get old IRQ handler pointer
		mov	word ptr oldIRQaddr+2,es
		mov	word ptr oldIRQaddr,bx
		pop	es
		ret

saveoldIRQ	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Save old INT33h handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

saveold33	proc

		push	es
		mov	ax,3533h
		int	21h			; save old 33 handler
		mov	word ptr oldint33,bx
		mov	word ptr oldint33+2,es
		pop	es
		ret

		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                          Set new IRQ handler
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

setnewIRQ	proc

		push	ds
		mov	al,IRQintnum
		mov	ah,25h
		lds	dx,newIRQaddr
		int	21h			; set new IRQ handler
		pop	ds
		ret

		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Print if already installed
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

printalready	proc

		lea	dx,alrStr		; 'Mouse already installed'
		mov	ah,9
		int	21h			; display char string at ds:dx

		ret

printalready	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
;                           Print mode and resolution
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

printmod&res	proc

		push	es

IFNDEF PS2
		cmp	mousetype,3		; Mouse systems mouse?
		jne	@micromode
		cmp	logitech?,0		; Logitech mouse?
		je	@notlogi

		lea	dx,datalogi
		jmp	@printmode

@notlogi:	lea	dx,MSMStr		; 'Driver Installed: Mouse'
		jmp	@printmode

@micromode:	lea	dx,MSStr		; 'Driver Installed: Microsoft'
ELSE
		lea	dx,drivmod
ENDIF

@printmode:	mov	ah,9
		int	21h

		lea	dx,resol		; 'Resolution:'
		mov	ah,9
		int	21h

		cmp	autores?,1
		jne	@noprauto
		lea	dx,auto
		jmp	@prres
@noprauto:	lea	dx,times
@prres:		mov	ah,9
		int	21h

		pop	es
		ret

printmod&res	endp

;-------------------

; DOS 5.0+ UMB's
SaveMemStrat	dw	0
SaveUMBLink	db	0

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; Get "xms" handler address (2 words)
; ZF indicates error
;
getXMSaddr	proc	near
		xor	bx,bx
		mov	es,bx
		mov	ax,4310h	; XMS: Get Driver Address
		int	2Fh
		mov	[xms_ofs],bx
		mov	[xms_seg],es
		mov	ax,es
		or	ax,bx		; ZF indicates error: JZ error
		ret
getXMSaddr	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; Get Allocation Srategy
; CF indicates error
GetAllocStrat	proc	near
		mov	ax,5800h	; get DOS memory alloc strategy
		int	21h
		jc	@@fingas	; not supported
		mov	[SaveMemStrat],ax

		mov	ax,5802h	; get UMB link state
		int	21h
		jc	@@fingas	; not supported
		mov	[SaveUMBLink],al
		clc
@@fingas:	ret
GetAllocStrat	endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; Restore allocation strategy
;
ResAllocStrat	proc	near
		mov	ax,5801h		; set DOS memory alloc strategy
		mov	bx,[SaveMemStrat]
		int	21h
		mov	ax,5803h		; set UMB link state
		mov	bl,[SaveUMBLink]
		xor	bh,bh
		int	21h
		ret
ResAllocStrat	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; function AllocMem
;In:	AX - memory required
;Out:	AX - segment (or 0 if error)
;	dest_seg
;	mem_type

AllocMem	proc	near			; call with AX = n of bytes

		push	ds es
		mov	[mem_type],0
		mov	[dest_seg],0
		add	ax,0Fh
		shr	ax,4
		mov	[paragraphs],ax

; Check if UMB is DOS5+ type

		mov	ah,30h
		int	21h
		cmp	al,5			; DOS >= 5.0, supports UMBs
		jb	@@noDOS5UMBs

		call	GetAllocStrat
		jc	@@noDOS5UMBs

		mov	ax,5801h		; set DOS memory alloc strategy
		xor	bx,bx			; low mem, first fit
		int	21h
		jc	@@noDOS5UMBs		; reports >= 5.0 no support

		mov	ax,5803h		; set UMB link state
		mov	bx,1			; add UMB to MCB chain
		int	21h
		jc	@@noDOS5UMBs

; try to set a good strategy to allocate DOS supported UMBs

		mov	ax,5801h		; set alloc strategy
		mov	bx,41h			; hi mem, best fit
		int	21h
		jnc	@@linkUMB		; jump if success

; try a worse one then

		mov	ax,5801h	; set alloc strategy
		mov	bx,81h		; hi mem then low mem, best fit
		int	21h
		jc	@@dev5		; jump if error

@@linkUMB:	mov	ax,5803h	; add UMBs to link state
		mov	bx,1
		int	21h
		mov	ah,48h		; allocate UMB memory
		mov	bx,[paragraphs]
		int	21h
		jc	@@dev5
		cmp	ax,0A000h	; check if allocated mem is
		ja	@@Dumb_OK	; beyond 640k. Jump if yes

		mov	es,ax		; if below, then free it
		mov	ah,49h
		int	21h
		stc			; indicate it
		jmp	@@dev5

@@Dumb_OK:	clc
@@dev5:		pushf
		push	ax
		call	ResAllocStrat	; restore allocation strategy
		pop	ax
		popf
		jc	@@noDOS5UMBs	; jump if UMB allocating not successful
		mov	dest_seg,ax	; else set proper variables and exit
		mov	mem_type,1	; 1 = DOS 5.0+ UMB
		jmp	@@fin

; try XMS driver to allocate UMB

@@noDOS5UMBs:	mov	ax,4300h	; XMS: Installation Check
		int	2Fh
		cmp     al,80h
		jne	@@noXMS_UMB
		call	getXMSaddr
		jz	@@noXMS_UMB
		mov	ah,10h		; XMS: Request Upper Memory Block
		mov	dx,paragraphs
		call	dword ptr xms
		cmp	ax,1
		jne	@@noXMS_UMB
		cmp	dx,paragraphs
		jb	@@noAlcanza
		mov	dest_seg,bx
		mov	mem_type,2	; 2 = XMS UMB
		jmp	@@fin

@@noAlcanza:	mov	dx,bx
		mov	ah,11h		; XMS: Release Upper Memory Block
		call	dword ptr xms

; try to allocate conventional memory

@@noXMS_UMB:	mov	ah,48h		; get maximum available memory
		mov	bx,-1
		int	21h
		cmp	bx,paragraphs
		jbe	@@noFIN_CONV	; jump if not enough
		sub	bx,paragraphs
		dec	bx		; (-1 because MCB occupies 1 parag.)
		mov	ah,48h		; allocate it
		int	21h
		jc	@@noFIN_CONV	; jump if error
		mov	es,ax		; ES = allocated segment
		mov	ah,48h		; allocate memory
		mov	bx,paragraphs
		int	21h
		pushf
		push	ax
		mov	ah,49h		; free allocated memory
		int	21h
		pop	ax
		popf
		jc	@@noFIN_CONV
		mov	dest_seg,ax	; AX=segment
		mov	mem_type,3	; 3 = it's in conventional memory
		jmp	@@fin

@@noFIN_CONV:

@@fin:		pop	es ds
		mov	ax,dest_seg
		ret
AllocMem	endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
FreeMem		proc	near
;IN: ES - segment to free

		push	ds es
		mov	al,es:mem_type
		cmp	al,2
		je	@@xms
		cmp	al,3
		je	@@finConv

@@dos5:		call	GetAllocStrat
		jc	@@finfree	; error?
		mov	ax,5803h	; unlink UMBs
		xor	bx,bx
		int	21h
		mov	ah,49h		; free allocated memory
		int	21h
		call	ResAllocStrat
		jmp	@@finfree

@@xms:		call	getXMSaddr
		jz	@@finfree	; error?
		mov	ah,11h		; XMS: Release Upper Memory Block
		mov	dx,es
		call	dword ptr xms
		jmp	@@finfree

@@finConv:	mov	ah,49h		; free allocated memory
		int	21h
@@finfree:	pop	es ds
		ret

FreeMem		endp


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
allochmem	proc

		mov	ax,offset IRQ_number	; get number of bytes
		call	AllocMem		;  we need memory for
		jnc	@okmem

		mov	ah,9
		lea	dx,noemem		; error if no available
		int	21h
		mov	ax,4cffh
		int	21h

@okmem:		mov	bx,ax
		dec	bx
		push	ds
		mov	ds,bx			; modify MCB
		mov	word ptr ds:[1],ax
		pop	ds

		mov	es,bx
		lea	si,ctstr
		mov	di,8
		mov	cx,8
		rep	movsb			; copy process name

		mov	es,ax

		mov	dx,ax
		mov	ah,26h
		int	21h			; create PSP

		ret

		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
relocate	proc

		mov	si,100h			; relocate the resident
		mov	di,si			;  portion
		mov	cx,offset IRQ_number-offset start
		rep	movsb
		ret

		endp

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
label endProgram

		end	start
