]> git.sur5r.net Git - cc65/blob - libsrc/c128/mou/c128-pot.s
3d5dd6fe417a51452f950fa49479337910057e0a
[cc65] / libsrc / c128 / mou / c128-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-04-26, Christian Groessler
7 ; 2014-05-05, Greg King
8 ;
9
10         .include        "zeropage.inc"
11         .include        "mouse-kernel.inc"
12         .include        "c128.inc"
13
14         .macpack        generic
15
16 ; ------------------------------------------------------------------------
17 ; Header. Includes jump table
18
19 .segment        "HEADER"
20
21 HEADER:
22
23 ; Driver signature
24
25         .byte   $6d, $6f, $75           ; "mou"
26         .byte   MOUSE_API_VERSION       ; Mouse driver API version number
27
28 ; Library reference
29
30 libref: .addr   $0000
31
32 ; Jump table
33
34         .addr   INSTALL
35         .addr   UNINSTALL
36         .addr   HIDE
37         .addr   SHOW
38         .addr   SETBOX
39         .addr   GETBOX
40         .addr   MOVE
41         .addr   BUTTONS
42         .addr   POS
43         .addr   INFO
44         .addr   IOCTL
45         .addr   IRQ
46
47 ; Mouse driver flags
48
49         .byte   MOUSE_FLAG_LATE_IRQ
50
51 ; Callback table, set by the kernel before INSTALL is called
52
53 CHIDE:  jmp     $0000                   ; Hide the cursor
54 CSHOW:  jmp     $0000                   ; Show the cursor
55 CPREP:  jmp     $0000                   ; Prepare to move the cursor
56 CDRAW:  jmp     $0000                   ; Draw the cursor
57 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
58 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
59
60
61 ;----------------------------------------------------------------------------
62 ; Constants
63
64 SCREEN_HEIGHT   = 200
65 SCREEN_WIDTH    = 320
66
67 .enum   JOY
68         UP      = $01
69         DOWN    = $02
70         LEFT    = $04
71         RIGHT   = $08
72         FIRE    = $10
73 .endenum
74
75 ;----------------------------------------------------------------------------
76 ; Global variables. The bounding box values are sorted so that they can be
77 ; written with the least effort in the SETBOX and GETBOX routines, so don't
78 ; reorder them.
79
80 .bss
81
82 Vars:
83 YPos:           .res    2               ; Current mouse position, Y
84 XPos:           .res    2               ; Current mouse position, X
85 XMin:           .res    2               ; X1 value of bounding box
86 YMin:           .res    2               ; Y1 value of bounding box
87 XMax:           .res    2               ; X2 value of bounding box
88 YMax:           .res    2               ; Y2 value of bounding box
89 Buttons:        .res    1               ; Button mask
90
91 INIT_save:      .res    1
92
93 ; Keyboard buffer fill level at start of interrupt
94
95 old_key_count:  .res    1
96
97 ; Original IRQ vector
98
99 old_irq:        .res    2
100
101 .rodata
102
103 ; Default values for above variables
104 ; (We use ".proc" because we want to define both a label and a scope.)
105
106 .proc   DefVars
107         .word   SCREEN_HEIGHT/2         ; YPos
108         .word   SCREEN_WIDTH/2          ; XPos
109         .word   0                       ; XMin
110         .word   0                       ; YMin
111         .word   SCREEN_WIDTH - 1        ; XMax
112         .word   SCREEN_HEIGHT - 1       ; YMax
113         .byte   0                       ; Buttons
114 .endproc
115
116 .code
117
118 ;----------------------------------------------------------------------------
119 ; INSTALL routine. Is called after the driver is loaded into memory. If
120 ; possible, check if the hardware is present.
121 ; Must return an MOUSE_ERR_xx code in a/x.
122
123 INSTALL:
124
125 ; Disable the BASIC interpreter's interrupt-driven sprite-motion code.
126 ; That allows direct access to the VIC-IIe's sprite registers.
127
128         lda     INIT_STATUS
129         sta     INIT_save
130         lda     #%11000000
131         sta     INIT_STATUS
132
133 ; Initialize variables. Just copy the default stuff over
134
135         ldx     #.sizeof(DefVars)-1
136 @L1:    lda     DefVars,x
137         sta     Vars,x
138         dex
139         bpl     @L1
140
141 ; Be sure the mouse cursor is invisible and at the default location. We
142 ; need to do that here, because our mouse interrupt handler doesn't set the
143 ; mouse position if it hasn't changed.
144
145         sei
146         jsr     CHIDE
147         lda     XPos
148         ldx     XPos+1
149         jsr     CMOVEX
150         lda     YPos
151         ldx     YPos+1
152         jsr     CMOVEY
153
154 ; Initiate our IRQ magic.
155
156         ; Remember the ROM IRQ continuation address.
157         ldx     IRQInd+2
158         lda     IRQInd+1
159         stx     old_irq+1
160         sta     old_irq
161
162         lda     libref
163         ldx     libref+1
164         sta     ptr3
165         stx     ptr3+1
166
167         ; Set the ROM IRQ continuation address to point to the provided routine.
168         ldy     #2
169         lda     (ptr3),y
170         sta     IRQInd+1
171         iny
172         lda     (ptr3),y
173         sta     IRQInd+2
174
175         ; Set the address of our IRQ callback routine.
176         ; Because it's called via "rts", we must use "address-1".
177         iny
178         lda     #<(callback-1)
179         sta     (ptr3),y
180         iny
181         lda     #>(callback-1)
182         sta     (ptr3),y
183
184         ; Set the ROM entry-point vector.
185         ; Because it's called via "rts", we must decrement it by one.
186         iny
187         lda     old_irq
188         sub     #<1
189         sta     (ptr3),y
190         iny
191         lda     old_irq+1
192         sbc     #>1
193         sta     (ptr3),y
194         cli
195
196 ; Done, return zero (= MOUSE_ERR_OK)
197
198         ldx     #$00
199         txa
200         rts
201
202 ;----------------------------------------------------------------------------
203 ; UNINSTALL routine. Is called before the driver is removed from memory.
204 ; No return code required (the driver is removed from memory on return).
205
206 UNINSTALL:
207         lda     old_irq
208         ldx     old_irq+1
209         sei
210         sta     IRQInd+1
211         stx     IRQInd+2
212         ;cli                            ; This will be done at end of HIDE
213
214         jsr     HIDE                    ; Hide cursor on exit
215         lda     INIT_save
216         sta     INIT_STATUS
217         rts
218
219 ;----------------------------------------------------------------------------
220 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
221 ; a counter for calls to show/hide, and the driver entry point is only called
222 ; if the mouse is currently visible and should get hidden. For most drivers,
223 ; no special action is required besides hiding the mouse cursor.
224 ; No return code required.
225
226 HIDE:   sei
227         jsr     CHIDE
228         cli
229         rts
230
231 ;----------------------------------------------------------------------------
232 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
233 ; a counter for calls to show/hide, and the driver entry point is only called
234 ; if the mouse is currently hidden and should become visible. For most drivers,
235 ; no special action is required besides enabling the mouse cursor.
236 ; No return code required.
237
238 SHOW:   sei
239         jsr     CSHOW
240         cli
241         rts
242
243 ;----------------------------------------------------------------------------
244 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
245 ; from the C program, that is, a pointer to a mouse_box struct in a/x.
246 ; No checks are done if the mouse is currently inside the box, this is the job
247 ; of the caller. It is not necessary to validate the parameters, trust the
248 ; caller and save some code here. No return code required.
249
250 SETBOX: sta     ptr1
251         stx     ptr1+1                  ; Save data pointer
252
253         ldy     #.sizeof (MOUSE_BOX)-1
254         sei
255
256 @L1:    lda     (ptr1),y
257         sta     XMin,y
258         dey
259         bpl     @L1
260
261         cli
262         rts
263
264 ;----------------------------------------------------------------------------
265 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
266 ; come from the C program, that is, a pointer to a mouse_box struct in a/x.
267
268 GETBOX: sta     ptr1
269         stx     ptr1+1                  ; Save data pointer
270
271         ldy     #.sizeof (MOUSE_BOX)-1
272         sei
273
274 @L1:    lda     XMin,y
275         sta     (ptr1),y
276         dey
277         bpl     @L1
278
279         cli
280         rts
281
282 ;----------------------------------------------------------------------------
283 ; MOVE: Move the mouse to a new position. The position is passed as it comes
284 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
285 ; remove the parameter from the stack on return.
286 ; No checks are done if the new position is valid (within the bounding box or
287 ; the screen). No return code required.
288 ;
289
290 MOVE:   sei                             ; No interrupts
291
292         sta     YPos
293         stx     YPos+1                  ; New Y position
294         jsr     CMOVEY                  ; Set it
295
296         ldy     #$01
297         lda     (sp),y
298         sta     XPos+1
299         tax
300         dey
301         lda     (sp),y
302         sta     XPos                    ; New X position
303
304         jsr     CMOVEX                  ; Move the cursor
305
306         cli                             ; Allow interrupts
307         rts
308
309 ;----------------------------------------------------------------------------
310 ; BUTTONS: Return the button mask in a/x.
311
312 BUTTONS:
313         lda     Buttons
314         ldx     #$00
315
316 ; Make the buttons look like a 1351 mouse.
317
318         and     #JOY::LEFT | JOY::RIGHT
319         lsr     a
320         lsr     a
321         ;clc                            ; ("lsr" shifted zero into carry flag)
322         adc     #%00001110              ; Shift bit 1 over to bit 4
323         and     #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT
324         rts
325
326 ;----------------------------------------------------------------------------
327 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
328 ; No return code required.
329
330 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
331
332         sei                             ; Disable interrupts
333         lda     XPos                    ; Transfer the position
334         sta     (ptr1),y
335         lda     XPos+1
336         iny
337         sta     (ptr1),y
338         lda     YPos
339         iny
340         sta     (ptr1),y
341         lda     YPos+1
342         cli                             ; Enable interrupts
343
344         iny
345         sta     (ptr1),y                ; Store last byte
346
347         rts                             ; Done
348
349 ;----------------------------------------------------------------------------
350 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
351 ; struct pointed to by ptr1. No return code required.
352 ;
353 ; We're cheating here to keep the code smaller: The first fields of the
354 ; mouse_info struct are identical to the mouse_pos struct, so we will just
355 ; call _mouse_pos to initialize the struct pointer and fill the position
356 ; fields.
357
358 INFO:   jsr     POS
359
360 ; Fill in the button state
361
362         jsr     BUTTONS
363         ldy     #MOUSE_INFO::BUTTONS
364         sta     (ptr1),y
365
366         rts
367
368 ;----------------------------------------------------------------------------
369 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
370 ; specific data in ptr1, and the ioctl code in A.
371 ; Must return an error code in a/x.
372 ;
373
374 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioctls for now
375         ldx     #>MOUSE_ERR_INV_IOCTL
376         rts
377
378 ;----------------------------------------------------------------------------
379 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
380 ; (so be careful).
381 ;
382
383 IRQ:    jsr     CPREP
384         lda     KEY_COUNT
385         sta     old_key_count
386         lda     #$7F
387         sta     CIA1_PRA
388         lda     CIA1_PRB                ; Read port #1
389         eor     #%11111111              ; Make all bits active high
390         sta     Buttons
391
392         ldx     #%01000000              ; Read port 1 paddles
393         stx     CIA1_PRA
394         ldy     #<256
395 :       dey
396         bne     :-
397         ldx     SID_ADConv1
398         stx     XPos
399         ldx     SID_ADConv2
400         stx     YPos
401
402         lda     #$FF
403         tax
404         bne     @AddX                   ; Branch always
405         lda     #$01
406         ldx     #$00
407
408 ; Calculate the new X coordinate (--> a/y)
409
410 @AddX:  add     XPos
411         tay                             ; Remember low byte
412         txa
413         adc     XPos+1
414         tax
415
416 ; Limit the X coordinate to the bounding box
417
418         cpy     XMin
419         sbc     XMin+1
420         bpl     @L1
421         ldy     XMin
422         ldx     XMin+1
423         jmp     @L2
424 @L1:    txa
425
426         cpy     XMax
427         sbc     XMax+1
428         bmi     @L2
429         ldy     XMax
430         ldx     XMax+1
431 @L2:    sty     XPos
432         stx     XPos+1
433
434 ; Move the mouse pointer to the new X pos
435
436         tya
437         jsr     CMOVEX
438
439         lda     #$FF
440         tax
441         bne     @AddY
442 @Down:  lda     #$01
443         ldx     #$00
444
445 ; Calculate the new Y coordinate (--> a/y)
446
447 @AddY:  add     YPos
448         tay                             ; Remember low byte
449         txa
450         adc     YPos+1
451         tax
452
453 ; Limit the Y coordinate to the bounding box
454
455         cpy     YMin
456         sbc     YMin+1
457         bpl     @L3
458         ldy     YMin
459         ldx     YMin+1
460         jmp     @L4
461 @L3:    txa
462
463         cpy     YMax
464         sbc     YMax+1
465         bmi     @L4
466         ldy     YMax
467         ldx     YMax+1
468 @L4:    sty     YPos
469         stx     YPos+1
470
471 ; Move the mouse pointer to the new X pos
472
473         tya
474         jsr     CMOVEY
475         jsr     CDRAW
476         clc                             ; Interrupt not "handled"
477         rts
478
479 .define OLD_BUTTONS Buttons             ; Tells callback.inc where the old port status is stored
480 .include        "callback.inc"