]> git.sur5r.net Git - cc65/blob - libsrc/c128/mouse.s
921461bae5c958f217b3a62794d7dac397c08ac4
[cc65] / libsrc / c128 / 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        "c128.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         sei                             ; Disable interrupts
157
158         sta     YMax
159         stx     YMax+1                  ; maxy
160
161         lda     (sp),y
162         sta     XMax
163         iny
164         lda     (sp),y
165         sta     XMax+1                  ; maxx
166
167         iny
168         lda     (sp),y
169         sta     YMin
170         iny
171         lda     (sp),y
172         sta     YMin+1                  ; miny
173
174         iny
175         lda     (sp),y
176         sta     XMin
177         iny
178         lda     (sp),y
179         sta     XMin+1                  ; minx
180
181         cli                             ; Enable interrupts
182
183         jmp     addysp1                 ; Drop params, return
184
185 ; --------------------------------------------------------------------------
186 ;
187 ; void __fastcall__ mouse_pos (struct mouse_pos* pos);
188 ; /* Return the current mouse position */
189 ;
190
191 _mouse_pos:
192         sta     ptr1
193         stx     ptr1+1                  ; Remember the argument pointer
194
195         ldy     #0                      ; Structure offset
196
197         sei                             ; Disable interrupts
198
199         lda     XPos                    ; Transfer the position
200         sta     (ptr1),y
201         lda     XPos+1
202         iny
203         sta     (ptr1),y
204         lda     YPos
205         iny
206         sta     (ptr1),y
207         lda     YPos
208         iny
209         sta     (ptr1),y
210
211         cli                             ; Restore initial interrupt state
212
213         rts                             ; Done
214
215 ; --------------------------------------------------------------------------
216 ;
217 ; void __fastcall__ mouse_info (struct mouse_info* info);
218 ; /* Return the state of the mouse buttons and the position of the mouse */
219 ;
220
221 _mouse_info:
222
223 ; We're cheating here to keep the code smaller: The first fields of the
224 ; mouse_info struct are identical to the mouse_pos struct, so we will just
225 ; call _mouse_pos to initialize the struct pointer and fill the position
226 ; fields.
227
228         jsr     _mouse_pos
229
230 ; Fill in the button state
231
232         jsr     _mouse_buttons          ; Will not touch ptr1
233         ldy     #4
234         sta     (ptr1),y
235
236         rts
237
238 ; --------------------------------------------------------------------------
239 ;
240 ; void __fastcall__ mouse_move (int x, int y);
241 ;
242
243 _mouse_move:
244         jsr     popsreg                 ; Get X
245         sei                             ; Disable interrupts
246
247         sta     YPos
248         stx     YPos+1
249         lda     sreg
250         ldx     sreg+1
251         sta     XPos
252         stx     XPos+1                  ; Set new position
253
254         jsr     MoveSprite              ; Move the sprite to the mouse pos
255
256 @L9:    cli                             ; Enable interrupts
257         rts
258
259
260 ; --------------------------------------------------------------------------
261 ;
262 ; unsigned char mouse_buttons (void);
263 ;
264
265 _mouse_buttons:
266         lda     MousePort               ; Get the port
267         jmp     _readjoy                ; Same as joystick
268
269 ; --------------------------------------------------------------------------
270 ;
271 ; Mouse interrupt handler
272 ;
273
274 MouseIRQ:
275         cld
276         lda     SID_ADConv1             ; Get mouse X movement
277         ldy     OldPotX
278         jsr     MoveCheck               ; Calculate movement vector
279         sty     OldPotX
280
281 ; Calculate the new X coordinate (--> a/y)
282
283         add     XPos
284         tay                             ; Remember low byte
285         txa
286         adc     XPos+1
287         tax
288
289 ; Limit the X coordinate to the bounding box
290
291         cpy     XMin
292         sbc     XMin+1
293         bpl     @L1
294         ldy     XMin
295         ldx     XMin+1
296         jmp     @L2
297 @L1:    txa
298
299         cpy     XMax
300         sbc     XMax+1
301         bmi     @L2
302         ldy     XMax
303         ldx     XMax+1
304 @L2:    sty     XPos
305         stx     XPos+1
306
307 ; Calculate the Y movement vector
308
309         lda     SID_ADConv2             ; Get mouse Y movement
310         ldy     OldPotY
311         jsr     MoveCheck               ; Calculate movement
312         sty     OldPotY
313
314 ; Calculate the new Y coordinate (--> a/y)
315
316         sta     OldValue
317         lda     YPos
318         sub     OldValue
319         tay
320         stx     OldValue
321         lda     YPos+1
322         sbc     OldValue
323         tax
324
325         cpy     YMin
326         sbc     YMin+1
327         bpl     @L3
328         ldy     YMin
329         ldx     YMin+1
330         jmp     @L4
331 @L3:    txa
332
333         cpy     YMax
334         sbc     YMax+1
335         bmi     @L4
336         ldy     YMax
337         ldx     YMax+1
338 @L4:    sty     YPos
339         stx     YPos+1
340
341 ; Move the mouse sprite if it is enabled
342
343         jsr     MoveSprite              ; Move the sprite
344
345 ; Jump to the next IRQ handler
346
347         jmp     (OldIRQ)
348
349
350 ; --------------------------------------------------------------------------
351 ;
352 ; Move check routine, called for both coordinates.
353 ;
354 ; Entry:        y = old value of pot register
355 ;               a = current value of pot register
356 ; Exit:         y = value to use for old value
357 ;               x/a = delta value for position
358 ;
359
360 MoveCheck:
361         sty     OldValue
362         sta     NewValue
363         ldx     #$00
364
365         sub     OldValue                ; a = mod64 (new - old)
366         and     #%01111111
367         cmp     #%01000000              ; if (a > 0)
368         bcs     @L1                     ;
369         lsr     a                       ;   a /= 2;
370         beq     @L2                     ;   if (a != 0)
371         ldy     NewValue                ;     y = NewValue
372         rts                             ;   return
373
374 @L1:    ora     #%11000000              ; else or in high order bits
375         cmp     #$FF                    ; if (a != -1)
376         beq     @L2
377         sec
378         ror     a                       ;   a /= 2
379         dex                             ;   high byte = -1 (X = $FF)
380         ldy     NewValue
381         rts
382
383 @L2:    txa                             ; A = $00
384         rts
385
386 ; --------------------------------------------------------------------------
387 ;
388 ; Move the mouse sprite to the current mouse position. Must be called
389 ; with interrupts off. MoveSprite1 is an entry without checking and
390 ; loading X
391 ;
392
393 MoveSprite:
394
395         lda     Visible                 ; Mouse visible?
396         bne     MoveSpriteDone          ; Jump if no
397         ldx     MouseSprite             ; Sprite defined?
398         beq     MoveSpriteDone          ; Jump if no
399
400 ; Set the high X bit
401
402 MoveSprite1:
403         lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
404         and     NotMask-1,x             ; Mask out sprite bit
405         ldy     XPos+1                  ; Test Y position
406         beq     @L1
407         ora     BitMask-1,x             ; Set high X bit
408 @L1:    sta     VIC_SPR_HI_X            ; Set hi X sprite values
409
410 ; Set the low X byte
411
412         txa
413         asl     a                       ; Index*2
414         tax
415         lda     XPos
416         sta     VIC_SPR0_X-2,x          ; Set low byte
417
418 ; Set the Y position
419
420         ldy     YPos+1                  ; Negative or too large?
421         bne     MoveSpriteDone          ; Jump if yes
422         lda     YPos
423         sta     VIC_SPR0_Y-2,x          ; Set Y position
424
425 ; Done
426
427 MoveSpriteDone:
428         rts
429
430 ; --------------------------------------------------------------------------
431 ; Data
432
433 .bss
434
435 OldIRQ:         .res    2               ; Old IRQ vector
436 MousePort:      .res    1               ; Port used for the mouse
437 MouseSprite:    .res    1               ; Number of sprite to control
438 OldValue:       .res    1               ; Temp for MoveCheck routine
439 NewValue:       .res    1               ; Temp for MoveCheck routine
440
441 Visible:        .res    1               ; Is the mouse visible?
442 OldPotX:        .res    1               ; Old hw counter values
443 OldPotY:        .res    1
444
445 XPos:           .res    2               ; Current mouse position, X
446 YPos:           .res    2               ; Current mouse position, Y
447
448 XMin:           .res    2               ; X1 value of bounding box
449 YMin:           .res    2               ; Y1 value of bounding box
450 XMax:           .res    2               ; X2 value of bounding box
451 YMax:           .res    2               ; Y2 value of bounding box
452
453 .data
454
455 BitMask:        .byte   $01, $02, $04, $08, $10, $20, $40, $80
456 NotMask:        .byte   $FE, $FD, $FB, $F7, $EF, $DF, $BF, $7F
457
458
459
460
461