]> git.sur5r.net Git - cc65/blobdiff - libsrc/c64/mouse.s
Fixed a bug
[cc65] / libsrc / c64 / mouse.s
index 4e02a36429bcaa9b54d6445abc73de09b4ceb200..23c228a7bc85b242e0385db1bae41c2cdae982e7 100644 (file)
@@ -8,52 +8,69 @@
        .export         _mouse_init, _mouse_done
        .export         _mouse_hide, _mouse_show
        .export         _mouse_box, _mouse_info
-       .export         _mouse_x, _mouse_y
-       .export         _mouse_move
+       .export         _mouse_move, _mouse_pos
+       .export         _mouse_buttons, _mouse_info
 
-               .import         popa, popsreg, addysp1
-       .importzp       sp, sreg
+       .import         _readjoy
+               .import         popax, addysp1
+       .importzp       ptr1, sp
 
        .include        "c64.inc"
 
+       .macpack        generic
+
+
 .code
 
 ; --------------------------------------------------------------------------
 ;
-; void __fastcall__ mouse_init (unsigned char port, unsigned char sprite);
+; Constants
 ;
 
-_mouse_init:
-       tax                             ; Save sprite number
-       jsr     popa                    ; Get the port number
+SPRITE_HEIGHT          = 21
+SPRITE_WIDTH   = 24
+SCREEN_HEIGHT  = 200
+SCREEN_WIDTH   = 320
+XCORR          = SPRITE_WIDTH
 
-               ldy     OldIRQ+1                ; Already initialized?
-               bne     Done                    ; Jump if yes
+; --------------------------------------------------------------------------
+;
+; unsigned char __fastcall__ mouse_init (unsigned char type);
+;
 
-       stx     MouseSprite             ; Remember the sprite number
-       sta     MousePort               ; Remember the port number
+_mouse_init:
+               lda     OldIRQ+1                ; Already initialized?
+               bne     AlreadyInitialized      ; Jump if yes
 
 ; Initialize variables
 
                ldx     #0
-       stx     XPos
+       lda     #XCORR
+               sta     XPos
        stx     XPos+1
        stx     YPos
        stx     YPos+1
        stx     OldPotX
        stx     OldPotY
                stx     XMin
-       stx     XMin+1
-       stx     YMin
-       stx     YMin+1
+       stx     XMin+1                  ; XMin = 0
+       lda     #50                     ; ## FIXME: This is the PAL value
+       sta     YCorr
+       sta     YPos
+       stx     YPos+1
+       sec
+        sbc            #SPRITE_HEIGHT          ; Sprite height in pixels
+       sta     YMin
+       stx     YMin+1                  ; YMin = 29
+       lda     #SCREEN_HEIGHT          ; Vertical screen res
+       add     YCorr                   ; Add correction factor
+       sta     YMax
        stx     YMax+1
-       inx                             ; X = 1
-               stx     Visible                 ; Mouse *not* visible
-       stx     XMax+1                  ; >320
-       ldx     #<320
-       stx     XMax
-       ldx     #200
-       stx     YMax
+       inx                             ; X = 1
+               stx     Invisible               ; Mouse *not* visible
+       lda     #<(SCREEN_WIDTH + SPRITE_WIDTH)
+       sta     XMax
+       stx     XMax+1                  ; XMax = 320 + sprite width
 
 ; Remember the old IRQ vector
 
@@ -62,11 +79,17 @@ _mouse_init:
        lda     IRQVec+1
        sta     OldIRQ+1
 
-; Set our own IRQ vector
+; Set our own IRQ vector.
+
+               ldx     #<MouseIRQ
+       ldy     #>MouseIRQ
+       jsr     SetIRQ                  ; Set our IRQ vector, disable sprite 0
+       lda     #1                      ; Mouse successfully initialized
+       rts
 
-       lda     #<MouseIRQ
-       ldx     #>MouseIRQ
-       bne     SetIRQ
+AlreadyInitialized:
+       lda     #0                      ; Error
+       rts
 
 ; --------------------------------------------------------------------------
 ;
@@ -74,36 +97,37 @@ _mouse_init:
 ;
 
 _mouse_done:
