mouse.asm 6.63 KB
Newer Older
Ercan Ersoy's avatar
Ercan Ersoy committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
; MOUSE.ASM
;
; License CC0 PUBLIC DOMAIN
;
; To the extent possible under law, Mark J. Olesen has waived all copyright 
; and related or neighboring rights to FDOSTUI Library. This work is published 
; from: United States.


include MOUSE.INC

.MODEL medium

.DATA?

public queue

QUEUE_SIZE EQU 24
queue mouse_event QUEUE_SIZE dup(?) ; mouse event circular buffer
QUEUE_BYTES EQU $ - queue ; event queue size

.DATA

PUBLIC _mouse_initialized

public qstart
public qend
public qactive

qstart dw 0 ; where the next element will be dequeued
qend dw 0 ; where the next element will be queued
qactive dw 0; number of occupied slots

_mouse_initialized dw 0 ; indicator if mouse is enabled
saved_mask dw 0  ; saved interrupt chain mask
saved_routine_dx dw 0 ; saved interrupt dx value
saved_routine_es dw 0 ; saved interrupt es value

.CODE
        
; get mouse event from queue
; 
; inputs:
;  ax:dx address of struct mouse_event (ax offset, dx segment)
; ouputs:
;   ax 0 no event
;   ax !0 event
; destroys:
;  ax
;
; int mouse_get_event(struct mouse_event far* ev);
;
public mouse_get_event_
mouse_get_event_ PROC FAR

    push bx
    push cx
    push dx
    push si
    push di
    push es

    ; ax(offset):dx(segment) is struct to fill
    ; set es:di address of struct
    mov di, ax
    push dx
    pop es
    
    ; zero data structure 
    mov cx, SIZE mouse_event
    xor ax, ax
    push di
    cld
    rep stosb
    pop di

    ; check if any slots are active
    cli
    mov ax, [word ptr qactive]
    or ax, ax
    jz evexit
    
    dec ax
    mov [word ptr qactive], ax 
    
    ; set address of slot
    mov ax, [word ptr qstart]
    mov bx, SIZE mouse_event
    mul bx
    lea si, queue
    add si, ax
    
    ; qstart= (qstart+1) % QUEUE_SIZE
    mov ax, [word ptr qstart]
    inc ax
    cwd
    mov bx, QUEUE_SIZE
    div bx 
    mov [qstart], dx
    
    ; copy event into data structure
    ;mov ax, [ds:si].m_btn_state
    ;mov [es:di].m_btn_state, ax
    ;mov ax, [ds:si].m_curs_col
    ;mov [es:di].m_curs_col, ax
    ;mov ax, [ds:si].m_curs_row
    ;mov [es:di].m_curs_row, ax
    cld
    mov cx, 3
    rep movsw
    
    mov ax, 0FFFFh

evexit:
    sti
    
    pop es
    pop di
    pop si
    pop dx
    pop cx
    pop bx
    
    retf
mouse_get_event_ ENDP

; handle mouse interrupt
; place event in queue
; input:
;   ax condition mask causing call
;   bx button state
;   cx horizontal cursor position
;   dx vertical cursor position
;   di horizontal counts
;   si vertical counts
;   ds mouse driver segment
mouse_handler PROC FAR
; handler for mouse events
; store event in circular buffer queue

    push ax
    push ds
    
    mov ax, seg queue
    mov ds, ax
    
    ; insert into end of queue
    mov ax, [word ptr qend]
    push bx
    push dx
    mov bx, SIZE mouse_event
    mul bx
    pop dx
    pop bx
    lea si, queue
    add si, ax
    
    mov [word ptr si].m_btn_state, bx
    mov [word ptr si].m_curs_col, cx
    mov [word ptr si].m_curs_row, dx
    
    ; end = (end + 1) % QUEUE_SIZE;
    mov ax, [word ptr qend]
    inc ax
    cwd
    mov bx, QUEUE_SIZE
    div bx 
    mov [word ptr qend], dx
    
    ; test if we reached maximum capacity
    ; if qactive < QUEUE_SIZE) 
    ;    qactive++;
    ; else
    ;   qstart= (qstart + 1) % QUEUE_SIZE;
    mov ax, [word ptr qactive]
    cmp ax, QUEUE_SIZE
    jge hndoverflow
    inc ax
    mov [word ptr qactive], ax
    jmp hndexit
    
