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