-               lda     OldIRQ                  ; Initialized?
-       ldx     OldIRQ+1
-       beq     Done                    ; Jump if no
-       ldy     #0
-       sty     OldIRQ+1                ; Reset the initialized flag
-SetIRQ:        sei                             ; Disable interrupts
-       sta     IRQVec                  ; Set the new/old vector
-       stx     IRQVec+1
-       cli                             ; Enable interrupts
+       ldx     OldIRQ
+               ldy     OldIRQ+1                ; Initialized?
+       beq     Done                    ; Jump if no
+       lda     #0
+       sta     OldIRQ+1                ; Reset the initialized flag
+SetIRQ:        sei                             ; Disable interrupts
+       stx     IRQVec                  ; Set the new/old vector
+               sty     IRQVec+1
+               lda     VIC_SPR_ENA             ; Get sprite enable register
+       and     #$FE                    ; Disable sprite #0
+       sta     VIC_SPR_ENA             ; Write back
+       cli                             ; Enable interrupts
 Done:  rts
 
+
 ; --------------------------------------------------------------------------
 ;
 ; void mouse_hide (void);
 ;
 
 _mouse_hide:
-               lda     Visible                 ; Get the flag
+               lda     Invisible               ; Get the flag
        bne     @L1                     ; Jump if already invisible
-               ldx     MouseSprite             ; Sprite defined?
-       beq     @L1                     ; Jump if no
-
-       lda     NotMask-1,x             ; Get clean mask
 
+       lda     #$FE                    ; Clear bit for sprite #0
        sei                             ; Disable interrupts
        and     VIC_SPR_ENA
        sta     VIC_SPR_ENA             ; Disable sprite
-       cli                             ; Enable interrupts
+       cli                             ; Enable interrupts
 
-@L1:   inc     Visible                 ; Set the flag to invisible
+@L1:   inc     Invisible               ; Set the flag to invisible
        rts
 
 ; --------------------------------------------------------------------------
@@ -112,21 +136,16 @@ _mouse_hide:
 ;
 
 _mouse_show:
-       lda     Visible                 ; Mouse already visible?
-       beq     @L1                     ; Jump if yes
-               dec     Visible                 ; Get the flag
-       bne     @L1                     ; Jump if still invisible
-               ldx     MouseSprite             ; Sprite defined?          
+       lda     Invisible               ; Mouse invisible?
        beq     @L1                     ; Jump if no
+               dec     Invisible               ; Set the flag
+       bne     @L1                     ; Jump if still invisible
 
                sei                             ; Disable interrupts
        jsr     MoveSprite1             ; Move the sprite to it's position
-
-       ldx     MouseSprite             ; Get sprite number (again)
-       lda     BitMask-1,x             ; Get bit mask
-               ora     VIC_SPR_ENA
-       sta     VIC_SPR_ENA             ; Enable sprite
-
+               lda     VIC_SPR_ENA             ; Get sprite enable register
+       ora     #$01                    ; Enable sprite #0
+       sta     VIC_SPR_ENA             ; Write back
        cli                             ; Enable interrupts
 
 @L1:   rts
@@ -139,70 +158,103 @@ _mouse_show:
 _mouse_box:
        ldy     #0                      ; Stack offset
 
-       php
-       sei                             ; Disable interrupts
+       add     YCorr                   ; Adjust the Y value
+       bcc     @L1
+       inx
+        clc
+@L1:   sei                             ; Disable interrupts
 
        sta     YMax
-       stx     YMax+1                  ; maxy
+       stx     YMax+1                  ; maxy
 
-       lda     (sp),y
+       lda     (sp),y
+       adc     #XCORR
        sta     XMax
        iny
        lda     (sp),y
-       sta     XMax+1                  ; maxx
+       adc     #$00
+       sta     XMax+1                  ; maxx
 
        iny
        lda     (sp),y
-       sta     YMin
+       add     YCorr
+       sta     YMin
        iny
        lda     (sp),y
-       sta     YMin+1                  ; miny
+       adc     #$00
+       sta     YMin+1                  ; miny
 
        iny
        lda     (sp),y
-       sta     XMin
+       add     #XCORR
+       sta     XMin
        iny
        lda     (sp),y
