+++ /dev/null
-;
-; Ullrich von Bassewitz, 19.09.2001
-;
-; Routines for the 1351 proportional mouse. Parts of the code are from
-; the Commodore 1351 mouse users guide.
-;
-
- .export _mouse_init, _mouse_done
- .export _mouse_hide, _mouse_show
- .export _mouse_box, _mouse_info
- .export _mouse_move, _mouse_pos
- .export _mouse_buttons, _mouse_info
- .condes MouseIRQ, 2
-
- .import _readjoy
- .import sys_bank, restore_bank
- .import popax, addysp1
- .importzp vic, sid, ptr1, sp
-
- .include "cbm510.inc"
-
- .macpack generic
-
-
-.code
-
-; --------------------------------------------------------------------------
-;
-; Constants
-;
-
-SPRITE_HEIGHT = 21
-SPRITE_WIDTH = 24
-SCREEN_HEIGHT = 200
-SCREEN_WIDTH = 320
-XCORR = SPRITE_WIDTH
-
-; --------------------------------------------------------------------------
-;
-; unsigned char __fastcall__ mouse_init (unsigned char type);
-;
-
-.proc _mouse_init
- lda Initialized ; Already initialized?
- bne AlreadyInitialized ; Jump if yes
-
-; Initialize variables
-
- ldx #0
- lda #XCORR
- sta XPos
- stx XPos+1
- stx YPos
- stx YPos+1
- stx OldPotX
- stx OldPotY
- stx XMin
- 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 Invisible ; Mouse *not* visible
- lda #<(SCREEN_WIDTH + SPRITE_WIDTH)
- sta XMax
- stx XMax+1 ; XMax = 320 + sprite width
-
-; Mouse successfully initialized
-
- lda #1
- sta Initialized
- rts
-
-AlreadyInitialized:
- lda #0 ; Error
- rts
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; void mouse_done (void);
-;
-
-_mouse_done:
-
- lda #0
- sta Initialized ; Reset the initialized flag
-
-; Disable the mouse sprite
-
-DisableSprite:
-
- ldx IndReg
- lda #$0F
- sta IndReg ; Switch to the system bank
-
- ldy #VIC_SPR_ENA
- sei ; Disable interrupts
- lda (vic),y
- and #$FE ; Clear bit for sprite #0
- sta (vic),y ; Disable sprite
- cli ; Enable interrupts
-
- stx IndReg ; Switch back the segment
- rts
-
-; --------------------------------------------------------------------------
-;
-; void mouse_hide (void);
-;
-
-.proc _mouse_hide
-
- lda Invisible ; Get the flag
- bne @L1 ; Jump if already invisible
- jsr DisableSprite ; Disabe the mouse sprite
-@L1: inc Invisible ; Set the flag to invisible
- rts
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; void mouse_show (void);
-;
-
-.proc _mouse_show
-
- lda Invisible ; Mouse invisible?
- beq @L1 ; Jump if no
- dec Invisible ; Set the flag
- bne @L1 ; Jump if still invisible
-
- jsr sys_bank ; Switch to the system bank
-
- sei ; Disable interrupts
- jsr MoveSprite1 ; Move the sprite to it's position
- ldy #VIC_SPR_ENA
- lda (vic),y ; Get sprite enable register
- ora #$01 ; Enable sprite #0
- sta (vic),y ; Write back
- cli ; Enable interrupts
-
- jsr restore_bank ; Switch back the bank
-
-@L1: rts
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; void __fastcall__ mouse_box (int minx, int miny, int maxx, int maxy);
-;
-
-.proc _mouse_box
-
- ldy #0 ; Stack offset
-
- add YCorr ; Adjust the Y value
- bcc @L1
- inx
- clc
-@L1: sei ; Disable interrupts
-
- sta YMax
- stx YMax+1 ; maxy
-
- lda (sp),y
- adc #XCORR
- sta XMax
- iny
- lda (sp),y
- adc #$00
- sta XMax+1 ; maxx
-
- iny
- lda (sp),y
- add YCorr
- sta YMin
- iny
- lda (sp),y
- adc #$00
- sta YMin+1 ; miny
-
- iny
- lda (sp),y
- add #XCORR
- sta XMin
- iny
- lda (sp),y
- adc #$00
- sta XMin+1 ; minx
-
- cli ; Enable interrupts
-
- jmp addysp1 ; Drop params, return
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; void __fastcall__ mouse_pos (struct mouse_pos* pos);
-; /* Return the current mouse position */
-;
-
-.proc _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
-
- sub YCorr ; Apply the Y correction value
- bcs @L1
- dex
-@L1: iny
- sta (ptr1),y ; Store YPos
- txa
- iny
- sta (ptr1),y
-
- rts ; Done
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; void __fastcall__ mouse_info (struct mouse_info* info);
-; /* Return the state of the mouse buttons and the position of the mouse */
-;
-
-.proc _mouse_info
-
-; 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
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; void __fastcall__ mouse_move (int x, int y);
-;
-
-.proc _mouse_move
-
- 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: jsr sys_bank
- sei
- sta XPos
- stx XPos+1 ; Set new position
- jsr MoveSprite ; Move the sprite to the mouse pos
- cli ; Enable interrupts
- jsr restore_bank
-
- rts
-
-.endproc
-
-; --------------------------------------------------------------------------
-;
-; unsigned char mouse_buttons (void);
-;
-
-.proc _mouse_buttons
-
- lda #$00 ; Use port #0
- jmp _readjoy ; Same as joystick
-
-.endproc
-
-
-; --------------------------------------------------------------------------
-;
-; Mouse interrupt handler
-;
-
-IRQDone:rts
-
-MouseIRQ:
- lda Initialized ; Mouse initialized?
- beq IRQDone ; Jump if no
-
- ldy #SID_ADConv1
- lda (sid),y ; Get mouse X movement
- ldy OldPotX
- jsr MoveCheck ; Calculate movement vector
- sty OldPotX
-
-; Calculate the new X coordinate (--> a/y)
-
- 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
-
-; Calculate the Y movement vector
-
- ldy #SID_ADConv2
- lda (sid),y ; Get mouse Y movement
- ldy OldPotY
- jsr MoveCheck ; Calculate movement
- sty OldPotY
-
-; Calculate the new Y coordinate (--> a/y)
-
- sta OldValue
- lda YPos
- sub OldValue
- tay
- stx OldValue
- lda YPos+1
- sbc OldValue
- tax
-
- 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 sprite to the current mouse position. Must be called
-; with interrupts off and the system bank enabled. MoveSprite1 is an entry
-; without checking.
-
-MoveSprite:
-
- lda Invisible ; Mouse visible?
- bne Done ; Jump if no
-
-; Set the high X bit
-
-MoveSprite1:
- ldy #VIC_SPR_HI_X
- lda (vic),y ; Get high X bits of all sprites
- and #$FE ; Clear bit for sprite #0
- ldx XPos+1 ; Test Y position
- beq @L5
- ora #$01 ; Set high X bit
-@L5: sta (vic),y ; Set hi X sprite values
-
-; Set the low X byte
-
- lda XPos
- ldy #VIC_SPR0_X
- sta (vic),y ; Set low byte
-
-; Set the Y position
-
- ldy YPos+1 ; Negative or too large?
- bne Done ; Jump if yes
- lda YPos
- ldy #VIC_SPR0_Y
- sta (vic),y ; Set Y position
-
-; Done
-
-Done: rts
-
-; --------------------------------------------------------------------------
-;
-; Move check routine, called for both coordinates.
-;
-; Entry: y = old value of pot register
-; a = current value of pot register
-; Exit: y = value to use for old value
-; x/a = delta value for position
-;
-
-.proc MoveCheck
-
- sty OldValue
- sta NewValue
- ldx #$00
-
- 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)
- beq @L2
- sec
- ror a ; a /= 2
- dex ; high byte = -1 (X = $FF)
- ldy NewValue
- rts
-
-@L2: txa ; A = $00
- rts
-
-.endproc
-
-; --------------------------------------------------------------------------
-; Data
-
-.bss
-
-Initialized: .res 1 ; True if mouse initialized
-OldInitStatus: .res 1 ; Old IRQ flag value
-OldValue: .res 1 ; Temp for MoveCheck routine
-NewValue: .res 1 ; Temp for MoveCheck routine
-YCorr: .res 1 ; Correction for Y coordinate
-
-Invisible: .res 1 ; Is the mouse invisible?
-OldPotX: .res 1 ; Old hw counter values
-OldPotY: .res 1
-
-XPos: .res 2 ; Current mouse position, X
-YPos: .res 2 ; Current mouse position, Y
-
-XMin: .res 2 ; X1 value of bounding box
-YMin: .res 2 ; Y1 value of bounding box
-XMax: .res 2 ; X2 value of bounding box
-YMax: .res 2 ; Y2 value of bounding box
-
-