]> git.sur5r.net Git - cc65/blob - libsrc/atari/mou/atrst.s
Always print the mouse cursor, even if coordinates haven't changed.
[cc65] / libsrc / atari / mou / atrst.s
1 ;
2 ; Mouse driver for ST & Amiga mouses and Atari trakball.
3 ;
4 ; Original access routines: 05/07/2000 Freddy Offenga
5 ; Converted to driver: Christian Groessler, 2014-01-04
6 ;
7 ; Defines:
8 ;       AMIGA_MOUSE     -       builds Amiga mouse version
9 ;       TRAK_MOUSE      -       builds trakball version
10 ; If none of these defines are active, the ST mouse version
11 ; is being built.
12 ;
13
14         .include        "zeropage.inc"
15         .include        "mouse-kernel.inc"
16         .include        "atari.inc"
17
18         .macpack        generic
19
20 .if .not ( .defined (AMIGA_MOUSE) .or .defined (TRAK_MOUSE))
21         ST_MOUSE = 1
22 .endif
23
24 ; ------------------------------------------------------------------------
25 ; Header. Includes jump table
26
27 .segment        "JUMPTABLE"
28
29 HEADER:
30
31 ; Driver signature
32
33         .byte   $6d, $6f, $75           ; "mou"
34         .byte   MOUSE_API_VERSION       ; Mouse driver API version number
35
36 ; Library reference
37
38 libref: .addr   $0000
39
40 ; Jump table
41
42         .addr   INSTALL
43         .addr   UNINSTALL
44         .addr   HIDE
45         .addr   SHOW
46         .addr   SETBOX
47         .addr   GETBOX
48         .addr   MOVE
49         .addr   BUTTONS
50         .addr   POS
51         .addr   INFO
52         .addr   IOCTL
53         .addr   IRQ
54
55 ; Mouse driver flags
56
57         .byte   MOUSE_FLAG_LATE_IRQ
58
59 ; Callback table, set by the kernel before INSTALL is called
60
61 CHIDE:  jmp     $0000                   ; Hide the cursor
62 CSHOW:  jmp     $0000                   ; Show the cursor
63 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
64 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
65
66
67 ;----------------------------------------------------------------------------
68 ; Constants
69
70 SCREEN_HEIGHT   = 191
71 SCREEN_WIDTH    = 319
72
73 .enum   JOY
74         UP      = $01
75         DOWN    = $02
76         LEFT    = $04
77         RIGHT   = $08
78 .endenum
79
80 ;----------------------------------------------------------------------------
81 ; Global variables. The bounding box values are sorted so that they can be
82 ; written with the least effort in the SETBOX and GETBOX routines, so don't
83 ; reorder them.
84
85 .bss
86
87 Vars:
88 YPos:           .res    2               ; Current mouse position, Y
89 XPos:           .res    2               ; Current mouse position, X
90 XMin:           .res    2               ; X1 value of bounding box
91 YMin:           .res    2               ; Y1 value of bounding box
92 XMax:           .res    2               ; X2 value of bounding box
93 YMax:           .res    2               ; Y2 value of bounding box
94 Buttons:        .res    1               ; Button mask
95
96 XPosWrk:        .res    2
97 YPosWrk:        .res    2
98
99 visible:        .res    1
100
101 .if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE)
102 dumx:           .res    1
103 dumy:           .res    1
104 .endif
105
106 .ifdef TRAK_MOUSE
107 oldval:         .res    1
108 .endif
109
110 .ifndef __ATARIXL__
111 OldT1:          .res    2
112 .else
113
114 .data
115 set_VTIMR1_handler:
116                 .byte   $4C, 0, 0
117 .endif
118
119 .rodata
120
121 ; Default values for some of the above variables
122 ; (We use ".proc" because we want to define both a label and a scope.)
123
124 .proc   DefVars
125         .word   (SCREEN_HEIGHT+1)/2     ; YPos
126         .word   (SCREEN_WIDTH+1)/2      ; XPos
127         .word   0                       ; XMin
128         .word   0                       ; YMin
129         .word   SCREEN_WIDTH            ; XMax
130         .word   SCREEN_HEIGHT           ; YMax
131         .byte   0                       ; Buttons
132 .endproc
133
134 .ifdef ST_MOUSE
135
136 ; ST mouse lookup table
137
138 STTab:  .byte $FF,$01,$00,$01
139         .byte $00,$FF,$00,$01
140         .byte $01,$00,$FF,$00
141         .byte $01,$00,$01,$FF
142
143 .endif
144
145 .ifdef AMIGA_MOUSE
146
147 ; Amiga mouse lookup table
148
149 AmiTab: .byte $FF,$01,$00,$FF
150         .byte $00,$FF,$FF,$01
151         .byte $01,$FF,$FF,$00
152         .byte $FF,$00,$01,$FF
153
154 .endif
155
156 .code
157
158 ;----------------------------------------------------------------------------
159 ; INSTALL routine. Is called after the driver is loaded into memory. If
160 ; possible, check if the hardware is present.
161 ; Must return an MOUSE_ERR_xx code in a/x.
162
163 INSTALL:
164
165 ; Initialize variables. Just copy the default stuff over
166
167         ldx     #.sizeof(DefVars)-1
168 @L1:    lda     DefVars,x
169         sta     Vars,x
170         dex
171         bpl     @L1
172
173 ; Be sure the mouse cursor is invisible and at the default location.
174
175         jsr     CHIDE
176         lda     XPos
177         sta     XPosWrk
178         ldx     XPos+1
179         stx     XPosWrk+1
180         jsr     CMOVEX
181         lda     YPos
182         sta     YPosWrk
183         ldx     YPos+1
184         stx     YPosWrk+1
185         jsr     CMOVEY
186
187 ; Install timer irq routine to poll mouse.
188
189 .ifdef __ATARIXL__
190
191         ; Setup pointer to wrapper install/deinstall function.
192         lda     libref
193         sta     set_VTIMR1_handler+1
194         lda     libref+1
195         sta     set_VTIMR1_handler+2
196
197         ; Install my handler.
198         sec
199         lda     #<T1Han
200         ldx     #>T1Han
201         jsr     set_VTIMR1_handler
202
203 .else
204
205         lda     VTIMR1
206         sta     OldT1
207         lda     VTIMR1+1
208         sta     OldT1+1
209
210         php
211         sei
212         lda     #<T1Han
213         sta     VTIMR1
214         lda     #>T1Han
215         sta     VTIMR1+1
216         plp
217
218 .endif
219
220         lda     #%00000001
221         sta     AUDCTL
222
223         lda     #0
224         sta     AUDC1
225
226         lda     #15
227         sta     AUDF1
228         sta     STIMER
229
230         lda     POKMSK
231         ora     #%00000001              ; timer 1 enable
232         sta     POKMSK
233         sta     IRQEN
234
235 ; Done, return zero (= MOUSE_ERR_OK)
236
237         ldx     #$00
238         txa
239         rts
240
241 ;----------------------------------------------------------------------------
242 ; UNINSTALL routine. Is called before the driver is removed from memory.
243 ; No return code required (the driver is removed from memory on return).
244
245 UNINSTALL:
246
247 ; uninstall timer irq routine
248
249         lda     POKMSK
250         and     #%11111110              ; timer 1 disable
251         sta     IRQEN
252         sta     POKMSK
253
254 .ifdef __ATARIXL__
255
256         clc
257         jsr     set_VTIMR1_handler
258
259 .else
260
261         php
262         sei
263         lda     OldT1
264         sta     VTIMR1
265         lda     OldT1+1
266         sta     VTIMR1+1
267         plp
268
269 .endif
270         ; fall thru...
271
272 ;----------------------------------------------------------------------------
273 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
274 ; a counter for calls to show/hide, and the driver entry point is only called
275 ; if the mouse is currently visible and should get hidden. For most drivers,
276 ; no special action is required besides hiding the mouse cursor.
277 ; No return code required.
278
279 HIDE:   dec     visible
280         php
281         sei
282         jsr     CHIDE
283         plp
284         rts
285
286 ;----------------------------------------------------------------------------
287 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
288 ; a counter for calls to show/hide, and the driver entry point is only called
289 ; if the mouse is currently hidden and should become visible. For most drivers,
290 ; no special action is required besides enabling the mouse cursor.
291 ; No return code required.
292
293 SHOW:   inc     visible
294         php
295         sei
296         jsr     CSHOW
297         plp
298         rts
299
300 ;----------------------------------------------------------------------------
301 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
302 ; from the C program, that is, a pointer to a mouse_box struct in a/x.
303 ; No checks are done if the mouse is currently inside the box, this is the job
304 ; of the caller. It is not necessary to validate the parameters, trust the
305 ; caller and save some code here. No return code required.
306
307 SETBOX: sta     ptr1
308         stx     ptr1+1                  ; Save data pointer
309
310         ldy     #.sizeof (MOUSE_BOX)-1
311         php
312         sei
313
314 @L1:    lda     (ptr1),y
315         sta     XMin,y
316         dey
317         bpl     @L1
318
319         plp
320         rts
321
322 ;----------------------------------------------------------------------------
323 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
324 ; come from the C program, that is, a pointer to a mouse_box struct in a/x.
325
326 GETBOX: sta     ptr1
327         stx     ptr1+1                  ; Save data pointer
328
329         ldy     #.sizeof (MOUSE_BOX)-1
330         php
331         sei
332
333 @L1:    lda     XMin,y
334         sta     (ptr1),y
335         dey
336         bpl     @L1
337
338         plp
339         rts
340
341 ;----------------------------------------------------------------------------
342 ; MOVE: Move the mouse to a new position. The position is passed as it comes
343 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
344 ; remove the parameter from the stack on return.
345 ; No checks are done if the new position is valid (within the bounding box or
346 ; the screen). No return code required.
347 ;
348
349 MOVE:   php
350         sei                             ; No interrupts
351
352         pha
353         txa
354         pha
355
356         lda     visible
357         beq     @L01
358
359         jsr     CHIDE
360
361 @L01:   pla
362         tax
363         pla
364
365         sta     YPos
366         sta     YPosWrk
367         stx     YPos+1                  ; New Y position
368         stx     YPosWrk+1
369         jsr     CMOVEY                  ; Set it
370
371         ldy     #$01
372         lda     (sp),y
373         sta     XPos+1
374         sta     XPosWrk+1
375         tax
376         dey
377         lda     (sp),y
378         sta     XPos                    ; New X position
379         sta     XPosWrk
380
381         jsr     CMOVEX                  ; Move the cursor
382
383         lda     visible
384         beq     @Ret
385
386         jsr     CSHOW
387
388 @Ret:   plp                             ; Restore interrupt flag
389         rts
390
391 ;----------------------------------------------------------------------------
392 ; BUTTONS: Return the button mask in a/x.
393
394 BUTTONS:
395         lda     Buttons
396         ldx     #$00
397         rts
398
399 ;----------------------------------------------------------------------------
400 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
401 ; No return code required.
402
403 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
404
405         php
406         sei                             ; Disable interrupts
407         lda     XPos                    ; Transfer the position
408         sta     (ptr1),y
409         lda     XPos+1
410         iny
411         sta     (ptr1),y
412         lda     YPos
413         iny
414         sta     (ptr1),y
415         lda     YPos+1
416         plp                             ; Restore interrupt flag
417
418         iny
419         sta     (ptr1),y                ; Store last byte
420
421         rts                             ; Done
422
423 ;----------------------------------------------------------------------------
424 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
425 ; struct pointed to by ptr1. No return code required.
426 ;
427 ; We're cheating here to keep the code smaller: The first fields of the
428 ; mouse_info struct are identical to the mouse_pos struct, so we will just
429 ; call _mouse_pos to initialize the struct pointer and fill the position
430 ; fields.
431
432 INFO:   jsr     POS
433
434 ; Fill in the button state
435
436         lda     Buttons
437         ldy     #MOUSE_INFO::BUTTONS
438         sta     (ptr1),y
439
440         rts
441
442 ;----------------------------------------------------------------------------
443 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
444 ; specific data in ptr1, and the ioctl code in A.
445 ; Must return an error code in a/x.
446 ;
447
448 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
449         ldx     #>MOUSE_ERR_INV_IOCTL
450         rts
451
452 ;----------------------------------------------------------------------------
453 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
454 ; (so be careful). The routine MUST return carry set if the interrupt has been
455 ; 'handled' - which means that the interrupt source is gone. Otherwise it
456 ; MUST return carry clear.
457 ;
458
459 IRQ:
460
461 ; Check for a pressed button and place the result into Buttons
462
463         ldx     #0
464         lda     TRIG0                   ; joystick #0 trigger
465         bne     @L0                     ; not pressed
466         ldx     #MOUSE_BTN_LEFT
467 @L0:    stx     Buttons
468
469         ldx     visible
470         beq     @L1
471         jsr     CHIDE
472
473 ; Limit the X coordinate to the bounding box
474
475 @L1:    lda     XPosWrk+1
476         ldy     XPosWrk
477         tax
478         cpy     XMin
479         sbc     XMin+1
480         bpl     @L2
481         ldy     XMin
482         ldx     XMin+1
483         jmp     @L3
484 @L2:    txa
485
486         cpy     XMax
487         sbc     XMax+1
488         bmi     @L3
489         ldy     XMax
490         ldx     XMax+1
491 @L3:    sty     XPos
492         stx     XPos+1
493
494         tya
495         jsr     CMOVEX
496
497 ; Limit the Y coordinate to the bounding box
498
499         lda     YPosWrk+1
500         ldy     YPosWrk
501         tax
502         cpy     YMin
503         sbc     YMin+1
504         bpl     @L4
505         ldy     YMin
506         ldx     YMin+1
507         jmp     @L5
508 @L4:    txa
509
510         cpy     YMax
511         sbc     YMax+1
512         bmi     @L5
513         ldy     YMax
514         ldx     YMax+1
515 @L5:    sty     YPos
516         stx     YPos+1
517
518         tya
519         jsr     CMOVEY
520
521         ldx     visible
522         beq     @Done
523
524         jsr     CSHOW
525
526 @Done:  clc
527         rts
528
529 ;----------------------------------------------------------------------------
530 ; T1Han: Local IRQ routine to poll mouse
531 ;
532
533 T1Han:  tya
534         pha
535         txa
536         pha
537
538 .ifdef DEBUG
539         lda     RANDOM
540         sta     COLBK
541 .endif
542
543         lda     PORTA
544         tay
545
546 .ifdef ST_MOUSE
547
548 ; ST mouse version
549
550         and     #%00000011
551         ora     dumx
552         tax
553         lda     STTab,x
554         bmi     nxst
555
556         beq     xist
557
558         dec     XPosWrk
559         lda     XPosWrk
560         cmp     #255
561         bne     nxst
562         dec     XPosWrk+1
563         jmp     nxst
564
565 xist:   inc     XPosWrk
566         bne     nxst
567         inc     XPosWrk+1
568
569 nxst:   tya
570         and     #%00001100
571         ora     dumy
572         tax
573         lda     STTab,x
574         bmi     nyst
575
576         bne     yst
577
578         dec     YPosWrk
579         lda     YPosWrk
580         cmp     #255
581         bne     nyst
582         dec     YPosWrk+1
583         jmp     nyst
584
585 yst:    inc     YPosWrk
586         bne     nyst
587         inc     YPosWrk+1
588
589 ; store old readings
590
591 nyst:   tya
592         and     #%00000011
593         asl
594         asl
595         sta     dumx
596         tya
597         and     #%00001100
598         lsr
599         lsr
600         sta     dumy
601
602 .elseif .defined (AMIGA_MOUSE)
603
604 ; Amiga mouse version
605
606         lsr
607         and     #%00000101
608         ora     dumx
609         tax
610         lda     AmiTab,x
611         bmi     nxami
612
613         bne     xiami
614
615         dec     XPosWrk
616         lda     XPosWrk
617         cmp     #255
618         bne     nxami
619         dec     XPosWrk+1
620         jmp     nxami
621
622 xiami:  inc     XPosWrk
623         bne     nxami
624         inc     XPosWrk+1
625
626 nxami:  tya
627
628         and     #%00000101
629         ora     dumy
630         tax
631         lda     AmiTab,x
632         bmi     nyami
633
634         bne     yiami
635
636         dec     YPosWrk
637         lda     YPosWrk
638         cmp     #255
639         bne     nyami
640         dec     YPosWrk+1
641         jmp     nyami
642
643 yiami:  inc     YPosWrk
644         bne     nyami
645         inc     YPosWrk+1
646
647 ; store old readings
648
649 nyami:  tya
650         and     #%00001010
651         sta     dumx
652         tya
653         and     #%00000101
654         asl
655         sta     dumy
656
657 .elseif .defined (TRAK_MOUSE)
658
659 ; trakball version
660
661         eor     oldval
662         and     #%00001000
663         beq     horiz
664
665         tya
666         and     #%00000100
667         beq     mmup
668
669         inc     YPosWrk
670         bne     horiz
671         inc     YPosWrk+1
672         bne     horiz
673
674 mmup:   dec     YPosWrk
675         lda     YPosWrk
676         cmp     #255
677         bne     horiz
678         dec     YPosWrk+1
679
680 horiz:  tya
681         eor     oldval
682         and     #%00000010
683         beq     mmexit
684
685         tya
686         and     #%00000001
687         beq     mmleft
688
689         inc     XPosWrk
690         bne     mmexit
691         inc     XPosWrk+1
692         bne     mmexit
693
694 mmleft: dec     XPosWrk
695         lda     XPosWrk
696         cmp     #255
697         bne     mmexit
698         dec     XPosWrk+1
699
700 mmexit: sty     oldval
701
702 .endif
703
704         pla
705         tax
706         pla
707         tay
708 .ifdef  __ATARIXL__
709         rts
710 .else
711         pla
712         rti
713 .endif