-       sta     XMin+1                  ; minx
+       adc     #$00
+       sta     XMin+1                  ; minx
 
-       plp                             ; Enable interrupts
+       cli                             ; Enable interrupts
 
        jmp     addysp1                 ; Drop params, return
 
 ; --------------------------------------------------------------------------
 ;
-; int __fastcall__ mouse_x (void);
+; void __fastcall__ mouse_pos (struct mouse_pos* pos);
+; /* Return the current mouse position */
 ;
 
-_mouse_x:
-       php
-       sei
-       lda     XPos
-       ldx     XPos+1
-       plp
-       rts
+_mouse_pos:
+               sta     ptr1
+       stx     ptr1+1                  ; Remember the argument pointer
+
+       ldy     #0                      ; Structure offset
+       sec                             ; Needed for the SBC later
+
+       sei                             ; Disable interrupts
+       lda     XPos                    ; Transfer the position
+       sbc     #XCORR
+       sta     (ptr1),y
+       lda     XPos+1
+       sbc     #$00
+       iny
+       sta     (ptr1),y
+       lda     YPos
+       ldx     YPos+1
+       cli                             ; Restore initial interrupt state
 
-; --------------------------------------------------------------------------
-;
-; int __fastcall__ mouse_y (void);
-;
+       sub     YCorr                   ; Apply the Y correction value
+       bcs     @L1
+       dex
+@L1:           iny
+       sta     (ptr1),y                ; Store YPos
+       txa
+       iny
+       sta     (ptr1),y
 
-_mouse_y:
-       php
-       sei
-       lda     YPos
-       ldx     YPos+1
-       plp
-       rts
+       rts                             ; Done
 
 ; --------------------------------------------------------------------------
 ;
-; void mouse_info (...);
+; void __fastcall__ mouse_info (struct mouse_info* info);
+; /* Return the state of the mouse buttons and the position of the mouse */
 ;
 
 _mouse_info:
-       rts
 
+; We're cheating here to keep the code smaller: The first fields of the
+; mouse_info struct are identical to the mouse_pos struct, so we will just
+; call _mouse_pos to initialize the struct pointer and fill the position
+; fields.
+
+        jsr    _mouse_pos
+
+; Fill in the button state
+
+       jsr     _mouse_buttons          ; Will not touch ptr1
+       ldy     #4
+       sta     (ptr1),y
+
+       rts
 
 ; --------------------------------------------------------------------------
 ;
@@ -210,20 +262,35 @@ _mouse_info:
 ;
 
 _mouse_move:
-       jsr     popsreg                 ; Get X
-       sei                             ; Disable interrupts
+       add     YCorr                   ; Add Y coordinate correction
+       bcc     @L1
+       inx
+       clc
+@L1:   sei
+       sta     YPos
+       stx     YPos+1
+       cli
+
+       jsr     popax                   ; Get X
+       adc     #XCORR                  ; Adjust X coordinate
+       bcc     @L2
+       inx
+@L2:   sei
+       sta     XPos
+       stx     XPos+1                  ; Set new position
+       jsr     MoveSprite              ; Move the sprite to the mouse pos
+       cli                             ; Enable interrupts
 
-       sta     YPos
-       stx     YPos+1
-       lda     sreg
-       ldx     sreg+1
-       sta     XPos
-       stx     XPos+1                  ; Set new position
+       rts
 
-       jsr     MoveSprite              ; Move the sprite to the mouse pos
+; --------------------------------------------------------------------------
+;
+; unsigned char mouse_buttons (void);
+;
 
-@L9:   cli                             ; Enable interrupts
-       rts
+_mouse_buttons:
+       lda     #$00                    ; Use port #0
+       jmp     _readjoy                ; Same as joystick
 
 ; --------------------------------------------------------------------------
 ;
@@ -239,8 +306,7 @@ MouseIRQ:
 
 ; Calculate the new X coordinate (--> a/y)
 
-       clc
-       adc     XPos
+               add     XPos
        tay                             ; Remember low byte
        txa
        adc     XPos+1
@@ -273,11 +339,14 @@ MouseIRQ:
 
 ; Calculate the new Y coordinate (--> a/y)
 
