]> git.sur5r.net Git - cc65/blob - libsrc/c128/mou/c128-1351.s
Merge remote-tracking branch 'upstream/master' into something_to_pull
[cc65] / libsrc / c128 / mou / c128-1351.s
1 ;
2 ; Driver for the 1351 proportional mouse. Parts of the code are from
3 ; the Commodore 1351 mouse users guide.
4 ;
5 ; Ullrich von Bassewitz, 2003-12-29, 2009-09-26
6 ;
7
8         .include        "zeropage.inc"
9         .include        "mouse-kernel.inc"
10         .include        "c128.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 ; Library reference
27
28         .addr   $0000
29
30 ; Jump table
31
32         .addr   INSTALL
33         .addr   UNINSTALL
34         .addr   HIDE
35         .addr   SHOW
36         .addr   SETBOX
37         .addr   GETBOX
38         .addr   MOVE
39         .addr   BUTTONS
40         .addr   POS
41         .addr   INFO
42         .addr   IOCTL
43         .addr   IRQ
44
45 ; Mouse driver flags
46
47         .byte   MOUSE_FLAG_LATE_IRQ
48
49 ; Callback table, set by the kernel before INSTALL is called
50
51 CHIDE:  jmp     $0000                   ; Hide the cursor
52 CSHOW:  jmp     $0000                   ; Show the cursor
53 CPREP:  jmp     $0000                   ; Prepare to move the cursor
54 CDRAW:  jmp     $0000                   ; Draw the cursor
55 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
56 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
57
58
59 ;----------------------------------------------------------------------------
60 ; Constants
61
62 SCREEN_HEIGHT   = 200
63 SCREEN_WIDTH    = 320
64
65 ;----------------------------------------------------------------------------
66 ; Global variables. The bounding box values are sorted so that they can be
67 ; written with the least effort in the SETBOX and GETBOX routines, so don't
68 ; reorder them.
69
70 .bss
71
72 Vars:
73 OldPotX:        .res    1               ; Old hw counter values
74 OldPotY:        .res    1
75
76 YPos:           .res    2               ; Current mouse position, Y
77 XPos:           .res    2               ; Current mouse position, X
78 XMin:           .res    2               ; X1 value of bounding box
79 YMin:           .res    2               ; Y1 value of bounding box
80 XMax:           .res    2               ; X2 value of bounding box
81 YMax:           .res    2               ; Y2 value of bounding box
82
83 OldValue:       .res    1               ; Temp for MoveCheck routine
84 NewValue:       .res    1               ; Temp for MoveCheck routine
85
86 .rodata
87
88 ; Default values for above variables
89 ; (We use ".proc" because we want to define both a label and a scope.)
90
91 .proc   DefVars
92         .byte   0, 0                    ; OldPotX/OldPotY
93         .word   SCREEN_HEIGHT/2         ; YPos
94         .word   SCREEN_WIDTH/2          ; XPos
95         .word   0                       ; XMin
96         .word   0                       ; YMin
97         .word   SCREEN_WIDTH            ; XMax
98         .word   SCREEN_HEIGHT           ; YMax
99 .endproc
100
101 .code
102
103 ;----------------------------------------------------------------------------
104 ; INSTALL routine. Is called after the driver is loaded into memory. If
105 ; possible, check if the hardware is present.
106 ; Must return an MOUSE_ERR_xx code in a/x.
107
108 INSTALL:
109
110 ; Initialize variables. Just copy the default stuff over
111
112         ldx     #.sizeof(DefVars)-1
113 @L1:    lda     DefVars,x
114         sta     Vars,x
115         dex
116         bpl     @L1
117
118 ; Be sure the mouse cursor is invisible and at the default location. We
119 ; need to do that here, because our mouse interrupt handler doesn't set the
120 ; mouse position if it hasn't changed.
121
122         sei
123         jsr     CHIDE
124         lda     XPos
125         ldx     XPos+1
126         jsr     CMOVEX
127         lda     YPos
128         ldx     YPos+1
129         jsr     CMOVEY
130         cli
131
132 ; Done, return zero (= MOUSE_ERR_OK)
133
134         ldx     #$00
135         txa
136         rts                             ; Run into UNINSTALL instead
137
138 ;----------------------------------------------------------------------------
139 ; UNINSTALL routine. Is called before the driver is removed from memory.
140 ; No return code required (the driver is removed from memory on return).
141
142 UNINSTALL       = HIDE                  ; Hide cursor on exit
143
144 ;----------------------------------------------------------------------------
145 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
146 ; a counter for calls to show/hide, and the driver entry point is only called
147 ; if the mouse is currently visible and should get hidden. For most drivers,
148 ; no special action is required besides hiding the mouse cursor.
149 ; No return code required.
150
151 HIDE:   sei
152         jsr     CHIDE
153         cli
154         rts
155
156 ;----------------------------------------------------------------------------
157 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
158 ; a counter for calls to show/hide, and the driver entry point is only called
159 ; if the mouse is currently hidden and should become visible. For most drivers,
160 ; no special action is required besides enabling the mouse cursor.
161 ; No return code required.
162
163 SHOW:   sei
164         jsr     CSHOW
165         cli
166         rts
167
168 ;----------------------------------------------------------------------------
169 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
170 ; from the C program, that is, a pointer to a mouse_box struct in a/x.
171 ; No checks are done if the mouse is currently inside the box, this is the job
172 ; of the caller. It is not necessary to validate the parameters, trust the
173 ; caller and save some code here. No return code required.
174
175 SETBOX: sta     ptr1
176         stx     ptr1+1                  ; Save data pointer
177
178         ldy     #.sizeof (MOUSE_BOX)-1
179         sei
180
181 @L1:    lda     (ptr1),y
182         sta     XMin,y
183         dey
184         bpl     @L1
185
186         cli
187         rts
188
189 ;----------------------------------------------------------------------------
190 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
191 ; come from the C program, that is, a pointer to a mouse_box struct in a/x.
192
193 GETBOX: sta     ptr1
194         stx     ptr1+1                  ; Save data pointer
195
196         ldy     #.sizeof (MOUSE_BOX)-1
197         sei
198
199 @L1:    lda     XMin,y
200         sta     (ptr1),y
201         dey
202         bpl     @L1
203
204         cli
205         rts
206
207 ;----------------------------------------------------------------------------
208 ; MOVE: Move the mouse to a new position. The position is passed as it comes
209 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
210 ; remove the parameter from the stack on return.
211 ; No checks are done if the new position is valid (within the bounding box or
212 ; the screen). No return code required.
213 ;
214
215 MOVE:   sei                             ; No interrupts
216
217         sta     YPos
218         stx     YPos+1                  ; New Y position
219         jsr     CMOVEY                  ; Set it
220
221         ldy     #$01
222         lda     (sp),y
223         sta     XPos+1
224         tax
225         dey
226         lda     (sp),y
227         sta     XPos                    ; New X position
228
229         jsr     CMOVEX                  ; Move the cursor
230
231         cli                             ; Allow interrupts
232         rts
233
234 ;----------------------------------------------------------------------------
235 ; BUTTONS: Return the button mask in a/x.
236
237 BUTTONS:
238         lda     #$7F
239         sei
240         sta     CIA1_PRA
241         lda     CIA1_PRB                ; Read joystick #0
242         cli
243         ldx     #0
244         and     #$1F
245         eor     #$1F
246         rts
247
248 ;----------------------------------------------------------------------------
249 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
250 ; No return code required.
251
252 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
253
254         sei                             ; Disable interrupts
255         lda     XPos                    ; Transfer the position
256         sta     (ptr1),y
257         lda     XPos+1
258         iny
259         sta     (ptr1),y
260         lda     YPos
261         iny
262         sta     (ptr1),y
263         lda     YPos+1
264         cli                             ; Enable interrupts
265
266         iny
267         sta     (ptr1),y                ; Store last byte
268
269         rts                             ; Done
270
271 ;----------------------------------------------------------------------------
272 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
273 ; struct pointed to by ptr1. No return code required.
274 ;
275 ; We're cheating here to keep the code smaller: The first fields of the
276 ; mouse_info struct are identical to the mouse_pos struct, so we will just
277 ; call _mouse_pos to initialize the struct pointer and fill the position
278 ; fields.
279
280 INFO:   jsr     POS
281
282 ; Fill in the button state
283
284         jsr     BUTTONS                 ; Will not touch ptr1
285         ldy     #MOUSE_INFO::BUTTONS
286         sta     (ptr1),y
287
288         rts
289
290 ;----------------------------------------------------------------------------
291 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
292 ; specific data in ptr1, and the ioctl code in A.
293 ; Must return an error code in a/x.
294 ;
295
296 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
297         ldx     #>MOUSE_ERR_INV_IOCTL
298         rts
299
300 ;----------------------------------------------------------------------------
301 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
302 ; (so be careful). The routine MUST return carry set if the interrupt has been
303 ; 'handled' - which means that the interrupt source is gone. Otherwise it
304 ; MUST return carry clear.
305 ;
306
307 IRQ:    jsr     CPREP
308         lda     SID_ADConv1             ; Get mouse X movement
309         ldy     OldPotX
310         jsr     MoveCheck               ; Calculate movement vector
311         sty     OldPotX
312
313 ; Skip processing if nothing has changed
314
315         bcc     @SkipX
316
317 ; Calculate the new X coordinate (--> a/y)
318
319         add     XPos
320         tay                             ; Remember low byte
321         txa
322         adc     XPos+1
323         tax
324
325 ; Limit the X coordinate to the bounding box
326
327         cpy     XMin
328         sbc     XMin+1
329         bpl     @L1
330         ldy     XMin
331         ldx     XMin+1
332         jmp     @L2
333 @L1:    txa
334
335         cpy     XMax
336         sbc     XMax+1
337         bmi     @L2
338         ldy     XMax
339         ldx     XMax+1
340 @L2:    sty     XPos
341         stx     XPos+1
342
343 ; Move the mouse pointer to the new X pos
344
345         tya
346         jsr     CMOVEX
347
348 ; Calculate the Y movement vector
349
350 @SkipX: lda     SID_ADConv2             ; Get mouse Y movement
351         ldy     OldPotY
352         jsr     MoveCheck               ; Calculate movement
353         sty     OldPotY
354
355 ; Skip processing if nothing has changed
356
357         bcc     @SkipY
358
359 ; Calculate the new Y coordinate (--> a/y)
360
361         sta     OldValue
362         lda     YPos
363         sub     OldValue
364         tay
365         stx     OldValue
366         lda     YPos+1
367         sbc     OldValue
368         tax
369
370 ; Limit the Y coordinate to the bounding box
371
372         cpy     YMin
373         sbc     YMin+1
374         bpl     @L3
375         ldy     YMin
376         ldx     YMin+1
377         jmp     @L4
378 @L3:    txa
379
380         cpy     YMax
381         sbc     YMax+1
382         bmi     @L4
383         ldy     YMax
384         ldx     YMax+1
385 @L4:    sty     YPos
386         stx     YPos+1
387
388 ; Move the mouse pointer to the new X pos
389
390         tya
391         jsr     CMOVEY
392
393 ; Done
394
395 @SkipY: jsr     CDRAW
396         clc                             ; Interrupt not "handled"
397         rts
398
399 ; --------------------------------------------------------------------------
400 ;
401 ; Move check routine, called for both coordinates.
402 ;
403 ; Entry:        y = old value of pot register
404 ;               a = current value of pot register
405 ; Exit:         y = value to use for old value
406 ;               x/a = delta value for position
407 ;
408
409 MoveCheck:
410         sty     OldValue
411         sta     NewValue
412         ldx     #$00
413
414         sub     OldValue                ; a = mod64 (new - old)
415         and     #%01111111
416         cmp     #%01000000              ; if (a > 0)
417         bcs     @L1                     ;
418         lsr     a                       ;   a /= 2;
419         beq     @L2                     ;   if (a != 0)
420         ldy     NewValue                ;     y = NewValue
421         sec
422         rts                             ;   return
423
424 @L1:    ora     #%11000000              ; else or in high order bits
425         cmp     #$FF                    ; if (a != -1)
426         beq     @L2
427         sec
428         ror     a                       ;   a /= 2
429         dex                             ;   high byte = -1 (X = $FF)
430         ldy     NewValue
431         sec
432         rts
433
434 @L2:    txa                             ; A = $00
435         clc
436         rts
437