; MOUSE-DRIVER (emulation) (w) '94 by SiPiYou/CD aka Nima Ghasseminejad
; if you enhance this stuff, please gimme a copy of y'a work, thnx!

.386
CodeS  segment use16
       assume  cs:CodeS, ds:CodeS

       MC      equ 0            ; .. guess what!
       MaxX    equ 11
       MaxY    equ 11
       MPort   equ 03f8h
       MIrq    equ 4

       OldScr  db 11*11 dup (?)
       Old     dw 0
       _x      dw 0
       _y      dw 0
       Left    db 0
       Right   db 0
       Active  db 0
       MProt   db 3 dup (?)
       BCnter  dw ?
       OldInt  dd ?
       Old33h  dd ?

       ; Sorry to Commodore... But I really like this mouse pointer!
label Mouse1 byte
db mc+12,mc+15,   99,   99,   99,   99,   99,   99,   99,   99,   99
db mc+00,mc+12,mc+15,mc+15,   99,   99,   99,   99,   99,   99,   99
db    99,mc+00,mc+12,mc+12,mc+15,mc+15,   99,   99,   99,   99,   99
db    99,mc+00,mc+12,mc+12,mc+12,mc+12,mc+15,mc+15,   99,   99,   99
db    99,   99,mc+00,mc+12,mc+12,mc+12,mc+12,mc+12,mc+15,mc+15,   99
db    99,   99,mc+00,mc+12,mc+12,mc+12,mc+12,mc+12,mc+12,mc+12,mc+12
db    99,   99,   99,mc+00,mc+12,mc+12,mc+12,mc+15,   99,   99,   99
db    99,   99,   99,mc+00,mc+12,mc+12,mc+00,mc+12,mc+15,   99,   99
db    99,   99,   99,   99,mc+00,mc+12,   99,mc+00,mc+12,mc+15,   99
db    99,   99,   99,   99,mc+00,mc+12,   99,   99,mc+00,mc+12,mc+15
db    99,   99,   99,   99,   99,   99,   99,   99,   99,mc+00,mc+12

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
HideMouse:
         pusha
         mov      ax, cs
         mov      ds, ax

         mov      Active, 1
         mov      cx, _X
         mov      dx, _Y

         shr      cx, 1
         mov      ax, 0a000h
         mov      es, ax

         xchg     dh, dl                 ; * 256
         mov      di, dx
         shr      dx, 2
         add      di, dx
         add      di, cx

; restore OldMouse
         mov      bx, offset Mouse1
         mov      bp, Old
         mov      si, offset OldScr
         mov      cx, MaxY
@HYRestore:
         push     cx
         mov      cx, MaxX
@HXRestore:
         mov      al, [si]
         inc      si
         mov      ah, es:[bp]
         cmp      ah, ds:[bx]
         jne      short @HNoRestore
         mov      es:[bp], al
@HNoRestore:
         inc      bx
         inc      bp
         loop     @HXRestore
         add      bp, 320-MaxY
         pop      cx
         loop     @HYRestore
         popa
         ret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
ShowMouse:
         call     NewMouse
         mov      cs:_X, 0
         mov      cs:_Y, 0
         mov      cs:Active, 1
         pop      bx
         iret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
NewMouse:
         pusha
         mov      ax, 0a000h
         mov      es, ax

         mov      ax, cs
         mov      ds, ax

         mov      cx, _X
         mov      dx, _Y

         shr      cx, 1

         xchg     dh, dl                 ; * 256
         mov      di, dx
         shr      dx, 2
         add      di, dx
         add      di, cx

; restore OldMouse
         mov      bx, offset Mouse1
         mov      bp, Old
         mov      si, offset OldScr
         mov      cx, MaxY
@YRestore:
         push     cx
         mov      cx, MaxX
@XRestore:
         mov      al, [si]
         inc      si
         mov      ah, es:[bp]
         cmp      ah, ds:[bx]
         jne      short @NoRestore
         mov      es:[bp], al
@NoRestore:
         inc      bx
         inc      bp
         loop     @XRestore
         add      bp, 320-MaxY
         pop      cx
         loop     @YRestore

         mov      Old, di
         mov      bp, di
         mov      si, offset OldScr

         mov      cx, MaxY
@YSave:
         push     cx
         mov      cx, MaxX
@XSave:
         mov      al, es:[bp]
         mov      [si], al
         inc      si
         inc      bp
         loop     @XSave
         pop      cx
         add      bp, 320-MaxY
         loop     short @YSave

; plot new mouse
         mov      dx, 03dah
@WaitRet:
         in       al, dx
         test     al, 1
         jnz      short @WaitRet

         mov      si, offset mouse1
         mov      cx, MaxY
@YLoop:
         push     cx
         mov      cx, MaxX
@XLoop:
         mov      al, cs:[si]
         inc      si
         cmp      al, 99
         je       short @NoPlot
         mov      es:[di], al