-       clc
-       adc     YPos
-       tay                             ; Remember low byte
-       txa
-       adc     YPos+1
+       sta     OldValue
+       lda     YPos
+       sub     OldValue
+       tay
+       stx     OldValue
+       lda     YPos+1
+       sbc     OldValue
+       tax
 
        cpy     YMin
        sbc     YMin+1
@@ -319,8 +388,7 @@ MoveCheck:
        sta     NewValue
        ldx     #$00
 
-       sec                             ; a = mod64 (new - old)
-       sbc     OldValue
+       sub     OldValue                ; a = mod64 (new - old)
        and     #%01111111
        cmp     #%01000000              ; if (a > 0)
        bcs     @L1                     ;
@@ -334,51 +402,45 @@ MoveCheck:
        beq     @L2
        sec
        ror     a                       ;   a /= 2
-       ldx     #$FF                    ;   high byte = -1
+               dex                             ;   high byte = -1 (X = $FF)
        ldy     NewValue
        rts
 
-@L2:   lda     #0
+@L2:           txa                             ; A = $00
        rts
 
 ; --------------------------------------------------------------------------
 ;
 ; Move the mouse sprite to the current mouse position. Must be called
-; with interrupts off. MoveSprite1 is an entry without checking and
-; loading X
+; with interrupts off. MoveSprite1 is an entry without checking.
 ;
 
 MoveSprite:
 
-       lda     Visible                 ; Mouse visible?
+       lda     Invisible               ; Mouse visible?
                bne     MoveSpriteDone          ; Jump if no
-       ldx     MouseSprite             ; Sprite defined?
-       beq     MoveSpriteDone          ; Jump if no
 
 ; Set the high X bit
 
 MoveSprite1:
        lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
-       and     NotMask-1,x             ; Mask out sprite bit
-       ldy     XPos+1                  ; Test Y position
+       and     #$FE                    ; Clear bit for sprite #0
+       ldy     XPos+1                  ; Test Y position
        beq     @L1
-       ora     BitMask-1,x             ; Set high X bit
+               ora     #$01                    ; Set high X bit
 @L1:   sta     VIC_SPR_HI_X            ; Set hi X sprite values
 
 ; Set the low X byte
 
-       txa
-       asl     a                       ; Index*2
-       tax
        lda     XPos
-       sta     VIC_SPR0_X-2,x          ; Set low byte
+               sta     VIC_SPR0_X              ; Set low byte
 
 ; Set the Y position
 
-       ldy     YPos+1                  ; Negative or too large?
+       ldy     YPos+1                  ; Negative or too large?
        bne     MoveSpriteDone          ; Jump if yes
        lda     YPos
-       sta     VIC_SPR0_Y-2,x          ; Set Y position
+       sta     VIC_SPR0_Y              ; Set Y position
 
 ; Done
 
@@ -390,14 +452,13 @@ MoveSpriteDone:
 
 .bss
 
-OldIRQ:                .res    2               ; Old IRQ vector
-MousePort:     .res    1               ; Port used for the mouse
-MouseSprite:   .res    1               ; Number of sprite to control
+OldIRQ:                .res    2               ; Old IRQ vector
 OldValue:      .res    1               ; Temp for MoveCheck routine
 NewValue:      .res    1               ; Temp for MoveCheck routine
+YCorr:         .res    1               ; Correction for Y coordinate
 
-Visible:       .res    1               ; Is the mouse visible?
-OldPotX:       .res    1               ; Old hw counter values
+Invisible:     .res    1               ; Is the mouse invisible?
+OldPotX:       .res    1               ; Old hw counter values
 OldPotY:       .res    1
 
 XPos:          .res    2               ; Current mouse position, X
@@ -408,12 +469,4 @@ YMin:              .res    2               ; Y1 value of bounding box
 XMax:          .res    2               ; X2 value of bounding box
 YMax:          .res    2               ; Y2 value of bounding box
 
-.data
-
-BitMask:       .byte   $01, $02, $04, $08, $10, $20, $40, $80
-NotMask:               .byte   $FE, $FD, $FB, $F7, $EF, $DF, $BF, $7F
-
-
-
-