.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
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
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
.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
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
; 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
; 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
;----------------------------------------------------------------------------
; Skip processing if nothing has changed
- tay
- beq @SkipX
+ bcc @SkipX
; Calculate the new X coordinate (--> a/y)
; 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)
; 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
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
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
; 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
.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.
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
.addr movey
-