]> git.sur5r.net Git - cc65/blob - libsrc/atari/mou/atrst.s
773e171e1edb4b24756e7010a11ef744facf9dd3
[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 CPREP:  jmp     $0000                   ; Prepare to move the cursor
64 CDRAW:  jmp     $0000                   ; Draw the cursor
65 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
66 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
67
68
69 ;----------------------------------------------------------------------------
70 ; Constants
71
72 SCREEN_HEIGHT   = 191
73 SCREEN_WIDTH    = 319
74
75 .enum   JOY
76         UP      = $01
77         DOWN    = $02
78         LEFT    = $04
79         RIGHT   = $08
80 .endenum
81
82 ;----------------------------------------------------------------------------
83 ; Global variables. The bounding box values are sorted so that they can be
84 ; written with the least effort in the SETBOX and GETBOX routines, so don't
85 ; reorder them.
86
87 .bss
88
89 Vars:
90 YPos:           .res    2               ; Current mouse position, Y
91 XPos:           .res    2               ; Current mouse position, X
92 XMin:           .res    2               ; X1 value of bounding box
93 YMin:           .res    2               ; Y1 value of bounding box
94 XMax:           .res    2               ; X2 value of bounding box
95 YMax:           .res    2               ; Y2 value of bounding box
96 Buttons:        .res    1               ; Button mask
97
98 XPosWrk:        .res    2
99 YPosWrk:        .res    2
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 ; Make sure the mouse cursor is at the default location.
174
175         lda     XPos
176         sta     XPosWrk
177         ldx     XPos+1
178         stx     XPosWrk+1
179         jsr     CMOVEX
180         lda     YPos
181         sta     YPosWrk
182         ldx     YPos+1
183         stx     YPosWrk+1
184         jsr     CMOVEY
185
186 ; Install timer irq routine to poll mouse.
187
188 .ifdef __ATARIXL__
189
190         ; Setup pointer to wrapper install/deinstall function.
191         lda     libref
192         sta     set_VTIMR1_handler+1
193         lda     libref+1
194         sta     set_VTIMR1_handler+2
195
196         ; Install my handler.
197         sec
198         lda     #<T1Han
199         ldx     #>T1Han
200         jsr     set_VTIMR1_handler
201
202 .else
203
204         lda     VTIMR1
205         sta     OldT1
206         lda     VTIMR1+1
207         sta     OldT1+1
208
209         php
210         sei
211         lda     #<T1Han
212         sta     VTIMR1
213         lda     #>T1Han
214         sta     VTIMR1+1
215         plp
216
217 .endif
218
219         lda     #%00000001
220         sta     AUDCTL
221
222         lda     #0
223         sta     AUDC1
224
225         lda     #15
226         sta     AUDF1
227         sta     STIMER
228
229         lda     POKMSK
230         ora     #%00000001              ; timer 1 enable
231         sta     POKMSK
232         sta     IRQEN
233
234 ; Done, return zero (= MOUSE_ERR_OK)
235
236         ldx     #$00
237         txa
238         rts
239
240 ;----------------------------------------------------------------------------
241 ; UNINSTALL routine. Is called before the driver is removed from memory.
242 ; No return code required (the driver is removed from memory on return).
243
244 UNINSTALL:
245
246 ; uninstall timer irq routine
247
248         lda     POKMSK
249         and     #%11111110              ; timer 1 disable
250         sta     IRQEN
251         sta     POKMSK
252
253 .ifdef __ATARIXL__
254
255         clc
256         jsr     set_VTIMR1_handler
257
258 .else
259
260         php
261         sei
262         lda     OldT1
263         sta     VTIMR1
264         lda     OldT1+1
265         sta     VTIMR1+1
266         plp
267
268 .endif
269         ; fall thru...
270
271 ;----------------------------------------------------------------------------
272 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
273 ; a counter for calls to show/hide, and the driver entry point is only called
274 ; if the mouse is currently visible and should get hidden. For most drivers,
275 ; no special action is required besides hiding the mouse cursor.
276 ; No return code required.
277
278 HIDE:   php
279         sei
280         jsr     CHIDE
281         plp
282         rts
283
284 ;----------------------------------------------------------------------------
285 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
286 ; a counter for calls to show/hide, and the driver entry point is only called
287 ; if the mouse is currently hidden and should become visible. For most drivers,
288 ; no special action is required besides enabling the mouse cursor.
289 ; No return code required.
290
291 SHOW:   php
292         sei
293         jsr     CSHOW
294         plp
295         rts
296
297 ;----------------------------------------------------------------------------
298 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
299 ; from the C program, that is, a pointer to a mouse_box struct in a/x.
300 ; No checks are done if the mouse is currently inside the box, this is the job
301 ; of the caller. It is not necessary to validate the parameters, trust the
302 ; caller and save some code here. No return code required.
303
304 SETBOX: sta     ptr1
305         stx     ptr1+1                  ; Save data pointer
306
307         ldy     #.sizeof (MOUSE_BOX)-1
308         php
309         sei
310
311 @L1:    lda     (ptr1),y
312         sta     XMin,y
313         dey
314         bpl     @L1
315
316         plp
317         rts
318
319 ;----------------------------------------------------------------------------
320 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
321 ; come from the C program, that is, a pointer to a mouse_box struct in a/x.
322
323 GETBOX: sta     ptr1
324         stx     ptr1+1                  ; Save data pointer
325
326         ldy     #.sizeof (MOUSE_BOX)-1
327         php
328         sei
329
330 @L1:    lda     XMin,y
331         sta     (ptr1),y
332         dey
333         bpl     @L1
334
335         plp
336         rts
337
338 ;----------------------------------------------------------------------------
339 ; MOVE: Move the mouse to a new position. The position is passed as it comes
340 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
341 ; remove the parameter from the stack on return.
342 ; No checks are done if the new position is valid (within the bounding box or
343 ; the screen). No return code required.
344 ;
345
346 MOVE:   php
347         sei                             ; No interrupts
348
349         pha
350         txa
351         pha
352         jsr     CPREP
353         pla
354         tax
355         pla
356
357         sta     YPos
358         sta     YPosWrk
359         stx     YPos+1                  ; New Y position
360         stx     YPosWrk+1
361         jsr     CMOVEY                  ; Set it
362
363         ldy     #$01
364         lda     (sp),y
365         sta     XPos+1
366         sta     XPosWrk+1
367         tax
368         dey
369         lda     (sp),y
370         sta     XPos                    ; New X position
371         sta     XPosWrk
372         jsr     CMOVEX                  ; Move the cursor
373
374         jsr     CDRAW
375
376         plp                             ; Restore interrupt flag
377         rts
378
379 ;----------------------------------------------------------------------------
380 ; BUTTONS: Return the button mask in a/x.
381
382 BUTTONS:
383         lda     Buttons
384         ldx     #$00
385         rts
386
387 ;----------------------------------------------------------------------------
388 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
389 ; No return code required.
390
391 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
392
393         php
394         sei                             ; Disable interrupts
395         lda     XPos                    ; Transfer the position
396         sta     (ptr1),y
397         lda     XPos+1
398         iny
399         sta     (ptr1),y
400         lda     YPos
401         iny
402         sta     (ptr1),y
403         lda     YPos+1
404         plp                             ; Restore interrupt flag
405
406         iny
407         sta     (ptr1),y                ; Store last byte
408
409         rts                             ; Done
410
411 ;----------------------------------------------------------------------------
412 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
413 ; struct pointed to by ptr1. No return code required.
414 ;
415 ; We're cheating here to keep the code smaller: The first fields of the
416 ; mouse_info struct are identical to the mouse_pos struct, so we will just
417 ; call _mouse_pos to initialize the struct pointer and fill the position
418 ; fields.
419
420 INFO:   jsr     POS
421
422 ; Fill in the button state
423
424         lda     Buttons
425         ldy     #MOUSE_INFO::BUTTONS
426         sta     (ptr1),y
427
428         rts
429
430 ;----------------------------------------------------------------------------
431 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
432 ; specific data in ptr1, and the ioctl code in A.
433 ; Must return an error code in a/x.
434 ;
435
436 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
437         ldx     #>MOUSE_ERR_INV_IOCTL
438         rts
439
440 ;----------------------------------------------------------------------------
441 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
442 ; (so be careful). The routine MUST return carry set if the interrupt has been
443 ; 'handled' - which means that the interrupt source is gone. Otherwise it
444 ; MUST return carry clear.
445 ;
446
447 IRQ:
448
449 ; Turn mouse polling IRQ back on in case it disabled itself due to CRITIC
450 ; flag being set.
451
452         lda     POKMSK
453         ora     #%00000001              ; timer 1 enable
454         sta     POKMSK
455         sta     IRQEN
456
457 ; Check for a pressed button and place the result into Buttons
458
459         ldx     #0
460         lda     TRIG0                   ; joystick #0 trigger
461         bne     @L0                     ; not pressed
462         ldx     #MOUSE_BTN_LEFT
463 @L0:    stx     Buttons
464
465         jsr     CPREP
466
467 ; Limit the X coordinate to the bounding box
468
469         lda     XPosWrk+1
470         ldy     XPosWrk
471         tax
472         cpy     XMin
473         sbc     XMin+1
474         bpl     @L2
475         ldy     XMin
476         ldx     XMin+1
477         jmp     @L3
478 @L2:    txa
479
480         cpy     XMax
481         sbc     XMax+1
482         bmi     @L3
483         ldy     XMax
484         ldx     XMax+1
485 @L3:    sty     XPos
486         stx     XPos+1
487
488         tya
489         jsr     CMOVEX
490
491 ; Limit the Y coordinate to the bounding box
492
493         lda     YPosWrk+1
494         ldy     YPosWrk
495         tax
496         cpy     YMin
497         sbc     YMin+1
498         bpl     @L4
499         ldy     YMin
500         ldx     YMin+1
501         jmp     @L5
502 @L4:    txa
503
504         cpy     YMax
505         sbc     YMax+1
506         bmi     @L5
507         ldy     YMax
508         ldx     YMax+1
509 @L5:    sty     YPos
510         stx     YPos+1
511
512         tya
513         jsr     CMOVEY
514
515         jsr     CDRAW
516
517         clc
518         rts
519
520
521 ;----------------------------------------------------------------------------
522 ; T1Han: Local IRQ routine to poll mouse
523 ;
524
525 T1Han:  lda     CRITIC                  ; if CRITIC flag is set, disable the
526         bne     disable_me              ; high frequency polling IRQ, in order
527                                         ; not to interfere with SIO I/O (e.g.
528                                         ; floppy access)
529
530         tya
531         pha
532         txa
533         pha
534
535 .ifdef DEBUG
536         lda     RANDOM
537         sta     COLBK
538 .endif
539
540         lda     PORTA
541         tay
542
543 .ifdef ST_MOUSE
544
545 ; ST mouse version
546
547         and     #%00000011
548         ora     dumx
549         tax
550         lda     STTab,x
551         bmi     nxst
552
553         beq     xist
554
555         dec     XPosWrk
556         lda     XPosWrk
557         cmp     #255
558         bne     nxst
559         dec     XPosWrk+1
560         jmp     nxst
561
562 xist:   inc     XPosWrk
563         bne     nxst
564         inc     XPosWrk+1
565
566 nxst:   tya
567         and     #%00001100
568         ora     dumy
569         tax
570         lda     STTab,x
571         bmi     nyst
572
573         bne     yst
574
575         dec     YPosWrk
576         lda     YPosWrk
577         cmp     #255
578         bne     nyst
579         dec     YPosWrk+1
580         jmp     nyst
581
582 yst:    inc     YPosWrk
583         bne     nyst
584         inc     YPosWrk+1
585
586 ; store old readings
587
588 nyst:   tya
589         and     #%00000011
590         asl
591         asl
592         sta     dumx
593         tya
594         and     #%00001100
595         lsr
596         lsr
597         sta     dumy
598
599 .elseif .defined (AMIGA_MOUSE)
600
601 ; Amiga mouse version
602
603         lsr
604         and     #%00000101
605         ora     dumx
606         tax
607         lda     AmiTab,x
608         bmi     nxami
609
610         bne     xiami
611
612         dec     XPosWrk
613         lda     XPosWrk
614         cmp     #255
615         bne     nxami
616         dec     XPosWrk+1
617         jmp     nxami
618
619 xiami:  inc     XPosWrk
620         bne     nxami
621         inc     XPosWrk+1
622
623 nxami:  tya
624
625         and     #%00000101
626         ora     dumy
627         tax
628         lda     AmiTab,x
629         bmi     nyami
630
631         bne     yiami
632
633         dec     YPosWrk
634         lda     YPosWrk
635         cmp     #255
636         bne     nyami
637         dec     YPosWrk+1
638         jmp     nyami
639
640 yiami:  inc     YPosWrk
641         bne     nyami
642         inc     YPosWrk+1
643
644 ; store old readings
645
646 nyami:  tya
647         and     #%00001010
648         sta     dumx
649         tya
650         and     #%00000101
651         asl
652         sta     dumy
653
654 .elseif .defined (TRAK_MOUSE)
655
656 ; trakball version
657
658         eor     oldval
659         and     #%00001000
660         beq     horiz
661
662         tya
663         and     #%00000100
664         beq     mmup
665
666         inc     YPosWrk
667         bne     horiz
668         inc     YPosWrk+1
669         bne     horiz
670
671 mmup:   dec     YPosWrk
672         lda     YPosWrk
673         cmp     #255
674         bne     horiz
675         dec     YPosWrk+1
676
677 horiz:  tya
678         eor     oldval
679         and     #%00000010
680         beq     mmexit
681
682         tya
683         and     #%00000001
684         beq     mmleft
685
686         inc     XPosWrk
687         bne     mmexit
688         inc     XPosWrk+1
689         bne     mmexit
690
691 mmleft: dec     XPosWrk
692         lda     XPosWrk
693         cmp     #255
694         bne     mmexit
695         dec     XPosWrk+1
696
697 mmexit: sty     oldval
698
699 .endif
700
701         pla
702         tax
703         pla
704         tay
705 .ifdef  __ATARIXL__
706         rts
707 .else
708         pla
709         rti
710 .endif
711
712
713 ; Disable the interrupt source which caused us to be called.
714 ; The interrupt will be enabled again by the "IRQ" routine.
715 ; The "IRQ" routine, despite its name, is called from the
716 ; vertical blank NMI interrupt *only* if the CRITIC flag has
717 ; been cleared.
718
719 disable_me:
720         lda     POKMSK
721         and     #%11111110              ; timer 1 disable
722         sta     IRQEN
723         sta     POKMSK
724 .ifdef  __ATARIXL__
725         rts
726 .else
727         pla
728         rti
729 .endif