hndoverflow:    
    ; move start to the next oldest
    mov ax, [word ptr qstart]
    inc ax
    cwd
    mov bx, QUEUE_SIZE
    div bx 
    mov [word ptr qstart], dx
    jmp hndexit
    
hndexit:    

    pop ds
    pop ax
    
    retf
mouse_handler ENDP

; query if a mouse is present
; inputs:
;   none
; outputs:
;   ax -1  mouse not supported (driver not installed)
;   ax 0 mouse is installed
;   bx number of mouse buttons
; destroys: 
;   ax
mouse_query_has_mouse PROC FAR
;
; testing mouse presence
; 1. test interrupt vector 33H to see if it contains a value
;    other than zero. Zero indicates mouse driver is not installed.
; 2. Check if vector points to in IRET (cfh) instruction
; 3. Check for presence of mouse via int 33h

    push es

    ; get interrupt vector
    ; ah = 35
    ; al = interrupt vector to get
    ; returns:
    ; es:bx pointer to interrupt handler
    mov ah, 0035h
    mov al, 0033h
    int 0021h
    mov ax, es
    or  ax, ax
    jz  nomouse
    cmp byte ptr es:[bx], 0cfh
    jz  nomouse
    ; Reset/Query installed state
    ; AX = 0
    ; int 33h
    ; returns:
    ; AX= 0 mouse not installed
    ; AX= FFFFh mouse is installed
    ; BX= number of mouse buttons
    xor ax, ax
    int 033h
    or  ax, ax
    jz  nomouse
    xor ax, ax
    jmp qryexit
    
nomouse:
    mov ax, -1
    xor bx, bx
    
qryexit:

    pop es
    
    retf
mouse_query_has_mouse ENDP 

; initialize mouse 
;
; outputs:
;   ax -1  mouse not supported (driver not installed)
;   ax 0 mouse has been initialized
; destroys:
;   ax
;
; int mouse_init();
;
public mouse_init_
mouse_init_ PROC FAR

    push bx
    push cx
    push dx
    push es

    mov [word ptr qstart], 0
    mov [word ptr qend], 0
    mov [word ptr qactive], 0

    call mouse_query_has_mouse 
    or ax, ax
    jnz iniexit
    
    ; exchange interrupt routines
    mov ax, seg mouse_handler
    mov es, ax
    mov dx, offset mouse_handler
    mov cx, 000fh ; mask for all events
    mov ax, 0014h
    int 033h
  
    mov [word ptr saved_mask], cx
    mov [word ptr saved_routine_dx], dx
    mov [word ptr saved_routine_es], es
    mov [word ptr _mouse_initialized], 1
    xor ax, ax
   
iniexit:

    pop es
    pop dx
    pop cx
    pop bx
    
    retf
mouse_init_ ENDP

; deinitialize mouse
; inputs:
;   none
; outputs:
;   none
; destroys:
;   none
; 
public mouse_deinit_
mouse_deinit_ PROC FAR

    push ax
    push bx
    push cx
    push dx
    push es

    cmp [word ptr _mouse_initialized], 0
    jz dexit
    
    dosmouse_hide
    
    ; restore interrupt handler 
    mov cx, [word ptr saved_mask]
    mov dx, [word ptr saved_routine_dx]
    mov ax, [word ptr saved_routine_es]
    mov es, ax
    mov ax, 00ch
    int 033h
    
    mov [word ptr saved_mask], 0
    mov [word ptr saved_routine_dx], 0
    mov [word ptr saved_routine_es], 0
    mov [word ptr _mouse_initialized], 0
    
dexit:

    pop es
    pop dx
    pop cx
    pop bx
    pop ax
    
    retf
mouse_deinit_ ENDP

END