]> git.sur5r.net Git - cc65/commitdiff
Mouse driver implementation
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 23 Mar 2004 21:54:24 +0000 (21:54 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 23 Mar 2004 21:54:24 +0000 (21:54 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2957 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/c64/c64-1351.s
libsrc/c64/mcbdefault.s

index 6bd4cefe5e86e1d5239ef03b932c69b86cb07188..ab4732aaa6a2704c6adc6969caa4ad8f36e5831c 100644 (file)
@@ -37,11 +37,6 @@ HEADER:
         .addr   IOCTL
         .addr   IRQ
 
-; Data that is visible to the outside. Initialized by the kernel.
-
-XPos:   .word   0                       ; Current mouse position, X
-YPos:   .word   0                       ; Current mouse position, Y
-
 ; Callback table, set by the kernel before INSTALL is called
 
 CHIDE:  jmp     $0000                   ; Hide the cursor
@@ -57,9 +52,8 @@ SCREEN_HEIGHT   = 200
 SCREEN_WIDTH    = 320
 
 ;----------------------------------------------------------------------------
-;
-; Global variables
-;
+; Global variables. The bounding box values are sorted so that they can be
+; written with the least effort in the BOX routine, so don't reorder them.
 
 .bss
 
@@ -67,10 +61,12 @@ Vars:
 OldPotX:       .res    1               ; Old hw counter values
 OldPotY:       .res    1
 
-XMin:          .res    2               ; X1 value of bounding box
-YMin:          .res    2               ; Y1 value of bounding box
-XMax:          .res    2               ; X2 value of bounding box
+YPos:           .res    2               ; Current mouse position, Y
+XPos:           .res    2               ; Current mouse position, X
 YMax:          .res    2               ; Y2 value of bounding box
+XMax:          .res    2               ; X2 value of bounding box
+YMin:          .res    2               ; Y1 value of bounding box
+XMin:          .res    2               ; X1 value of bounding box
 
 OldValue:      .res    1               ; Temp for MoveCheck routine
 NewValue:      .res    1               ; Temp for MoveCheck routine
@@ -81,9 +77,12 @@ NewValue:    .res    1               ; Temp for MoveCheck routine
 
 .proc   DefVars
         .byte   0, 0                    ; OldPotX/OldPotY
-        .word   0, 0                    ; XMin/YMin
-        .word   SCREEN_WIDTH            ; XMax
+        .word   SCREEN_HEIGHT/2         ; YPos
+        .word   SCREEN_WIDTH/2          ; XPos
         .word   SCREEN_HEIGHT           ; YMax
+        .word   SCREEN_WIDTH            ; XMax
+        .word   0                       ; YMin
+        .word   0                       ; XMin
 .endproc
 
 .code
@@ -103,18 +102,31 @@ INSTALL:
         dex
         bpl     @L1
 
+; Be sure the mouse cursor is invisible and at the default location. We
+; need to do that here, because our mouse interrupt handler doesn't set the
+; mouse position if it hasn't changed.
+
+        sei
+        jsr     CHIDE
+        lda     XPos
+        ldx     XPos+1
+        jsr     CMOVEX
+        lda     YPos
+        ldx     YPos+1
+        jsr     CMOVEY
+        cli
+
 ; Done, return zero (= MOUSE_ERR_OK)
 
-        inx                             ; X = 0
+        ldx     #$00
         txa
-;       rts                             ; Run into UNINSTALL instead
+        rts                             ; Run into UNINSTALL instead
 
 ;----------------------------------------------------------------------------
 ; UNINSTALL routine. Is called before the driver is removed from memory.
 ; No return code required (the driver is removed from memory on return).
 
-UNINSTALL:
-        rts
+UNINSTALL       = HIDE                  ; Hide cursor on exit
 
 ;----------------------------------------------------------------------------
 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
@@ -123,7 +135,10 @@ UNINSTALL:
 ; no special action is required besides hiding the mouse cursor.
 ; No return code required.
 
-HIDE    = CHIDE
+HIDE:   sei
+        jsr     CHIDE
+        cli
+        rts
 
 ;----------------------------------------------------------------------------
 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
@@ -132,15 +147,31 @@ HIDE    = CHIDE
 ; no special action is required besides enabling the mouse cursor.
 ; No return code required.
 
-SHOW    = CSHOW
+SHOW:   sei
+        jsr     CSHOW
+        cli
+        rts
 
 ;----------------------------------------------------------------------------
-; BOX: Set the mouse bounding box. No checks are done if the mouse is
-; currently inside the box, this is the job of the caller. It is not necessary
-; to validate the parameters, trust the caller and save some code here.
-; No return code required.
+; BOX: Set the mouse bounding box. The parameters are passed as they come from
+; the C program, that is, maxy in a/x and the other parameters on the stack.
+; The C wrapper will remove the parameters from the stack when the driver
+; routine returns.
+; No checks are done if the mouse is currently inside the box, this is the job
+; of the caller. It is not necessary to validate the parameters, trust the
+; caller and save some code here. No return code required.
+
+BOX:    ldy     #5
+        sei
+        sta     YMax
+        stx     YMax+1
+
+@L1:    lda     (sp),y
+        sta     XMax,y
+        dey
+        bpl     @L1
 
-BOX:
+        cli
                rts
 
 ;----------------------------------------------------------------------------
@@ -243,8 +274,7 @@ IRQ:    lda SID_ADConv1             ; Get mouse X movement
 
 ; Skip processing if nothing has changed
 
-        tay
-        beq     @SkipX
+        bcc     @SkipX
 
 ; Calculate the new X coordinate (--> a/y)
 
@@ -275,19 +305,18 @@ IRQ:    lda       SID_ADConv1             ; Get mouse X movement
 ; Move the mouse pointer to the new X pos
 
         tya
-        jsr     CMOVEY
+        jsr     CMOVEX
 
 ; Calculate the Y movement vector
 
 @SkipX: lda    SID_ADConv2             ; Get mouse Y movement
-       ldy     OldPotY
-       jsr     MoveCheck               ; Calculate movement
-       sty     OldPotY
+       ldy     OldPotY
+       jsr     MoveCheck               ; Calculate movement
+       sty     OldPotY
 
 ; Skip processing if nothing has changed
 
-        tay
-        beq     @SkipY
+        bcc     @SkipY
 
 ; Calculate the new Y coordinate (--> a/y)
 
@@ -303,8 +332,8 @@ IRQ:    lda SID_ADConv1             ; Get mouse X movement
 ; Limit the Y coordinate to the bounding box
 
        cpy     YMin
-       sbc     YMin+1
-       bpl     @L3
+       sbc     YMin+1
+       bpl     @L3
                ldy     YMin
                ldx     YMin+1
        jmp     @L4
@@ -316,12 +345,12 @@ IRQ:    lda       SID_ADConv1             ; Get mouse X movement
        ldy     YMax
        ldx     YMax+1
 @L4:   sty     YPos
-       stx     YPos+1
+       stx     YPos+1
 
 ; Move the mouse pointer to the new X pos
 
         tya
-        jsr     CMOVEX
+        jmp     CMOVEY
 
 ; Done
 
@@ -342,24 +371,27 @@ MoveCheck:
        sta     NewValue
        ldx     #$00
 
-       sub     OldValue                ; a = mod64 (new - old)
+       sub     OldValue                ; a = mod64 (new - old)
        and     #%01111111
-       cmp     #%01000000              ; if (a > 0)
-       bcs     @L1                     ;
-       lsr     a                       ;   a /= 2;
-       beq     @L2                     ;   if (a != 0)
-       ldy     NewValue                ;     y = NewValue
-       rts                             ;   return
-
-@L1:   ora     #%11000000              ; else or in high order bits
-       cmp     #$FF                    ; if (a != -1)
+       cmp     #%01000000              ; if (a > 0)
+       bcs     @L1                     ;
+       lsr     a                       ;   a /= 2;
+       beq     @L2                     ;   if (a != 0)
+       ldy     NewValue                ;     y = NewValue
+        sec
+       rts                             ;   return
+
+@L1:   ora     #%11000000              ; else or in high order bits
+       cmp     #$FF                    ; if (a != -1)
        beq     @L2
        sec
-       ror     a                       ;   a /= 2
-               dex                             ;   high byte = -1 (X = $FF)
+       ror     a                       ;   a /= 2
+               dex                             ;   high byte = -1 (X = $FF)
        ldy     NewValue
+        sec
        rts
 
-@L2:           txa                             ; A = $00
+@L2:           txa                             ; A = $00
+        clc
        rts
 
index 44c9110354821f37f1f3c6c6f7cf5811a892d5ad..0199f717fd5d995f227173cf1dfd058cf806caaa 100644 (file)
@@ -2,6 +2,9 @@
 ; Default mouse callbacks for the C64
 ;
 ; Ullrich von Bassewitz, 2004-03-20
+;
+; All functions in this module should be interrupt safe, because they may
+; be called from an interrupt handler
 ;
 
         .export         _mouse_def_callbacks
@@ -9,6 +12,7 @@
         .include        "mouse-kernel.inc"
         .include        "c64.inc"
 
+        .macpack        generic
 
 ; Sprite definitions. The first value can be changed to adjust the number
 ; of the sprite used for the mouse.
@@ -18,71 +22,74 @@ MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK)  ; Negative mask
 VIC_SPR_X       = (VIC_SPR0_X + 2*MOUSE_SPR)    ; Sprite X register
 VIC_SPR_Y       = (VIC_SPR0_Y + 2*MOUSE_SPR)    ; Sprite Y register
 
-
 .code
 
 ; --------------------------------------------------------------------------
-; Hide the mouse pointer
+; Hide the mouse pointer. Always called with interrupts disabled.
 
 .proc   hide
 
         lda     #MOUSE_SPR_NMASK
-        sei
         and     VIC_SPR_ENA
         sta     VIC_SPR_ENA
-        cli
         rts
 
 .endproc
 
 ; --------------------------------------------------------------------------
-; Show the mouse pointer
+; Show the mouse pointer. Always called with interrupts disabled.
 
 .proc   show
 
         lda     #MOUSE_SPR_MASK
-        sei
         ora     VIC_SPR_ENA
         sta     VIC_SPR_ENA
-        cli
         rts
 
 .endproc
 
 ; --------------------------------------------------------------------------
-; Move the mouse pointer X position to the value in a/x
+; Move the mouse pointer X position to the value in a/x. Always called with
+; interrupts disabled.
 
 .proc   movex
 
-; Set the low byte, this frees A
+; Add the X correction and set the low byte. This frees A.
 
+        add     #24                     ; X correction
         sta     VIC_SPR_X
 
 ; Set the high byte
 
-        txa                             ; Test high byte of X coord
-        bne     @L1
-        sei
+        txa
+        adc     #0
+        bne     @L1                     ; Branch if high byte not zero
        lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
        and     #MOUSE_SPR_NMASK        ; Clear high bit for sprite
         sta     VIC_SPR_HI_X
-        cli
         rts
 
-@L1:    sei
-       lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
-       ora     #MOUSE_SPR_NMASK        ; Set high bit for sprite
+@L1:    lda    VIC_SPR_HI_X            ; Get high X bits of all sprites
+               ora     #MOUSE_SPR_MASK         ; Set high bit for sprite
         sta     VIC_SPR_HI_X
-        cli
         rts
 
 .endproc
 
 ; --------------------------------------------------------------------------
-; Move the mouse pointer Y position to the value in a/x
+; Move the mouse pointer Y position to the value in a/x. Always called with
+; interrupts disabled.
 
 .proc   movey
 
+        clc
+        ldx     PALFLAG
+        bne     @L1
+        adc     #50                     ; FIXME: Should be NTSC, is PAL value
+               sta     VIC_SPR_Y               ; Set Y position
+        rts
+
+@L1:    adc     #50                     ; Add PAL correction
                sta     VIC_SPR_Y               ; Set Y position
         rts
 
@@ -100,4 +107,3 @@ _mouse_def_callbacks:
         .addr   movey
 
 
-