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