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