@NoPlot:
         inc      di
         loop     @XLoop
         add      di, 320-MaxY
         pop      cx
         loop     @YLoop
         popa
         ret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
MHandler:
         push     ax  bx  cx  dx  di  bp  ds  es
         mov      ax, seg CodeS
         mov      ds, ax

         mov      dx, MPort
         in       al, dx
         test     al, 64
         jz       short @NoProtByte
         mov      BCnter, 0
@NoProtByte:
         mov      bx, BCnter
         cmp      bx, 2
         jae      short @Complete

         inc      BCnter
         mov      [Mprot+bx], al
         jmp      short @@Exit

@Complete:
         mov      [MProt+bx], al        ; save last byte...
         xor      ax, ax
         mov      [BCnter], ax

         mov      al, [Mprot]
         test     al, 32
         setnz    left
         test     al, 16
         setnz    right

         mov      bx, ax
         and      al, 3
         shl      al, 6
         add      al, [Mprot+1]
         cmp      al, 128
         jbe      short @NoXCorrection
         neg      al
         sub      _x, ax
         jnb      short @go2

         mov      _x, 0
         jmp      short @go2
@NoXCorrection:
         add      _X, ax
         cmp      _x, 640
         jb       short @go2
         mov      _x, 640
@go2:

         and      bl, 12
         shl      bl, 4
         add      bl, [Mprot+2]
         cmp      bl, 128
         jbe      short @NoYCorrection
         neg      bl
         sub      _y, bx
         jnb      short @go1

         mov      _y, 0
         jmp      short @go1
@NoYCorrection:
         add      _Y, bx
         cmp      _y, 200
         jb       short @go1
         mov      _y, 200
@go1:
         call     NewMouse
@@Exit:
         pop      es  ds  bp  di  dx  cx  bx
         mov      al, 20h
         out      20h, al
         pop      ax
         iret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
ResetMouse:
         pop      bx
         mov      bx, 2
         dec      ax
         iret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
ReturnState:
;Bit(s)  Descrition
; 0      left button pressed if 1
; 1      right button pressed if 1
         pop      bx

         xor      bx, bx
         mov      bl, cs:right
         shl      bl, 1
         add      bl, cs:left

         mov      cx, cs:_x
         mov      dx, cs:_y
         iret
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
SetMousePos:
;INT 33 - MS MOUSE v1.0+ - POSITION MOUSE CURSOR
;       AX = 0004h
;       CX = column
;       DX = row
         mov      cs:_X, cx
         mov      cs:_Y, dx
         cmp      cs:Active, 0
         jz       short @NotActive
         call     NewMouse
@NotActive:
         ret
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
Jmptable dw offset ResetMouse
         dw offset ShowMouse
         dw offset HideMouse
         dw offset ReturnState
         dw offset SetMousePos
Int33h:
         push     bx
         mov      bx, ax
         shl      bx, 1
         jmp      JmpTable+bx
         pop      bx
@Exit:
         iret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
InitMouse:
         cli
         in       al,21h
         jmp      $+2
         jmp      $+2

         and      al, not 2 shl (Mirq-1); enable mouse-irq
         out      21h, al

         mov      dx, MPort+3
         mov      al, 80h                ; set baudrate to 1200
         out      dx, al
         sub      dx, 3
         mov      ax, 115200 / 1200
         out      dx, al
         inc      dx
         mov      al, ah
         out      dx, al

         add      dx, 2
         mov      al, 2
         out      dx, al                 ; 7 N 1

         sub      dx, 2
         mov      al, 1
         out      dx, al                 ; enable int's...

         add      dx, 3
         mov      al, 1 or 2 or 8        ; raise DTR, RTS, OUT2
         out      dx, al

         sub      dx, 4
         in       al, dx                 ; ACK mouse, else no irq-call!

         mov      al, 20h                ; ACK Int.
         out      20h, al

         ; now install new mouse-handler

         mov      eax, es:[(8+Mirq) shl 2]
         mov      Oldint, eax
         mov      word ptr es:[(8+Mirq) shl 2], offset MHandler
         mov      word ptr es:[(8+Mirq) shl 2]+2, cs

         mov      eax, es:[4*33h]
         mov      Old33h, eax
         mov      word ptr es:[33h*4], offset Int33h
         mov      word ptr es:[33h*4]+2, cs

         sti
         ret

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
main:
         mov      ax, cs
         mov      ds, ax

         xor      ax, ax
         mov      es, ax

         mov      ax, 13h
         int      10h
         call     InitMouse

         mov      ax, 1
         int      33h

@looptst:
         cmp      left, 0
         je       short @looptst

         xor      ax, ax
         mov      es, ax
         mov      ax, cs
         mov      ds, ax

         mov      eax, OldInt
         cli
         mov      es:[(8+Mirq) shl 2], eax

         mov      eax, Old33h
         mov      es:[4*33h], eax
         sti

         mov      ax, 3
         int      10h
         mov      ah, 4ch
         int      21h

ends     CodeS
         end      main
