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