]> git.sur5r.net Git - cc65/commitdiff
Small speed improvement
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 19 Apr 2004 11:38:51 +0000 (11:38 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 19 Apr 2004 11:38:51 +0000 (11:38 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2979 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/c128/Makefile
libsrc/c128/c128-640-200-2.s
libsrc/c128/c128-640-480-2.s
libsrc/c128/c128-joymouse.s [new file with mode: 0644]

index 0cbb8ad8cab3886fb27a0b080bdeb81d3e0d5285..e615f9f7463dc2e7a69e3e50e6f6e175274b0b8a 100644 (file)
@@ -62,7 +62,7 @@ EMDS = c128-georam.emd c128-ram.emd c128-ramcart.emd c128-reu.emd c128-vdc.emd
 
 JOYS = c128-ptvjoy.joy c128-stdjoy.joy
 
-MOUS = c128-1351.mou
+MOUS = c128-1351.mou c128-joymouse.mou
 
 SERS = c128-swlink.ser
 
index dbe0a0e6bc6c4abe8d2be10c8f06c4bf9dee712e..7bd0285d689b515af6cbe7915521066dae54eae3 100644 (file)
@@ -1201,13 +1201,11 @@ CALC:
 
 abs:
        ; a/y := abs(a/y)
-       dey
-       iny
+       cpy     #$00
        bpl     absend
        ; negay
-neg:   clc
-       eor     #$ff
-       adc     #1
+neg:   eor     #$ff
+       add     #1
        pha
        tya
        eor     #$ff
index 48cbaf1ebe26cdad308b357dc49e387c44295da0..71755a0e9f71dbf3365fe95527f81b30bda0f94a 100644 (file)
@@ -1216,13 +1216,11 @@ CALC:
 
 abs:
        ; a/y := abs(a/y)
-       dey
-       iny
+       cpy     #$00
        bpl     absend
        ; negay
-neg:   clc
-       eor     #$ff
-       adc     #1
+neg:   eor     #$ff
+       add     #1
        pha
        tya
        eor     #$ff
diff --git a/libsrc/c128/c128-joymouse.s b/libsrc/c128/c128-joymouse.s
new file mode 100644 (file)
index 0000000..161d24c
--- /dev/null
@@ -0,0 +1,389 @@
+;
+; Driver for a "joystick mouse".
+;
+; Ullrich von Bassewitz, 2004-04-05
+;
+
+        .include        "zeropage.inc"
+        .include        "mouse-kernel.inc"
+       .include        "c128.inc"
+
+        .macpack        generic
+
+; ------------------------------------------------------------------------
+; Header. Includes jump table
+
+.segment        "JUMPTABLE"
+
+HEADER:
+
+; Driver signature
+
+        .byte   $6d, $6f, $75           ; "mou"
+        .byte   MOUSE_API_VERSION       ; Mouse driver API version number
+
+; Jump table.
+
+        .addr   INSTALL
+        .addr   UNINSTALL
+        .addr   HIDE
+        .addr   SHOW
+        .addr   BOX
+        .addr   MOVE
+        .addr   BUTTONS
+        .addr   POS
+        .addr   INFO
+        .addr   IOCTL
+        .addr   IRQ
+
+; Callback table, set by the kernel before INSTALL is called
+
+CHIDE:  jmp     $0000                   ; Hide the cursor
+CSHOW:  jmp     $0000                   ; Show the cursor
+CMOVEX: jmp     $0000                   ; Move the cursor to X coord
+CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
+
+
+;----------------------------------------------------------------------------
+; Constants
+
+SCREEN_HEIGHT   = 200
+SCREEN_WIDTH    = 320
+
+.enum   JOY
+        UP      = $01
+        DOWN    = $02
+        LEFT    = $04
+        RIGHT   = $08
+        FIRE    = $10
+.endenum
+
+;----------------------------------------------------------------------------
+; 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
+
+Vars:
+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
+Buttons:       .res    1               ; Button mask
+
+; Temporary value used in the int handler
+
+Temp:           .res    1
+
+; Default values for above variables
+
+.rodata
+
+.proc   DefVars
+        .word   SCREEN_HEIGHT/2         ; YPos
+        .word   SCREEN_WIDTH/2          ; XPos
+        .word   SCREEN_HEIGHT           ; YMax
+        .word   SCREEN_WIDTH            ; XMax
+        .word   0                       ; YMin
+        .word   0                       ; XMin
+       .byte   0                       ; Buttons
+.endproc
+
+.code
+
+;----------------------------------------------------------------------------
+; INSTALL routine. Is called after the driver is loaded into memory. If
+; possible, check if the hardware is present.
+; Must return an MOUSE_ERR_xx code in a/x.
+
+INSTALL:
+
+; Initialize variables. Just copy the default stuff over
+
+        ldx     #.sizeof(DefVars)-1
+@L1:    lda     DefVars,x
+        sta     Vars,x
+        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)
+
+        ldx     #$00
+        txa
+        rts
+
+;----------------------------------------------------------------------------
+; UNINSTALL routine. Is called before the driver is removed from memory.
+; No return code required (the driver is removed from memory on return).
+
+UNINSTALL       = HIDE                  ; Hide cursor on exit
+
+;----------------------------------------------------------------------------
+; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
+; a counter for calls to show/hide, and the driver entry point is only called
+; if the mouse is currently visible and should get hidden. For most drivers,
+; no special action is required besides hiding the mouse cursor.
+; No return code required.
+
+HIDE:   sei
+        jsr     CHIDE
+        cli
+        rts
+
+;----------------------------------------------------------------------------
+; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
+; a counter for calls to show/hide, and the driver entry point is only called
+; if the mouse is currently hidden and should become visible. For most drivers,
+; no special action is required besides enabling the mouse cursor.
+; No return code required.
+
+SHOW:   sei
+        jsr     CSHOW
+        cli
+        rts
+
+;----------------------------------------------------------------------------
+; 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
+
+        cli
+               rts
+
+;----------------------------------------------------------------------------
+; MOVE: Move the mouse to a new position. The position is passed as it comes
+; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
+; remove the parameter from the stack on return.
+; No checks are done if the new position is valid (within the bounding box or
+; the screen). No return code required.
+;
+
+MOVE:   sei                             ; No interrupts
+
+        sta     YPos
+        stx     YPos+1                  ; New Y position
+        jsr     CMOVEY                  ; Set it
+
+        ldy     #$01
+        lda     (sp),y
+        sta     XPos+1
+        tax
+        dey
+        lda     (sp),y
+        sta     XPos                    ; New X position
+
+        jsr     CMOVEX                 ; Move the cursor
+
+       cli                             ; Allow interrupts
+               rts
+
+;----------------------------------------------------------------------------
+; BUTTONS: Return the button mask in a/x.
+
+BUTTONS:
+       lda     Buttons
+       ldx     #$00
+       rts
+
+;----------------------------------------------------------------------------
+; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
+; No return code required.
+
+POS:    ldy            #MOUSE_POS::XCOORD      ; Structure offset
+
+       sei                             ; Disable interrupts
+       lda     XPos                    ; Transfer the position
+       sta     (ptr1),y
+       lda     XPos+1
+       iny
+       sta     (ptr1),y
+       lda     YPos
+        iny
+        sta     (ptr1),y
+       lda     YPos+1
+       cli                             ; Enable interrupts
+
+        iny
+        sta     (ptr1),y                ; Store last byte
+
+       rts                             ; Done
+
+;----------------------------------------------------------------------------
+; INFO: Returns mouse position and current button mask in the MOUSE_INFO
+; struct pointed to by ptr1. No return code required.
+;
+; 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.
+
+INFO:   jsr    POS
+
+; Fill in the button state
+
+               lda     Buttons
+       ldy     #MOUSE_INFO::BUTTONS
+       sta     (ptr1),y
+
+       rts
+
+;----------------------------------------------------------------------------
+; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
+; specific data in ptr1, and the ioctl code in A.
+; Must return an error code in a/x.
+;
+
+IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
+        ldx     #>MOUSE_ERR_INV_IOCTL
+        rts
+
+;----------------------------------------------------------------------------
+; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
+; (so be careful).
+;
+
+IRQ:   lda     #$7F
+       sta     CIA1_PRA
+       lda     CIA1_PRB                ; Read joystick #0
+        and     #$1F
+       eor     #$1F                    ; Make all bits active high
+        sta     Temp
+
+; Check for a pressed button and place the result into Buttons
+
+        ldx     #$00                    ; Assume no button pressed
+        and     #JOY::FIRE              ; Check fire button
+        beq     @L0                     ; Jump if not pressed
+        ldx     #MOUSE_BTN_LEFT         ; Left (only) button is pressed
+@L0:    stx     Buttons
+
+; Check left/right
+
+        lda     Temp                    ; Read joystick #0
+               and     #(JOY::LEFT | JOY::RIGHT)
+        beq     @SkipX                 ;
+
+; We will cheat here and rely on the fact that either the left, OR the right
+; bit can be active
+
+               and     #JOY::RIGHT             ; Check RIGHT bit
+               bne     @Right
+       lda     #$FF
+       tax
+       bne     @AddX                   ; Branch always
+@Right:        lda     #$01
+       ldx     #$00
+
+; Calculate the new X coordinate (--> a/y)
+
+@AddX:  add     XPos
+       tay                             ; Remember low byte
+       txa
+       adc     XPos+1
+       tax
+
+; Limit the X coordinate to the bounding box
+
+       cpy     XMin
+       sbc     XMin+1
+       bpl     @L1
+               ldy     XMin
+               ldx     XMin+1
+       jmp     @L2
+@L1:   txa
+
+       cpy     XMax
+       sbc     XMax+1
+       bmi     @L2
+       ldy     XMax
+       ldx     XMax+1
+@L2:   sty     XPos
+       stx     XPos+1
+
+; Move the mouse pointer to the new X pos
+
+        tya
+        jsr     CMOVEX
+
+; Calculate the Y movement vector
+
+@SkipX: lda     Temp                    ; Read joystick #0
+               and     #(JOY::UP | JOY::DOWN)  ; Check up/down
+        beq     @SkipY                 ;
+
+; We will cheat here and rely on the fact that either the up, OR the down
+; bit can be active
+
+               lsr     a                       ; Check UP bit
+               bcc     @Down
+       lda     #$FF
+       tax
+       bne     @AddY
+@Down: lda     #$01
+       ldx     #$00
+
+; Calculate the new Y coordinate (--> a/y)
+
+@AddY:         add     YPos
+       tay                             ; Remember low byte
+       txa
+       adc     YPos+1
+       tax
+
+; Limit the Y coordinate to the bounding box
+
+       cpy     YMin
+       sbc     YMin+1
+       bpl     @L3
+               ldy     YMin
+               ldx     YMin+1
+       jmp     @L4
+@L3:   txa
+
+       cpy     YMax
+       sbc     YMax+1
+       bmi     @L4
+       ldy     YMax
+       ldx     YMax+1
+@L4:   sty     YPos
+       stx     YPos+1
+
+; Move the mouse pointer to the new X pos
+
+        tya
+        jmp     CMOVEY
+
+; Done
+
+@SkipY: rts
+