]> git.sur5r.net Git - cc65/blob - libsrc/c64/c64-potmouse.s
Added Koala Pad mouse drivers written by Stefan Haubenthal.
[cc65] / libsrc / c64 / c64-potmouse.s
1 ;
2 ; Driver for a potentiometer "mouse" e.g. Koala Pad
3 ;
4 ; Ullrich von Bassewitz, 2004-03-29
5 ; Stefan Haubenthal, 2006-08-20
6 ;
7
8         .include        "zeropage.inc"
9         .include        "mouse-kernel.inc"
10         .include        "c64.inc"
11
12         .macpack        generic
13
14 ; ------------------------------------------------------------------------
15 ; Header. Includes jump table
16
17 .segment        "JUMPTABLE"
18
19 HEADER:
20
21 ; Driver signature
22
23         .byte   $6d, $6f, $75           ; "mou"
24         .byte   MOUSE_API_VERSION       ; Mouse driver API version number
25
26 ; Jump table.
27
28         .addr   INSTALL
29         .addr   UNINSTALL
30         .addr   HIDE
31         .addr   SHOW
32         .addr   BOX
33         .addr   MOVE
34         .addr   BUTTONS
35         .addr   POS
36         .addr   INFO
37         .addr   IOCTL
38         .addr   IRQ
39
40 ; Callback table, set by the kernel before INSTALL is called
41
42 CHIDE:  jmp     $0000                   ; Hide the cursor
43 CSHOW:  jmp     $0000                   ; Show the cursor
44 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
45 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
46
47
48 ;----------------------------------------------------------------------------
49 ; Constants
50
51 SCREEN_HEIGHT   = 200
52 SCREEN_WIDTH    = 320
53
54 .enum   JOY
55         UP      = $01
56         DOWN    = $02
57         LEFT    = $04
58         RIGHT   = $08
59         FIRE    = $10
60 .endenum
61
62 ;----------------------------------------------------------------------------
63 ; Global variables. The bounding box values are sorted so that they can be
64 ; written with the least effort in the BOX routine, so don't reorder them.
65
66 .bss
67
68 Vars:
69 YPos:           .res    2               ; Current mouse position, Y
70 XPos:           .res    2               ; Current mouse position, X
71 YMax:           .res    2               ; Y2 value of bounding box
72 XMax:           .res    2               ; X2 value of bounding box
73 YMin:           .res    2               ; Y1 value of bounding box
74 XMin:           .res    2               ; X1 value of bounding box
75 Buttons:        .res    1               ; Button mask
76
77 ; Temporary value used in the int handler
78
79 Temp:           .res    1
80
81 ; Default values for above variables
82
83 .rodata
84
85 .proc   DefVars
86         .word   SCREEN_HEIGHT/2         ; YPos
87         .word   SCREEN_WIDTH/2          ; XPos
88         .word   SCREEN_HEIGHT           ; YMax
89         .word   SCREEN_WIDTH            ; XMax
90         .word   0                       ; YMin
91         .word   0                       ; XMin
92         .byte   0                       ; Buttons
93 .endproc
94
95 .code
96
97 ;----------------------------------------------------------------------------
98 ; INSTALL routine. Is called after the driver is loaded into memory. If
99 ; possible, check if the hardware is present.
100 ; Must return an MOUSE_ERR_xx code in a/x.
101
102 INSTALL:
103
104 ; Initialize variables. Just copy the default stuff over
105
106         ldx     #.sizeof(DefVars)-1
107 @L1:    lda     DefVars,x
108         sta     Vars,x
109         dex
110         bpl     @L1
111
112 ; Be sure the mouse cursor is invisible and at the default location. We
113 ; need to do that here, because our mouse interrupt handler doesn't set the
114 ; mouse position if it hasn't changed.
115
116         sei
117         jsr     CHIDE
118         lda     XPos
119         ldx     XPos+1
120         jsr     CMOVEX
121         lda     YPos
122         ldx     YPos+1
123         jsr     CMOVEY
124         cli
125
126 ; Done, return zero (= MOUSE_ERR_OK)
127
128         ldx     #$00
129         txa
130         rts
131
132 ;----------------------------------------------------------------------------
133 ; UNINSTALL routine. Is called before the driver is removed from memory.
134 ; No return code required (the driver is removed from memory on return).
135
136 UNINSTALL       = HIDE                  ; Hide cursor on exit
137
138 ;----------------------------------------------------------------------------
139 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
140 ; a counter for calls to show/hide, and the driver entry point is only called
141 ; if the mouse is currently visible and should get hidden. For most drivers,
142 ; no special action is required besides hiding the mouse cursor.
143 ; No return code required.
144
145 HIDE:   sei
146         jsr     CHIDE
147         cli
148         rts
149
150 ;----------------------------------------------------------------------------
151 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
152 ; a counter for calls to show/hide, and the driver entry point is only called
153 ; if the mouse is currently hidden and should become visible. For most drivers,
154 ; no special action is required besides enabling the mouse cursor.
155 ; No return code required.
156
157 SHOW:   sei
158         jsr     CSHOW
159         cli
160         rts
161
162 ;----------------------------------------------------------------------------
163 ; BOX: Set the mouse bounding box. The parameters are passed as they come from
164 ; the C program, that is, maxy in a/x and the other parameters on the stack.
165 ; The C wrapper will remove the parameters from the stack when the driver
166 ; routine returns.
167 ; No checks are done if the mouse is currently inside the box, this is the job
168 ; of the caller. It is not necessary to validate the parameters, trust the
169 ; caller and save some code here. No return code required.
170
171 BOX:    ldy     #5
172         sei
173         sta     YMax
174         stx     YMax+1
175
176 @L1:    lda     (sp),y
177         sta     XMax,y
178         dey
179         bpl     @L1
180
181         cli
182         rts
183
184 ;----------------------------------------------------------------------------
185 ; MOVE: Move the mouse to a new position. The position is passed as it comes
186 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
187 ; remove the parameter from the stack on return.
188 ; No checks are done if the new position is valid (within the bounding box or
189 ; the screen). No return code required.
190 ;
191
192 MOVE:   sei                             ; No interrupts
193
194         sta     YPos
195         stx     YPos+1                  ; New Y position
196         jsr     CMOVEY                  ; Set it
197
198         ldy     #$01
199         lda     (sp),y
200         sta     XPos+1
201         tax
202         dey
203         lda     (sp),y
204         sta     XPos                    ; New X position
205
206         jsr     CMOVEX                  ; Move the cursor
207
208         cli                             ; Allow interrupts
209         rts
210
211 ;----------------------------------------------------------------------------
212 ; BUTTONS: Return the button mask in a/x.
213
214 BUTTONS:
215         lda     Buttons
216         ldx     #$00
217         rts
218
219 ;----------------------------------------------------------------------------
220 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
221 ; No return code required.
222
223 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
224
225         sei                             ; Disable interrupts
226         lda     XPos                    ; Transfer the position
227         sta     (ptr1),y
228         lda     XPos+1
229         iny
230         sta     (ptr1),y
231         lda     YPos
232         iny
233         sta     (ptr1),y
234         lda     YPos+1
235         cli                             ; Enable interrupts
236
237         iny
238         sta     (ptr1),y                ; Store last byte
239
240         rts                             ; Done
241
242 ;----------------------------------------------------------------------------
243 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
244 ; struct pointed to by ptr1. No return code required.
245 ;
246 ; We're cheating here to keep the code smaller: The first fields of the
247 ; mouse_info struct are identical to the mouse_pos struct, so we will just
248 ; call _mouse_pos to initialize the struct pointer and fill the position
249 ; fields.
250
251 INFO:   jsr     POS
252
253 ; Fill in the button state
254
255         lda     Buttons
256         ldy     #MOUSE_INFO::BUTTONS
257         sta     (ptr1),y
258
259         rts
260
261 ;----------------------------------------------------------------------------
262 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
263 ; specific data in ptr1, and the ioctl code in A.
264 ; Must return an error code in a/x.
265 ;
266
267 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
268         ldx     #>MOUSE_ERR_INV_IOCTL
269         rts
270
271 ;----------------------------------------------------------------------------
272 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
273 ; (so be careful).
274 ;
275
276 IRQ:    lda     #$7F
277         sta     CIA1_PRA
278         lda     CIA1_PRB                ; Read port #1
279         and     #%00001100
280         eor     #%00001100              ; Make all bits active high
281         asl
282         sta     Buttons
283         lsr
284         lsr
285         lsr
286         and     #%00000001
287         ora     Buttons
288         sta     Buttons
289         ldx     #%01000000
290         stx     CIA1_PRA
291         ldy     #0
292 :       dey
293         bne     :-
294         ldx     SID_ADConv1
295         stx     XPos
296         ldx     SID_ADConv2
297         stx     YPos
298
299         lda     #$FF
300         tax
301         bne     @AddX                   ; Branch always
302         lda     #$01
303         ldx     #$00
304
305 ; Calculate the new X coordinate (--> a/y)
306
307 @AddX:  add     XPos
308         tay                             ; Remember low byte
309         txa
310         adc     XPos+1
311         tax
312
313 ; Limit the X coordinate to the bounding box
314
315         cpy     XMin
316         sbc     XMin+1
317         bpl     @L1
318         ldy     XMin
319         ldx     XMin+1
320         jmp     @L2
321 @L1:    txa
322
323         cpy     XMax
324         sbc     XMax+1
325         bmi     @L2
326         ldy     XMax
327         ldx     XMax+1
328 @L2:    sty     XPos
329         stx     XPos+1
330
331 ; Move the mouse pointer to the new X pos
332
333         tya
334         jsr     CMOVEX
335
336         lda     #$FF
337         tax
338         bne     @AddY
339 @Down:  lda     #$01
340         ldx     #$00
341
342 ; Calculate the new Y coordinate (--> a/y)
343
344 @AddY:  add     YPos
345         tay                             ; Remember low byte
346         txa
347         adc     YPos+1
348         tax
349
350 ; Limit the Y coordinate to the bounding box
351
352         cpy     YMin
353         sbc     YMin+1
354         bpl     @L3
355         ldy     YMin
356         ldx     YMin+1
357         jmp     @L4
358 @L3:    txa
359
360         cpy     YMax
361         sbc     YMax+1
362         bmi     @L4
363         ldy     YMax
364         ldx     YMax+1
365 @L4:    sty     YPos
366         stx     YPos+1
367
368 ; Move the mouse pointer to the new X pos
369
370         tya
371         jmp     CMOVEY