]> git.sur5r.net Git - cc65/blob - libsrc/cbm510/mou/cbm510-joy.s
Create static drivers directly from source files.
[cc65] / libsrc / cbm510 / mou / cbm510-joy.s
1 ;
2 ; Driver for a "joystick mouse".
3 ;
4 ; 2009-09-26, Ullrich von Bassewitz
5 ; 2013-09-05, Greg King
6 ;
7
8         .include        "zeropage.inc"
9         .include        "../extzp.inc"
10
11         .include        "mouse-kernel.inc"
12         .include        "cbm510.inc"
13
14         .macpack        generic
15         .macpack        module
16
17
18 ; ------------------------------------------------------------------------
19 ; Header. Includes jump table
20
21         module_header   _cbm510_joy_mou
22
23 HEADER:
24
25 ; Driver signature
26
27         .byte   $6d, $6f, $75           ; ASCII "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 co-ord.
60 CMOVEY: jmp     $0000                   ; Move the cursor to y co-ord.
61
62
63 ;----------------------------------------------------------------------------
64 ; Constants
65
66 SCREEN_HEIGHT   = YSIZE * 8
67 SCREEN_WIDTH    = XSIZE * 8
68
69 .scope  JOY
70         UP      = %00000001
71         DOWN    = %00000010
72         LEFT    = %00000100
73         RIGHT   = %00001000
74         FIRE    = %00010000
75 .endscope
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 ; re-order 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
92 ; Temporary value used in the interrupt handler
93
94 Temp:           .res    1
95
96 .rodata
97
98 ; Default values for above variables
99 ; (We use ".proc" because we want to define both a label and a scope.)
100
101 .proc   DefVars
102         .word   SCREEN_HEIGHT / 2       ; YPos
103         .word   SCREEN_WIDTH / 2        ; XPos
104         .word   0                       ; XMin
105         .word   0                       ; YMin
106         .word   SCREEN_WIDTH - 1        ; XMax
107         .word   SCREEN_HEIGHT - 1       ; YMax
108 .endproc
109
110 .code
111
112 ;----------------------------------------------------------------------------
113 ; INSTALL routine. Is called after the driver is loaded into memory. If
114 ; possible, check if the hardware is present.
115 ; Must return a MOUSE_ERR_xx code in .XA.
116
117 INSTALL:
118
119 ; Initiate variables; just copy the default stuff over.
120
121         ldx     #.sizeof(DefVars) - 1
122 @L1:    lda     DefVars,x
123         sta     Vars,x
124         dex
125         bpl     @L1
126
127 ; Be sure the mouse cursor is invisible and at the default location. We
128 ; need to do that here because our mouse interrupt handler doesn't set the
129 ; mouse position if it hasn't changed.
130
131         sei
132         jsr     CHIDE
133         lda     XPos
134         ldx     XPos+1
135         jsr     CMOVEX
136         lda     YPos
137         ldx     YPos+1
138         jsr     CMOVEY
139         cli
140
141 ; Done, return zero.
142
143         ldx     #>MOUSE_ERR_OK
144         txa
145         rts
146
147 ;----------------------------------------------------------------------------
148 ; UNINSTALL routine. Is called before the driver is removed from memory.
149 ; No return code required (the driver is removed from memory, on return).
150
151 UNINSTALL       := HIDE                 ; Hide cursor, on exit
152
153 ;----------------------------------------------------------------------------
154 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
155 ; a counter for calls to show/hide; and, the driver entry point is called only
156 ; if the mouse currently is visible and should get hidden. For most drivers,
157 ; no special action is required besides hiding the mouse cursor.
158 ; No return code required.
159
160 HIDE:   sei
161         jsr     CHIDE
162         cli
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 called only
168 ; if the mouse currently is 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:   sei
173         jsr     CSHOW
174         cli
175         rts
176
177 ;----------------------------------------------------------------------------
178 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
179 ; from the C program, that is, a pointer to a mouse_box struct in .XA.
180 ; No checks are done if the mouse currently is inside the box; that is the job
181 ; of the caller. It is not necessary to validate the parameters; trust the
182 ; caller, and save some code here. No return code required.
183
184 SETBOX: sta     ptr1
185         stx     ptr1+1                  ; Save data pointer
186
187         ldy     #.sizeof (MOUSE_BOX) - 1
188         sei
189
190 @L1:    lda     (ptr1),y
191         sta     XMin,y
192         dey
193         bpl     @L1
194
195         cli
196         rts
197
198 ;----------------------------------------------------------------------------
199 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
200 ; come from the C program, that is, a pointer to a mouse_box struct in .XA.
201
202 GETBOX: sta     ptr1
203         stx     ptr1+1                  ; Save data pointer
204
205         ldy     #.sizeof (MOUSE_BOX) - 1
206
207 @L1:    lda     XMin,y
208         sta     (ptr1),y
209         dey
210         bpl     @L1
211
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 .XA. 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:   sei                             ; No interrupts
223
224         jsr     MoveY                   ; Set new y position
225
226         ldy     #1
227         lda     (sp),y
228         sta     XPos+1
229         tax
230         dey
231         lda     (sp),y
232         jsr     MoveX                   ; Move the pointer
233
234         cli                             ; Allow interrupts
235         rts
236
237 ;----------------------------------------------------------------------------
238 ; BUTTONS: Return the button mask in .XA.
239 ; Joystick 2's fire button is the  left mouse button.
240 ; Joystick 1's fire button is the right mouse button.
241
242 BUTTONS:
243         ldx     #15                    ; Switch to the system bank
244         stx     IndReg
245
246 ; Get the fire-button bits
247
248         ldy     #CIA::PRA
249         lda     (cia2),y
250
251 ; Switch back to the execution bank.
252
253         ldy     ExecReg
254         sty     IndReg
255
256 ; Joystick 2, fire button is in bit 7.
257 ; Joystick 1, fire button is in bit 6.
258
259         and     #%11000000
260         asl     a                       ; Move bits 7,6 to bits 1,0
261         rol     a
262         rol     a
263         adc     #%00001110              ; Move bit 1 to bit 4
264         and     #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT
265
266 ; Bits go up when buttons go down.
267
268         eor     #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT
269         ldx     #>0
270         rts
271
272 ;----------------------------------------------------------------------------
273 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
274 ; struct pointed to by ptr1. No return code required.
275 ;
276 ; We're cheating here to keep the code smaller: The first fields of the
277 ; mouse_info struct are identical to the mouse_pos struct; so, we just will
278 ; use _mouse_pos to fill the position fields.
279
280 INFO:   jsr     BUTTONS
281
282 ; Fill in the button state.
283
284         ldy     #MOUSE_INFO::BUTTONS
285         sta     (ptr1),y
286
287 ;       jmp     POS                     ; Fall through
288
289 ;----------------------------------------------------------------------------
290 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
291 ; No return code required.
292
293 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
294
295         sei                             ; Disable interrupts
296         lda     XPos                    ; Transfer the position
297         sta     (ptr1),y
298         lda     XPos+1
299         iny
300         sta     (ptr1),y
301         lda     YPos
302         iny
303         sta     (ptr1),y
304         lda     YPos+1
305         cli                             ; Enable interrupts
306
307         iny
308         sta     (ptr1),y                ; Store last byte
309
310         rts                             ; Done
311
312 ;----------------------------------------------------------------------------
313 ; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl-
314 ; specific data in ptr1, and the ioctl code in .A.
315 ; Must return an error code in .XA.
316 ;
317
318 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL   ; We don't support ioctls, for now
319         ldx     #>MOUSE_ERR_INV_IOCTL
320         rts
321
322 ;----------------------------------------------------------------------------
323 ; IRQ: Irq.-handler entry point. Called as a subroutine, but in the IRQ context
324 ; (so, be careful). The routine MUST return carry set if the interrupt has been
325 ; 'handled' -- which means that the interrupt source is gone. Otherwise, it
326 ; MUST return carry clear.
327 ; Reads joystick 2.
328 ;
329
330 IRQ:    jsr     CPREP
331         ldy     #15                     ; Switch to the system bank
332         sty     IndReg
333
334 ; Get the direction bits.
335
336         ldy     #CIA::PRB
337         lda     (cia2),y                ; Read joystick inputs
338
339 ; Switch back to the execution bank.
340
341         ldy     ExecReg
342         sty     IndReg
343
344 ; Joystick 2, directions in bits 7-4.
345 ; Mask the relevant bits.
346
347         and     #$F0
348         eor     #$F0                    ; All bits are inverted
349         sta     Temp
350
351 ; Check left/right.
352
353         and     #(JOY::LEFT | JOY::RIGHT) << 4
354         bze     @SkipX
355
356 ; We will cheat here, and rely on the fact that either the left OR the right
357 ; bit can be active.
358
359         and     #JOY::RIGHT << 4        ; Check RIGHT bit
360         bnz     @Right
361         lda     #<-1
362         tax
363         bnz     @AddX                   ; Branch always
364 @Right: lda     #<1
365         ldx     #>1
366
367 ; Calculate the new x co-ordinate (--> .YA).
368
369 @AddX:  add     XPos
370         tay                             ; Remember low byte
371         txa
372         adc     XPos+1
373         tax
374
375 ; Limit the x co-ordinate to the bounding box.
376
377         cpy     XMin
378         sbc     XMin+1
379         bpl     @L1
380         ldy     XMin
381         ldx     XMin+1
382         jmp     @L2
383
384 @L1:    txa
385         cpy     XMax
386         sbc     XMax+1
387         bmi     @L2
388         ldy     XMax
389         ldx     XMax+1
390 @L2:    tya
391         jsr     MoveX
392
393 ; Calculate the y movement vector.
394
395 @SkipX: lda     Temp                    ; Get joystick again
396         and     #(JOY::UP | JOY::DOWN) << 4  ; Check up/down
397         bze     @SkipY
398
399 ; We will cheat here, and rely on the fact that either the up OR the down
400 ; bit can be active.
401
402         and     #JOY::UP << 4           ; Check UP bit
403         bze     @Down
404         lda     #<-1
405         tax
406         bnz     @AddY
407 @Down:  lda     #<1
408         ldx     #>1
409
410 ; Calculate the new y co-ordinate (--> .YA).
411
412 @AddY:  add     YPos
413         tay                             ; Remember low byte
414         txa
415         adc     YPos+1
416         tax
417
418 ; Limit the y co-ordinate to the bounding box.
419
420         cpy     YMin
421         sbc     YMin+1
422         bpl     @L3
423         ldy     YMin
424         ldx     YMin+1
425         jmp     @L4
426
427 @L3:    txa
428         cpy     YMax
429         sbc     YMax+1
430         bmi     @L4
431         ldy     YMax
432         ldx     YMax+1
433 @L4:    tya
434         jsr     MoveY
435
436 ; Done
437
438 @SkipY: jsr     CDRAW
439         clc                             ; Interrupt not "handled"
440         rts
441
442 ; Move the mouse pointer to the new x pos.
443
444 MoveX:  sta     XPos
445         stx     XPos+1
446         jmp     CMOVEX
447
448 ; Move the mouse pointer to the new y pos.
449
450 MoveY:  sta     YPos
451         stx     YPos+1
452         jmp     CMOVEY