]> git.sur5r.net Git - cc65/blob - libsrc/c64/mouse.s
Added mouse_pos() and mouse_info(), removed mouse_x() and mouse_y()
[cc65] / libsrc / c64 / mouse.s
1 ;
2 ; Ullrich von Bassewitz, 24.04.1999
3 ;
4 ; Routines for the 1351 proportional mouse. Parts of the code are from
5 ; the Commodore 1351 mouse users guide.
6 ;
7
8         .export         _mouse_init, _mouse_done
9         .export         _mouse_hide, _mouse_show
10         .export         _mouse_box, _mouse_info
11         .export         _mouse_move, _mouse_pos
12         .export         _mouse_buttons, _mouse_info
13
14         .import         _readjoy
15         .import         popa, popsreg, addysp1
16         .importzp       ptr1, sp, sreg
17
18         .include        "c64.inc"
19
20         .macpack        generic
21
22 .code
23
24 ; --------------------------------------------------------------------------
25 ;
26 ; unsigned char __fastcall__ mouse_init (unsigned char port,
27 ;                                        unsigned char sprite,
28 ;                                        unsigned char type);
29 ;
30
31 _mouse_init:
32         jsr     popa                    ; Ignore the type, get sprite param
33         tax                             ; Save sprite number
34         jsr     popa                    ; Get the port number
35
36         ldy     OldIRQ+1                ; Already initialized?
37         bne     AlreadyInitialized      ; Jump if yes
38
39         stx     MouseSprite             ; Remember the sprite number
40         sta     MousePort               ; Remember the port number
41
42 ; Initialize variables
43
44         ldx     #0
45         stx     XPos
46         stx     XPos+1
47         stx     YPos
48         stx     YPos+1
49         stx     OldPotX
50         stx     OldPotY
51         stx     XMin
52         stx     XMin+1                  ; XMin = 0
53         lda     #29
54         sta     YMin
55         stx     YMin+1                  ; YMin = 29
56         lda     #250
57         sta     YMax
58         stx     YMax+1                  ; YMax = 250
59         inx                             ; X = 1
60         stx     Visible                 ; Mouse *not* visible
61         lda     #<344
62         sta     XMax
63         stx     XMax+1                  ; XMax = 344
64
65 ; Remember the old IRQ vector
66
67         lda     IRQVec
68         sta     OldIRQ
69         lda     IRQVec+1
70         sta     OldIRQ+1
71
72 ; Set our own IRQ vector. We cheat here to save a few bytes of code:
73 ; The function is expected to return a value not equal to zero on success,
74 ; and since we know that the high byte of the IRQ handler address is never
75 ; zweo, we will return just this byte.
76
77         ldx     #<MouseIRQ
78         lda     #>MouseIRQ
79         bne     SetIRQ                  ; Branch always
80
81 AlreadyInitialized:
82         lda     #0                      ; Error
83         rts
84
85 ; --------------------------------------------------------------------------
86 ;
87 ; void mouse_done (void);
88 ;
89
90 _mouse_done:
91         ldx     OldIRQ                  ; Initialized?
92         lda     OldIRQ+1
93         beq     Done                    ; Jump if no
94         ldy     #0
95         sty     OldIRQ+1                ; Reset the initialized flag
96 SetIRQ: sei                             ; Disable interrupts
97         stx     IRQVec                  ; Set the new/old vector
98         sta     IRQVec+1
99         cli                             ; Enable interrupts
100 Done:   rts
101
102 ; --------------------------------------------------------------------------
103 ;
104 ; void mouse_hide (void);
105 ;
106
107 _mouse_hide:
108         lda     Visible                 ; Get the flag
109         bne     @L1                     ; Jump if already invisible
110         ldx     MouseSprite             ; Sprite defined?
111         beq     @L1                     ; Jump if no
112
113         lda     NotMask-1,x             ; Get clean mask
114
115         sei                             ; Disable interrupts
116         and     VIC_SPR_ENA
117         sta     VIC_SPR_ENA             ; Disable sprite
118         cli                             ; Enable interrupts
119
120 @L1:    inc     Visible                 ; Set the flag to invisible
121         rts
122
123 ; --------------------------------------------------------------------------
124 ;
125 ; void mouse_show (void);
126 ;
127
128 _mouse_show:
129         lda     Visible                 ; Mouse already visible?
130         beq     @L1                     ; Jump if yes
131         dec     Visible                 ; Get the flag
132         bne     @L1                     ; Jump if still invisible
133         ldx     MouseSprite             ; Sprite defined?
134         beq     @L1                     ; Jump if no
135
136         sei                             ; Disable interrupts
137         jsr     MoveSprite1             ; Move the sprite to it's position
138
139         ldx     MouseSprite             ; Get sprite number (again)
140         lda     BitMask-1,x             ; Get bit mask
141         ora     VIC_SPR_ENA
142         sta     VIC_SPR_ENA             ; Enable sprite
143
144         cli                             ; Enable interrupts
145
146 @L1:    rts
147
148 ; --------------------------------------------------------------------------
149 ;
150 ; void __fastcall__ mouse_box (int minx, int miny, int maxx, int maxy);
151 ;
152
153 _mouse_box:
154         ldy     #0                      ; Stack offset
155
156         php
157         sei                             ; Disable interrupts
158
159         sta     YMax
160         stx     YMax+1                  ; maxy
161
162         lda     (sp),y
163         sta     XMax
164         iny
165         lda     (sp),y
166         sta     XMax+1                  ; maxx
167
168         iny
169         lda     (sp),y
170         sta     YMin
171         iny
172         lda     (sp),y
173         sta     YMin+1                  ; miny
174
175         iny
176         lda     (sp),y
177         sta     XMin
178         iny
179         lda     (sp),y
180         sta     XMin+1                  ; minx
181
182         plp                             ; Enable interrupts
183
184         jmp     addysp1                 ; Drop params, return
185
186 ; --------------------------------------------------------------------------
187 ;
188 ; void __fastcall__ mouse_pos (struct mouse_pos* pos);
189 ; /* Return the current mouse position */
190 ;
191
192 _mouse_pos:
193         sta     ptr1
194         stx     ptr1+1                  ; Remember the argument pointer
195
196         ldy     #0                      ; Structure offset
197
198         php
199         sei                             ; Disable interrupts
200
201         lda     XPos                    ; Transfer the position
202         sta     (ptr1),y
203         lda     XPos+1
204         iny
205         sta     (ptr1),y
206         lda     YPos
207         iny
208         sta     (ptr1),y
209         lda     YPos
210         iny
211         sta     (ptr1),y
212
213         plp                             ; Restore initial interrupt state
214
215         rts                             ; Done
216
217 ; --------------------------------------------------------------------------
218 ;
219 ; void __fastcall__ mouse_info (struct mouse_info* info);
220 ; /* Return the state of the mouse buttons and the position of the mouse */
221 ;
222
223 _mouse_info:
224
225 ; We're cheating here to keep the code smaller: The first fields of the
226 ; mouse_info struct are identical to the mouse_pos struct, so we will just
227 ; call _mouse_pos to initialize the struct pointer and fill the position
228 ; fields.
229
230         jsr     _mouse_pos
231
232 ; Fill in the button state
233
234         jsr     _mouse_buttons          ; Will not touch ptr1
235         ldy     #4
236         sta     (ptr1),y
237
238         rts
239
240 ; --------------------------------------------------------------------------
241 ;
242 ; void __fastcall__ mouse_move (int x, int y);
243 ;
244
245 _mouse_move:
246         jsr     popsreg                 ; Get X
247         sei                             ; Disable interrupts
248
249         sta     YPos
250         stx     YPos+1
251         lda     sreg
252         ldx     sreg+1
253         sta     XPos
254         stx     XPos+1                  ; Set new position
255
256         jsr     MoveSprite              ; Move the sprite to the mouse pos
257
258 @L9:    cli                             ; Enable interrupts
259         rts
260
261
262 ; --------------------------------------------------------------------------
263 ;
264 ; unsigned char mouse_buttons (void);
265 ;
266
267 _mouse_buttons:
268         lda     MousePort               ; Get the port
269         jmp     _readjoy                ; Same as joystick
270
271 ; --------------------------------------------------------------------------
272 ;
273 ; Mouse interrupt handler
274 ;
275
276 MouseIRQ:
277         cld
278         lda     SID_ADConv1             ; Get mouse X movement
279         ldy     OldPotX
280         jsr     MoveCheck               ; Calculate movement vector
281         sty     OldPotX
282
283 ; Calculate the new X coordinate (--> a/y)
284
285         add     XPos
286         tay                             ; Remember low byte
287         txa
288         adc     XPos+1
289         tax
290
291 ; Limit the X coordinate to the bounding box
292
293         cpy     XMin
294         sbc     XMin+1
295         bpl     @L1
296         ldy     XMin
297         ldx     XMin+1
298         jmp     @L2
299 @L1:    txa
300
301         cpy     XMax
302         sbc     XMax+1
303         bmi     @L2
304         ldy     XMax
305         ldx     XMax+1
306 @L2:    sty     XPos
307         stx     XPos+1
308
309 ; Calculate the Y movement vector
310
311         lda     SID_ADConv2             ; Get mouse Y movement
312         ldy     OldPotY
313         jsr     MoveCheck               ; Calculate movement
314         sty     OldPotY
315
316 ; Calculate the new Y coordinate (--> a/y)
317
318         sta     OldValue
319         lda     YPos
320         sub     OldValue
321         tay
322         stx     OldValue
323         lda     YPos+1
324         sbc     OldValue
325         tax
326
327         cpy     YMin
328         sbc     YMin+1
329         bpl     @L3
330         ldy     YMin
331         ldx     YMin+1
332         jmp     @L4
333 @L3:    txa
334
335         cpy     YMax
336         sbc     YMax+1
337         bmi     @L4
338         ldy     YMax
339         ldx     YMax+1
340 @L4:    sty     YPos
341         stx     YPos+1
342
343 ; Move the mouse sprite if it is enabled
344
345         jsr     MoveSprite              ; Move the sprite
346
347 ; Jump to the next IRQ handler
348
349         jmp     (OldIRQ)
350
351
352 ; --------------------------------------------------------------------------
353 ;
354 ; Move check routine, called for both coordinates.
355 ;
356 ; Entry:        y = old value of pot register
357 ;               a = current value of pot register
358 ; Exit:         y = value to use for old value
359 ;               x/a = delta value for position
360 ;
361
362 MoveCheck:
363         sty     OldValue
364         sta     NewValue
365         ldx     #$00
366
367         sub     OldValue                ; a = mod64 (new - old)
368         and     #%01111111
369         cmp     #%01000000              ; if (a > 0)
370         bcs     @L1                     ;
371         lsr     a                       ;   a /= 2;
372         beq     @L2                     ;   if (a != 0)
373         ldy     NewValue                ;     y = NewValue
374         rts                             ;   return
375
376 @L1:    ora     #%11000000              ; else or in high order bits
377         cmp     #$FF                    ; if (a != -1)
378         beq     @L2
379         sec
380         ror     a                       ;   a /= 2
381         dex                             ;   high byte = -1 (X = $FF)
382         ldy     NewValue
383         rts
384
385 @L2:    txa                             ; A = $00
386         rts
387
388 ; --------------------------------------------------------------------------
389 ;
390 ; Move the mouse sprite to the current mouse position. Must be called
391 ; with interrupts off. MoveSprite1 is an entry without checking and
392 ; loading X
393 ;
394
395 MoveSprite:
396
397         lda     Visible                 ; Mouse visible?
398         bne     MoveSpriteDone          ; Jump if no
399         ldx     MouseSprite             ; Sprite defined?
400         beq     MoveSpriteDone          ; Jump if no
401
402 ; Set the high X bit
403
404 MoveSprite1:
405         lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
406         and     NotMask-1,x             ; Mask out sprite bit
407         ldy     XPos+1                  ; Test Y position
408         beq     @L1
409         ora     BitMask-1,x             ; Set high X bit
410 @L1:    sta     VIC_SPR_HI_X            ; Set hi X sprite values
411
412 ; Set the low X byte
413
414         txa
415         asl     a                       ; Index*2
416         tax
417         lda     XPos
418         sta     VIC_SPR0_X-2,x          ; Set low byte
419
420 ; Set the Y position
421
422         ldy     YPos+1                  ; Negative or too large?
423         bne     MoveSpriteDone          ; Jump if yes
424         lda     YPos
425         sta     VIC_SPR0_Y-2,x          ; Set Y position
426
427 ; Done
428
429 MoveSpriteDone:
430         rts
431
432 ; --------------------------------------------------------------------------
433 ; Data
434
435 .bss
436
437 OldIRQ:         .res    2               ; Old IRQ vector
438 MousePort:      .res    1               ; Port used for the mouse
439 MouseSprite:    .res    1               ; Number of sprite to control
440 OldValue:       .res    1               ; Temp for MoveCheck routine
441 NewValue:       .res    1               ; Temp for MoveCheck routine
442
443 Visible:        .res    1               ; Is the mouse visible?
444 OldPotX:        .res    1               ; Old hw counter values
445 OldPotY:        .res    1
446
447 XPos:           .res    2               ; Current mouse position, X
448 YPos:           .res    2               ; Current mouse position, Y
449
450 XMin:           .res    2               ; X1 value of bounding box
451 YMin:           .res    2               ; Y1 value of bounding box
452 XMax:           .res    2               ; X2 value of bounding box
453 YMax:           .res    2               ; Y2 value of bounding box
454
455 .data
456
457 BitMask:        .byte   $01, $02, $04, $08, $10, $20, $40, $80
458 NotMask:        .byte   $FE, $FD, $FB, $F7, $EF, $DF, $BF, $7F
459
460
461
462
463