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