]> git.sur5r.net Git - cc65/blob - libsrc/cbm510/mou/cbm510-inkwl.s
Renamed the CBM510 lightpen driver to include the 184-C pen.
[cc65] / libsrc / cbm510 / mou / cbm510-inkwl.s
1 ;
2 ; Driver for the Inkwell Systems 170-C and 184-C lightpens.
3 ;
4 ; This driver reads only the main button on the 184-C.
5 ;
6 ; 2013-09-05, Greg King
7 ;
8
9         .include        "zeropage.inc"
10         .include        "../extzp.inc"
11
12         .include        "mouse-kernel.inc"
13         .include        "cbm510.inc"
14
15         .macpack        generic
16
17 ; ------------------------------------------------------------------------
18 ; Header. Includes jump table.
19
20 .segment        "JUMPTABLE"
21
22 HEADER:
23
24 ; Driver signature
25
26         .byte   $6d, $6f, $75           ; ASCII "mou"
27         .byte   MOUSE_API_VERSION       ; Mouse driver API version number
28
29 ; Library reference
30
31 LIBREF: .addr   $0000
32
33 ; Jump table
34
35         .addr   INSTALL
36         .addr   UNINSTALL
37         .addr   HIDE
38         .addr   SHOW
39         .addr   SETBOX
40         .addr   GETBOX
41         .addr   MOVE
42         .addr   BUTTONS
43         .addr   POS
44         .addr   INFO
45         .addr   IOCTL
46         .addr   IRQ
47
48 ; Mouse driver flags
49
50         .byte   MOUSE_FLAG_EARLY_IRQ
51
52 ; Callback table, set by the kernel before INSTALL is called.
53
54 CHIDE:  jmp     $0000                   ; Hide the cursor
55 CSHOW:  jmp     $0000                   ; Show the cursor
56 CMOVEX: jmp     $0000                   ; Move the cursor to X co-ord.
57 CMOVEY: jmp     $0000                   ; Move the cursor to Y co-ord.
58
59
60 ;----------------------------------------------------------------------------
61 ; Constants
62
63 SCREEN_WIDTH    = XSIZE * 8
64 SCREEN_HEIGHT   = YSIZE * 8
65
66 ;----------------------------------------------------------------------------
67 ; Global variables. The bounding box values are sorted so that they can be
68 ; written with the least effort in the SETBOX and GETBOX routines; so, don't
69 ; re-order them.
70
71 .rodata
72
73 ; Default values for below variables
74 ; (We use ".proc" because we want to define both a label and a scope.)
75
76 .proc   DefVars
77         .word   0                       ; XMin
78         .word   0                       ; YMin
79         .word   SCREEN_WIDTH - 1        ; XMax
80         .word   SCREEN_HEIGHT - 1       ; YMax
81 .endproc
82
83 .bss
84
85 Vars:
86 XMin:           .res    2               ; X1 value of bounding box
87 YMin:           .res    2               ; Y1 value of bounding box
88 XMax:           .res    2               ; X2 value of bounding box
89 YMax:           .res    2               ; Y2 value of bounding box
90
91 XPos:           .res    2               ; Current lightpen position, X
92 YPos:           .res    2               ; Current lightpen position, Y
93
94 OldPenX:        .res    1               ; Previous HW-counter values
95 OldPenY:        .res    1
96
97 .data
98
99 ; Default Inkwell calibration.
100 ; The first number is the width of the left border;
101 ; the second number is the actual calibration value.
102
103 XOffset:        .byte   (24 + 24) / 2   ; x-offset
104
105 ; Jump to a function that puts a new calibration value into XOffset.
106 Calibrate:      jmp     $0000
107
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 a MOUSE_ERR_xx code in .XA.
115
116 INSTALL:
117
118 ; Initiate variables. Just copy the default stuff over.
119
120         ldx     #.sizeof (DefVars) - 1
121 @L0:    lda     DefVars,x
122         sta     Vars,x
123         dex
124         bpl     @L0
125
126         ldx     #15                    ; Change to system bank
127         stx     IndReg
128         ldy     #VIC_LPEN_X
129         lda     (vic),y
130         sta     OldPenX
131         ldy     #VIC_LPEN_Y
132         lda     (vic),y
133         sta     OldPenY
134         ldx     ExecReg                 ; Change back to execution bank
135         stx     IndReg
136
137 ; Call a calibration function through the library-reference.
138
139         lda     LIBREF
140         ldx     LIBREF+1
141         sta     ptr1                    ; Point to mouse_adjuster
142         stx     ptr1+1
143         ldy     #1
144         lda     (ptr1),y
145         bze     @L1                     ; Don't call pointer if it's NULL
146         sta     Calibrate+2             ; Point to function
147         dey
148         lda     (ptr1),y
149         sta     Calibrate+1
150         lda     #<XOffset               ; Function will set this variable
151         ldx     #>XOffset
152         jsr     Calibrate
153
154 ; Be sure that the lightpen cursor is invisible and at the default location.
155 ; It needs to be done here because the lightpen interrupt handler doesn't
156 ; set the lightpen position if it hasn't changed.
157
158 @L1:    sei
159         jsr     CHIDE
160
161         lda     #<(SCREEN_HEIGHT / 2)
162         ldx     #>(SCREEN_HEIGHT / 2)
163         jsr     MoveY
164         lda     #<(SCREEN_WIDTH / 2)
165         ldx     #>(SCREEN_WIDTH / 2)
166         jsr     MoveX
167         cli
168
169 ; Done, return zero.
170
171         lda     #MOUSE_ERR_OK
172         tax
173         rts
174
175 ;----------------------------------------------------------------------------
176 ; UNINSTALL routine. Is called before the driver is removed from memory.
177 ; No return code required (the driver is removed from memory on return).
178
179 UNINSTALL       := HIDE                 ; Hide cursor on exit
180
181 ;----------------------------------------------------------------------------
182 ; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages
183 ; a counter for calls to show/hide, and the driver entry point is called only
184 ; if the mouse is currently visible, and should get hidden. For most drivers,
185 ; no special action is required besides hiding the lightpen cursor.
186 ; No return code required.
187
188 HIDE:   sei
189         jsr     CHIDE
190         cli
191         rts
192
193 ;----------------------------------------------------------------------------
194 ; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages
195 ; a counter for calls to show/hide, and the driver entry point is called only
196 ; if the mouse is currently hidden, and should become visible. For most drivers,
197 ; no special action is required besides enabling the lightpen cursor.
198 ; No return code required.
199
200 SHOW:   sei
201         jsr     CSHOW
202         cli
203         rts
204
205 ;----------------------------------------------------------------------------
206 ; SETBOX: Set the lightpen bounding box. The parameters are passed as they come
207 ; from the C program, that is, a pointer to a mouse_box struct in .XA.
208 ; No checks are done if the lightpen is currently inside the box, that is the job
209 ; of the caller. It is not necessary to validate the parameters; trust the
210 ; caller; and, save some code here. No return code required.
211
212 SETBOX: sta     ptr1
213         stx     ptr1+1                  ; Save data pointer
214
215         ldy     #.sizeof (MOUSE_BOX) - 1
216         sei
217
218 @L1:    lda     (ptr1),y
219         sta     XMin,y
220         dey
221         bpl     @L1
222
223         cli
224         rts
225
226 ;----------------------------------------------------------------------------
227 ; GETBOX: Return the lightpen bounding box. The parameters are passed as they
228 ; come from the C program, that is, a pointer to a mouse_box struct in .XA.
229
230 GETBOX: sta     ptr1
231         stx     ptr1+1                  ; Save data pointer
232
233         ldy     #.sizeof (MOUSE_BOX) - 1
234 @L1:    lda     XMin,y
235         sta     (ptr1),y
236         dey
237         bpl     @L1
238         rts
239
240 ;----------------------------------------------------------------------------
241 ; MOVE: Move the mouse to a new position. The position is passed as it comes
242 ; from the C program, that is: X on the stack and Y in .XA. The C wrapper will
243 ; remove the parameter from the stack on return.
244 ; No checks are done if the new position is valid (within the bounding box or
245 ; the screen). No return code required.
246 ;
247
248 MOVE:   sei                             ; No interrupts
249         jsr     MoveY
250
251         ldy     #$01
252         lda     (sp),y
253         tax
254         dey
255         lda     (sp),y
256         jsr     MoveX                   ; Move the cursor
257
258         cli                             ; Allow interrupts
259         rts
260
261 ;----------------------------------------------------------------------------
262 ; BUTTONS: Return the button mask in .XA.
263
264 BUTTONS:
265         ldx     #15                     ; To system bank
266         stx     IndReg
267         ldy     #CIA::PRB
268         lda     (cia2),y                ; Read joystick inputs
269         ldx     ExecReg                 ; Back to execution bank
270         stx     IndReg
271
272 ; Joystick 1, directions in bits 3-0.
273 ; Make the lightpen button look like a 1351 mouse.
274
275         asl     a                       ; Move joystick-left bit ...
276         asl     a                       ; ... to fire-button bit
277         eor     #MOUSE_BTN_LEFT
278         and     #MOUSE_BTN_LEFT
279         ldx     #>0
280         rts
281
282 ;----------------------------------------------------------------------------
283 ; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1.
284 ; No return code required.
285
286 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
287
288         sei                             ; Disable interrupts
289         lda     XPos                    ; Transfer the position
290         sta     (ptr1),y
291         lda     XPos+1
292         iny
293         sta     (ptr1),y
294         lda     YPos
295         iny
296         sta     (ptr1),y
297         lda     YPos+1
298         cli                             ; Enable interrupts
299
300         iny
301         sta     (ptr1),y                ; Store last byte
302         rts
303
304 ;----------------------------------------------------------------------------
305 ; INFO: Returns lightpen position and current button mask in the MOUSE_INFO
306 ; struct pointed to by ptr1. No return code required.
307 ;
308 ; We're cheating here, to keep the code smaller: The first fields of the
309 ; mouse_info struct are identical to the mouse_pos struct; so, we'll just
310 ; call _mouse_pos to initiate the struct pointer, and fill the position
311 ; fields.
312
313 INFO:   jsr     POS
314
315 ; Fill in the button state
316
317         jsr     BUTTONS                 ; Will not touch ptr1
318         ldy     #MOUSE_INFO::BUTTONS
319         sta     (ptr1),y
320         rts
321
322 ;----------------------------------------------------------------------------
323 ; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl-
324 ; specific data in ptr1, and the ioctl code in .A.
325 ; Must return an error code in .XA.
326 ;
327
328 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioctls, for now
329         ldx     #>MOUSE_ERR_INV_IOCTL
330         rts
331
332 ;----------------------------------------------------------------------------
333 ; IRQ: Irq.-handler entry point. Called as a subroutine, but in the IRQ context
334 ; (so, be careful). The routine MUST return carry set if the interrupt has been
335 ; 'handled' -- which means that the interrupt source is gone. Otherwise, it
336 ; MUST return carry clear.
337 ;
338
339 IRQ:    ldx     #15                     ; To system bank
340         stx     IndReg
341
342 ; Read the VIC-II lightpen registers.
343
344         ldy     #VIC_LPEN_Y
345         lda     (vic),y
346         cmp     OldPenY
347
348 ; Skip processing if nothing has changed.
349
350         beq     @SkipY
351         sta     OldPenY
352         ldx     ExecReg                 ; Back to execution bank
353         stx     IndReg
354
355 ; Subtract the height of the top border, so that the lightpen co-ordinate
356 ; will match the TGI co-ordinate.
357
358         sub     #50
359         tay                             ; Remember low byte
360         ldx     #>0
361
362 ; Limit the Y co-ordinate to the bounding box.
363
364         txa
365         cpy     YMin
366         sbc     YMin+1
367         bpl     @L3
368         ldy     YMin
369         ldx     YMin+1
370         jmp     @L4
371
372 @L3:    txa
373         cpy     YMax
374         sbc     YMax+1
375         bmi     @L4
376         ldy     YMax
377         ldx     YMax+1
378
379 @L4:    tya
380         jsr     MoveY
381
382         ldx     #15                     ; To system bank
383         stx     IndReg
384 @SkipY: ldy     #VIC_LPEN_X
385         lda     (vic),y
386         ldx     ExecReg                 ; Back to execution bank
387         stx     IndReg
388         cmp     OldPenX
389
390 ; Skip processing if nothing has changed.
391
392         beq     @SkipX
393         sta     OldPenX
394
395 ; Adjust the value by the calibration offset.
396
397         sub     XOffset
398
399 ; Calculate the new X co-ordinate.
400 ; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits.
401 ; Therefore, the VIC-II number is doubled. Then, it points to every other pixel;
402 ; but, it can reach across the screen.
403
404         asl     a
405         tay                             ; Remember low byte
406         lda     #>0
407         rol     a
408         tax                             ; Remember high byte
409
410 ; Limit the X co-ordinate to the bounding box.
411
412         cpy     XMin
413         sbc     XMin+1
414         bpl     @L1
415         ldy     XMin
416         ldx     XMin+1
417         jmp     @L2
418
419 @L1:    txa
420         cpy     XMax
421         sbc     XMax+1
422         bmi     @L2
423         ldy     XMax
424         ldx     XMax+1
425
426 @L2:    tya
427         jsr     MoveX
428
429 ; Done
430
431 @SkipX: clc                             ; Interrupt not "handled"
432         rts
433
434 ; Move the lightpen pointer to the new Y pos.
435
436 MoveY:  sta     YPos
437         stx     YPos+1
438         jmp     CMOVEY
439
440 ; Move the lightpen pointer to the new X pos.
441
442 MoveX:  sta     XPos
443         stx     XPos+1
444         jmp     CMOVEX