]> git.sur5r.net Git - cc65/blob - libsrc/c64/mouse.s
info about c1541 in docs, lowered highest available address to $6000 due to
[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_x, _mouse_y
12         .export         _mouse_move, _mouse_buttons
13                                                    
14         .import         _readjoy
15         .import         popa, popsreg, addysp1
16         .importzp       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 ; int __fastcall__ mouse_x (void);
189 ;
190
191 _mouse_x:
192         php
193         sei
194         lda     XPos
195         ldx     XPos+1
196         plp
197         rts
198
199 ; --------------------------------------------------------------------------
200 ;
201 ; int __fastcall__ mouse_y (void);
202 ;
203
204 _mouse_y:
205         php
206         sei
207         lda     YPos
208         ldx     YPos+1
209         plp
210         rts
211
212 ; --------------------------------------------------------------------------
213 ;
214 ; void mouse_info (...);
215 ;
216
217 _mouse_info:
218         rts
219
220
221 ; --------------------------------------------------------------------------
222 ;
223 ; void __fastcall__ mouse_move (int x, int y);
224 ;
225
226 _mouse_move:
227         jsr     popsreg                 ; Get X
228         sei                             ; Disable interrupts
229
230         sta     YPos
231         stx     YPos+1
232         lda     sreg
233         ldx     sreg+1
234         sta     XPos
235         stx     XPos+1                  ; Set new position
236
237         jsr     MoveSprite              ; Move the sprite to the mouse pos
238
239 @L9:    cli                             ; Enable interrupts
240         rts
241
242
243 ; --------------------------------------------------------------------------
244 ;
245 ; unsigned char mouse_buttons (void);
246 ;
247
248 _mouse_buttons:
249         lda     MousePort               ; Get the port 
250         jmp     _readjoy                ; Same as joystick
251
252 ; --------------------------------------------------------------------------
253 ;
254 ; Mouse interrupt handler
255 ;
256
257 MouseIRQ:
258         cld
259         lda     SID_ADConv1             ; Get mouse X movement
260         ldy     OldPotX
261         jsr     MoveCheck               ; Calculate movement vector
262         sty     OldPotX
263
264 ; Calculate the new X coordinate (--> a/y)
265
266         add     XPos
267         tay                             ; Remember low byte
268         txa
269         adc     XPos+1
270         tax
271
272 ; Limit the X coordinate to the bounding box
273
274         cpy     XMin
275         sbc     XMin+1
276         bpl     @L1
277         ldy     XMin
278         ldx     XMin+1
279         jmp     @L2
280 @L1:    txa
281
282         cpy     XMax
283         sbc     XMax+1
284         bmi     @L2
285         ldy     XMax
286         ldx     XMax+1
287 @L2:    sty     XPos
288         stx     XPos+1
289
290 ; Calculate the Y movement vector
291
292         lda     SID_ADConv2             ; Get mouse Y movement
293         ldy     OldPotY
294         jsr     MoveCheck               ; Calculate movement
295         sty     OldPotY
296
297 ; Calculate the new Y coordinate (--> a/y)
298
299         sta     OldValue
300         lda     YPos
301         sub     OldValue
302         tay
303         stx     OldValue
304         lda     YPos+1
305         sbc     OldValue
306         tax
307
308         cpy     YMin
309         sbc     YMin+1
310         bpl     @L3
311         ldy     YMin
312         ldx     YMin+1
313         jmp     @L4
314 @L3:    txa
315
316         cpy     YMax
317         sbc     YMax+1
318         bmi     @L4
319         ldy     YMax
320         ldx     YMax+1
321 @L4:    sty     YPos
322         stx     YPos+1
323
324 ; Move the mouse sprite if it is enabled
325
326         jsr     MoveSprite              ; Move the sprite
327
328 ; Jump to the next IRQ handler
329
330         jmp     (OldIRQ)
331
332
333 ; --------------------------------------------------------------------------
334 ;
335 ; Move check routine, called for both coordinates.
336 ;
337 ; Entry:        y = old value of pot register
338 ;               a = current value of pot register
339 ; Exit:         y = value to use for old value
340 ;               x/a = delta value for position
341 ;
342
343 MoveCheck:
344         sty     OldValue
345         sta     NewValue
346         ldx     #$00
347
348         sub     OldValue                ; a = mod64 (new - old)
349         and     #%01111111
350         cmp     #%01000000              ; if (a > 0)
351         bcs     @L1                     ;
352         lsr     a                       ;   a /= 2;
353         beq     @L2                     ;   if (a != 0)
354         ldy     NewValue                ;     y = NewValue
355         rts                             ;   return
356
357 @L1:    ora     #%11000000              ; else or in high order bits
358         cmp     #$FF                    ; if (a != -1)
359         beq     @L2
360         sec
361         ror     a                       ;   a /= 2
362         dex                             ;   high byte = -1 (X = $FF)
363         ldy     NewValue
364         rts
365
366 @L2:    txa                             ; A = $00
367         rts
368
369 ; --------------------------------------------------------------------------
370 ;
371 ; Move the mouse sprite to the current mouse position. Must be called
372 ; with interrupts off. MoveSprite1 is an entry without checking and
373 ; loading X
374 ;
375
376 MoveSprite:
377
378         lda     Visible                 ; Mouse visible?
379         bne     MoveSpriteDone          ; Jump if no
380         ldx     MouseSprite             ; Sprite defined?
381         beq     MoveSpriteDone          ; Jump if no
382
383 ; Set the high X bit
384
385 MoveSprite1:
386         lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
387         and     NotMask-1,x             ; Mask out sprite bit
388         ldy     XPos+1                  ; Test Y position
389         beq     @L1
390         ora     BitMask-1,x             ; Set high X bit
391 @L1:    sta     VIC_SPR_HI_X            ; Set hi X sprite values
392
393 ; Set the low X byte
394
395         txa
396         asl     a                       ; Index*2
397         tax
398         lda     XPos
399         sta     VIC_SPR0_X-2,x          ; Set low byte
400
401 ; Set the Y position
402
403         ldy     YPos+1                  ; Negative or too large?
404         bne     MoveSpriteDone          ; Jump if yes
405         lda     YPos
406         sta     VIC_SPR0_Y-2,x          ; Set Y position
407
408 ; Done
409
410 MoveSpriteDone:
411         rts
412
413 ; --------------------------------------------------------------------------
414 ; Data
415
416 .bss
417
418 OldIRQ:         .res    2               ; Old IRQ vector
419 MousePort:      .res    1               ; Port used for the mouse
420 MouseSprite:    .res    1               ; Number of sprite to control
421 OldValue:       .res    1               ; Temp for MoveCheck routine
422 NewValue:       .res    1               ; Temp for MoveCheck routine
423
424 Visible:        .res    1               ; Is the mouse visible?
425 OldPotX:        .res    1               ; Old hw counter values
426 OldPotY:        .res    1
427
428 XPos:           .res    2               ; Current mouse position, X
429 YPos:           .res    2               ; Current mouse position, Y
430
431 XMin:           .res    2               ; X1 value of bounding box
432 YMin:           .res    2               ; Y1 value of bounding box
433 XMax:           .res    2               ; X2 value of bounding box
434 YMax:           .res    2               ; Y2 value of bounding box
435
436 .data
437
438 BitMask:        .byte   $01, $02, $04, $08, $10, $20, $40, $80
439 NotMask:        .byte   $FE, $FD, $FB, $F7, $EF, $DF, $BF, $7F
440
441
442
443
444