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