]> git.sur5r.net Git - cc65/blob - libsrc/atari/mou/atrtt.s
Atari, Atari5200: disable "attract mode" on mouse or joystick input
[cc65] / libsrc / atari / mou / atrtt.s
1 ;
2 ; Mouse driver for Atari Touch Tablet
3 ;
4 ; Christian Groessler, 2014-01-05
5 ;
6
7         .include        "zeropage.inc"
8         .include        "mouse-kernel.inc"
9         .include        "atari.inc"
10
11         .macpack        generic
12         .macpack        module
13
14 ; ------------------------------------------------------------------------
15 ; Header. Includes jump table
16
17 .ifdef __ATARIXL__
18         module_header   _atrxtt_mou
19 .else
20         module_header   _atrtt_mou
21 .endif
22
23 HEADER:
24
25 ; Driver signature
26
27         .byte   $6d, $6f, $75           ; "mou"
28         .byte   MOUSE_API_VERSION       ; Mouse driver API version number
29
30 ; Library reference
31
32         .addr   $0000
33
34 ; Jump table
35
36         .addr   INSTALL
37         .addr   UNINSTALL
38         .addr   HIDE
39         .addr   SHOW
40         .addr   SETBOX
41         .addr   GETBOX
42         .addr   MOVE
43         .addr   BUTTONS
44         .addr   POS
45         .addr   INFO
46         .addr   IOCTL
47         .addr   IRQ
48
49 ; Mouse driver flags
50
51         .byte   MOUSE_FLAG_LATE_IRQ
52
53 ; Callback table, set by the kernel before INSTALL is called
54
55 CHIDE:  jmp     $0000                   ; Hide the cursor
56 CSHOW:  jmp     $0000                   ; Show the cursor
57 CPREP:  jmp     $0000                   ; Prepare to move the cursor
58 CDRAW:  jmp     $0000                   ; Draw the cursor
59 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
60 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
61
62
63 ;----------------------------------------------------------------------------
64 ; Constants
65
66 SCREEN_HEIGHT   = 191
67 SCREEN_WIDTH    = 319
68
69 .enum   JOY
70         UP      = $01
71         DOWN    = $02
72         LEFT    = $04
73         RIGHT   = $08
74 .endenum
75
76 ;----------------------------------------------------------------------------
77 ; Global variables. The bounding box values are sorted so that they can be
78 ; written with the least effort in the SETBOX and GETBOX routines, so don't
79 ; reorder them.
80
81 .bss
82
83 Vars:
84 YPos:           .res    2               ; Current mouse position, Y
85 XPos:           .res    2               ; Current mouse position, X
86 XMin:           .res    2               ; X1 value of bounding box
87 YMin:           .res    2               ; Y1 value of bounding box
88 XMax:           .res    2               ; X2 value of bounding box
89 YMax:           .res    2               ; Y2 value of bounding box
90 Buttons:        .res    1               ; Button mask
91 OldButton:      .res    1               ; previous buttons
92
93 ; Default values for above variables
94
95 .rodata
96
97 ; (We use ".proc" because we want to define both a label and a scope.)
98
99 .proc   DefVars
100         .word   SCREEN_HEIGHT/2         ; YPos
101         .word   SCREEN_WIDTH/2          ; XPos
102         .word   0                       ; XMin
103         .word   0                       ; YMin
104         .word   SCREEN_WIDTH            ; XMax
105         .word   SCREEN_HEIGHT           ; YMax
106         .byte   0                       ; Buttons
107 .endproc
108
109 .code
110
111 ;----------------------------------------------------------------------------
112 ; INSTALL routine. Is called after the driver is loaded into memory. If
113 ; possible, check if the hardware is present.
114 ; Must return an MOUSE_ERR_xx code in a/x.
115
116 INSTALL:
117
118 ; Initialize variables. Just copy the default stuff over
119
120         ldx     #.sizeof(DefVars)-1
121 @L1:    lda     DefVars,x
122         sta     Vars,x
123         dex
124         bpl     @L1
125
126 ; Make sure the mouse cursor is at the default location.
127
128         lda     XPos
129         ldx     XPos+1
130         jsr     CMOVEX
131         lda     YPos
132         ldx     YPos+1
133         jsr     CMOVEY
134
135 ; Done, return zero (= MOUSE_ERR_OK)
136
137         ldx     #$00
138         txa
139         rts
140
141 ;----------------------------------------------------------------------------
142 ; UNINSTALL routine. Is called before the driver is removed from memory.
143 ; No return code required (the driver is removed from memory on return).
144
145 UNINSTALL       = HIDE                  ; Hide cursor on exit
146
147 ;----------------------------------------------------------------------------
148 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
149 ; a counter for calls to show/hide, and the driver entry point is only called
150 ; if the mouse is currently visible and should get hidden. For most drivers,
151 ; no special action is required besides hiding the mouse cursor.
152 ; No return code required.
153
154 HIDE:   php
155         sei
156         jsr     CHIDE
157         plp
158         rts
159
160 ;----------------------------------------------------------------------------
161 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
162 ; a counter for calls to show/hide, and the driver entry point is only called
163 ; if the mouse is currently hidden and should become visible. For most drivers,
164 ; no special action is required besides enabling the mouse cursor.
165 ; No return code required.
166
167 SHOW:   php
168         sei
169         jsr     CSHOW
170         plp
171         rts
172
173 ;----------------------------------------------------------------------------
174 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
175 ; from the C program, that is, a pointer to a mouse_box struct in a/x.
176 ; No checks are done if the mouse is currently inside the box, this is the job
177 ; of the caller. It is not necessary to validate the parameters, trust the
178 ; caller and save some code here. No return code required.
179
180 SETBOX: sta     ptr1
181         stx     ptr1+1                  ; Save data pointer
182
183         ldy     #.sizeof (MOUSE_BOX)-1
184         php
185         sei
186
187 @L1:    lda     (ptr1),y
188         sta     XMin,y
189         dey
190         bpl     @L1
191
192         plp
193         rts
194
195 ;----------------------------------------------------------------------------
196 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
197 ; come from the C program, that is, a pointer to a mouse_box struct in a/x.
198
199 GETBOX: sta     ptr1
200         stx     ptr1+1                  ; Save data pointer
201
202         ldy     #.sizeof (MOUSE_BOX)-1
203         php
204         sei
205
206 @L1:    lda     XMin,y
207         sta     (ptr1),y
208         dey
209         bpl     @L1
210
211         plp
212         rts
213
214 ;----------------------------------------------------------------------------
215 ; MOVE: Move the mouse to a new position. The position is passed as it comes
216 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
217 ; remove the parameter from the stack on return.
218 ; No checks are done if the new position is valid (within the bounding box or
219 ; the screen). No return code required.
220 ;
221
222 MOVE:   php
223         sei                             ; No interrupts
224
225         pha
226         txa
227         pha
228         jsr     CPREP
229         pla
230         tax
231         pla
232
233         sta     YPos
234         stx     YPos+1                  ; New Y position
235         jsr     CMOVEY                  ; Set it
236
237         ldy     #$01
238         lda     (sp),y
239         sta     XPos+1
240         tax
241         dey
242         lda     (sp),y
243         sta     XPos                    ; New X position
244         jsr     CMOVEX                  ; Move the cursor
245
246         jsr     CSHOW
247
248         plp                             ; Restore interrupt flag
249         rts
250
251 ;----------------------------------------------------------------------------
252 ; BUTTONS: Return the button mask in a/x.
253
254 BUTTONS:
255         lda     Buttons
256         ldx     #$00
257         rts
258
259 ;----------------------------------------------------------------------------
260 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
261 ; No return code required.
262
263 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
264
265         php
266         sei                             ; Disable interrupts
267         lda     XPos                    ; Transfer the position
268         sta     (ptr1),y
269         lda     XPos+1
270         iny
271         sta     (ptr1),y
272         lda     YPos
273         iny
274         sta     (ptr1),y
275         lda     YPos+1
276         plp                             ; Restore interrupt flag
277
278         iny
279         sta     (ptr1),y                ; Store last byte
280
281         rts                             ; Done
282
283 ;----------------------------------------------------------------------------
284 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
285 ; struct pointed to by ptr1. No return code required.
286 ;
287 ; We're cheating here to keep the code smaller: The first fields of the
288 ; mouse_info struct are identical to the mouse_pos struct, so we will just
289 ; call _mouse_pos to initialize the struct pointer and fill the position
290 ; fields.
291
292 INFO:   jsr     POS
293
294 ; Fill in the button state
295
296         lda     Buttons
297         ldy     #MOUSE_INFO::BUTTONS
298         sta     (ptr1),y
299
300         rts
301
302 ;----------------------------------------------------------------------------
303 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
304 ; specific data in ptr1, and the ioctl code in A.
305 ; Must return an error code in a/x.
306 ;
307
308 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
309         ldx     #>MOUSE_ERR_INV_IOCTL
310         rts
311
312 ;----------------------------------------------------------------------------
313 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
314 ; (so be careful). The routine MUST return carry set if the interrupt has been
315 ; 'handled' - which means that the interrupt source is gone. Otherwise it
316 ; MUST return carry clear.
317 ;
318
319 IRQ:
320
321 ; Check for a pressed button and place the result into Buttons
322
323         ldx     #0
324         stx     Buttons
325
326         lda     PORTA                   ; get other buttons
327         eor     #255
328         tax
329         and     #5                      ; pen button and left button are mapped to left mouse button
330         beq     @L01
331         lda     #MOUSE_BTN_LEFT
332         ora     Buttons
333         sta     Buttons
334 @L01:   txa
335         and     #8
336         beq     @L02
337         lda     #MOUSE_BTN_RIGHT
338         ora     Buttons
339         sta     Buttons
340
341 ; Check if button status changed, and disable "attract mode" if yes
342
343 @L02:   lda     Buttons
344         cmp     OldButton
345         beq     @L03
346         sta     OldButton
347         lda     #0
348         sta     ATRACT
349
350 ; If we read 228 for X or Y positions, we assume the user has lifted the pen
351 ; and don't change the cursor position.
352
353 @L03:   lda     PADDL0
354         cmp     #228
355         beq     @Cont                   ; CF set if equal
356         lda     PADDL1
357         cmp     #228                    ; CF set if equal
358
359 @Cont:  php                             ; remember CF
360         jsr     CPREP
361         plp                             ; restore CF
362
363         bcc     @L04
364         jmp     @Show
365
366 @L04:   ldx     #0
367         stx     XPos+1
368         stx     YPos+1
369         stx     ATRACT                  ; disable "attract mode"
370
371 ; Get cursor position
372 ; -------------------
373 ; The touch pad is read thru the paddle potentiometers. The possible
374 ; values are 1..228. Since the maximum value is less than the X
375 ; dimension we have to "stretch" this value. In order to use only
376 ; divisions by powers of two, we use the following appoximation:
377 ; 320/227 = 1.4096
378 ; 1+1/2-1/8+1/32 = 1.4062
379 ; For Y we subtract 1/8 of it to get in the YMax ballpark.
380 ; 228-228/8=199.5
381 ; A small area in the Y dimension of the touchpad isn't used with
382 ; this approximation. The Y value is inverted, (0,0) is the bottom
383 ; left corner of the touchpad.
384
385 ; X
386
387         ldx     PADDL0                  ; get X postion
388         dex                             ; decrement, since it's 1-based
389         stx     XPos
390         txa
391         lsr     a
392         tax
393         clc
394         adc     XPos
395         sta     XPos
396         bcc     @L05
397         inc     XPos+1
398 @L05:   txa
399         lsr     a                       ; port value / 4
400         lsr     a                       ; port value / 8
401         tax
402         sec
403         lda     XPos
404         stx     XPos
405         sbc     XPos
406         sta     XPos
407         bcs     @L06
408         dec     XPos+1
409 @L06:   txa
410         lsr     a                       ; port value / 16
411         lsr     a                       ; port value / 32
412         clc
413         adc     XPos
414         sta     XPos
415         bcc     @L07
416         inc     XPos+1
417
418 @L07:   tay
419         lda     XPos+1
420         tax
421
422 ; Limit the X coordinate to the bounding box
423
424         cpy     XMin
425         sbc     XMin+1
426         bpl     @L08
427         ldy     XMin
428         ldx     XMin+1
429         jmp     @L09
430 @L08:   txa
431
432         cpy     XMax
433         sbc     XMax+1
434         bmi     @L09
435         ldy     XMax
436         ldx     XMax+1
437 @L09:   sty     XPos
438         stx     XPos+1
439
440 ; Move the mouse pointer to the new X pos
441
442         tya
443         jsr     CMOVEX
444
445 ; Y
446
447         ldx     PADDL1                  ; get Y postion
448         dex                             ; decrement, since it's 1-based
449         stx     YPos
450         lda     #228
451         sec
452         sbc     YPos                    ; invert value
453         tax
454         lsr     a
455         lsr     a
456         lsr     a
457         sta     YPos
458         txa
459         sec
460         sbc     YPos
461         sta     YPos
462         tay
463         lda     YPos+1
464         tax
465
466 ; Limit the Y coordinate to the bounding box
467
468         cpy     YMin
469         sbc     YMin+1
470         bpl     @L10
471         ldy     YMin
472         ldx     YMin+1
473         jmp     @L11
474 @L10:   txa
475
476         cpy     YMax
477         sbc     YMax+1
478         bmi     @L11
479         ldy     YMax
480         ldx     YMax+1
481 @L11:   sty     YPos
482         stx     YPos+1
483
484 ; Move the mouse pointer to the new X pos
485
486         tya
487         jsr     CMOVEY
488
489 @Show:  jsr     CDRAW
490
491         clc                             ; Interrupt not "handled"
492         rts