home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Go64!
/
Go64_1999-08_1999_CSW_Side_A.d64
/
inputdrvsrc.txt
< prev
next >
Wrap
Text File
|
2023-02-26
|
14KB
|
626 lines
;ACME 0.07
; --- Configurable values
; Start address
*=$c000; C64 value
;*=$0c00; C128 value
; Output file name
!to "inputdrv64.bin"; C64 file name
;!to "inputdrv128.bin"; C128 file name
; Pointer's maximum coordinates
MaximumCoordinateX = 319; VIC value
;MaximumCoordinateX = 639; VDC value
MaximumCoordinateY = 199
; Maximum step size ("speed") for
; joystick acceleration routine, in
; pixels.
MaxStep = $10; (max. $7f)
; Distance before acceleration starts,
; in pixels.
MaxTime = $04; (max. $7f)
; Sprites to use for overlay pointer
Sprite_A = 0
Sprite_B = 1
; Coordinates of "pointer pixel" within
; pointer sprites; adjust these if you
; use different sprites.
; (0,0) is sprite's upper left pixel.
Sprite_HotspotX = 1
Sprite_HotspotY = 1
; Base of VIC registers to write to.
VIC_Base = $d000; C64 value
;VIC_Base = $11d6; C128 value, location
; of mirror registers.
; Locations to store button states,
; $ff = pressed, $00 = not pressed.
; Mouse uses both buttons, joystick
; only uses "LeftButton".
LeftButton = $a4; C64 value
RightButton = $a5; C64 value
;LeftButton = $fa; C128 value
;RightButton = $ff; C128 value
; Location to store pointer's current
; pixel coordinates. The driver code
; relies on having *four consecutive*
; bytes:
; x low, x high, y low, y high.
Coordinates = $fb; $fb-$fe
; Location to store pointer's current
; character coordinates.
CharX = $b3; C64 value
CharY = $b4; C64 value
;CharX = $9b; C128 value
;CharY = $9c; C128 value
; --- System constants
; Interrupt vector
sys_iirq = $0314
; I/O registers
sid_pot = $d419
cia1_pra = $dc00
cia1_prb = $dc01
cia1_ddrb = $dc03
;mmu_cr = $ff00; C128 only
; --- Label definitions
; New names for some precalculated
; values, only to improve readability.
; Don't change these.
PointerXnow = Coordinates
PointerYnow = Coordinates+2
SpriteA_X = VIC_Base+2*Sprite_A
SpriteA_Y = VIC_Base+2*Sprite_A+1
SpriteB_X = VIC_Base+2*Sprite_B
SpriteB_Y = VIC_Base+2*Sprite_B+1
Sprites_OF = VIC_Base+16; X Overflow
; The character "^" in the following
; calculation means "to the power of".
; It is ACME syntax - if your assembler
; cannot do this, you may want to use
; hardcoded values here instead of
; calculations.
Sprites_Bitmask = 2^Sprite_A+2^Sprite_B
SpriteOffset_X = $18-Sprite_HotspotX
SpriteOffset_Y = $32-Sprite_HotspotY
; In the sprite coordinate system, the
; graphics pixel (0,0) has the
; coordinates ($18,$32), so these are
; needed for converting. Blame the VIC.
; --- Entry point
; Because this routine is the first,
; the file can be BOOTed on a C128.
Init
; Initialisation code, installs driver
; on IRQ vector.
; Fetch IRQ vector and write to end
lda sys_iirq
ldx sys_iirq+1
sta mod16+1
stx mod16+2
; Let IRQ vector point to driver code
lda #<Entry
ldx #>Entry
php
sei
sta sys_iirq
stx sys_iirq+1
plp
; The following five commands are only
; needed on the C128.
; lda mmu_cr
; tay
; and #$fe; activate I/O chips
; sta mmu_cr
; Init mouse buttons
lda #$11
sta cia1_prb
; sty mmu_cr; C128 only
; The following three mini-routines are
; only needed on the C64.
; Copy sprites to tape buffer
ldx #127
CpLp lda Sprites,x
sta $0340,x
dex
bpl CpLp
lda #Sprites_Bitmask
; Set sprite block pointers
ldx #$0d
stx 2040+Sprite_A
inx
stx 2040+Sprite_B
; Activate pointer sprites
ora VIC_Base+21
sta VIC_Base+21
; From here on, both C64+C128 again. :)
rts
; --- Variables
; Pixel counter before accelerating
JoyWaittime !byte 0
; --- Main code
Entry
; The driver consists of several
; distinct parts. To minimise
; performance wastage, you should
; remove all parts you don't need for
; the specific application.
; --- Part 0, initialisations
; Make sure decimal mode is off
cld
; Set button states to "not pressed",
; so the other parts only have to deal
; with setting them to "pressed".
lda #$00
sta LeftButton
sta RightButton
; --- Part 1, handling mouse movements
; mouse x
ldx #$00; 0 means "x stuff"
jsr PotDelta
; Now signed x movement is in A/Y.
; Add to current x value.
clc
adc PointerXnow
sta PointerXnow
tya
adc PointerXnow+1
sta PointerXnow+1
; mouse y
ldx #$01; 1 means "y stuff"
jsr PotDelta
; Now signed y movement is in A/Y.
; Mouse and computer use different y
; directions, so don't add to, but
; subtract from current y value.
; This is a reverse subtraction - it
; might be harder to understand, but it
; is faster and smaller than the usual
; way.
clc
sbc PointerYnow
eor #$ff
sta PointerYnow
tya
sbc PointerYnow+1
eor #$ff
sta PointerYnow+1
; --- Part 2, handling mouse buttons
; Prepare CIA by setting bits to input
ldy #$11
sty cia1_ddrb
ldx #$ff; $ff means "pressed"
lda #$10; check left button
bit cia1_prb
bne NotLB
stx LeftButton; store state
NotLB lda #$01; check right button
bit cia1_prb
bne NotRB
stx RightButton; store state
; Reset CIA to normal state
NotRB ldy #$00
sty cia1_ddrb
; --- Part 3, handling the joystick
; Fetch byte holding direction flags
lda cia1_pra
tax; ...and remember it
; Check 'up' direction
ror
bcs down
; Subtract current step size from y
; value if needed.
tay
sec
lda PointerYnow
sbc JoyStepsize
sta PointerYnow
bcs fixHiUp
dec PointerYnow+1
fixHiUp tya
; Check 'down' direction
down ror
bcs left
; Add current step size to y value if
; needed.
tay
;clc; C is always clear here
lda PointerYnow
adc JoyStepsize
sta PointerYnow
bcc fixHiDown
inc PointerYnow+1
fixHiDown tya
; Check 'left' direction
left ror
bcs right
; Subtract current step size from x
; value if needed.
tay
sec
lda PointerXnow
sbc JoyStepsize
sta PointerXnow
bcs fixHiLeft
dec PointerXnow+1
fixHiLeft tya
; Check 'right' direction
right ror
bcs Part3End
; Add current step size to x value if
; needed.
tay
;clc; C is always clear here
lda PointerXnow
adc JoyStepsize
sta PointerXnow
bcc fixHiRight
inc PointerXnow+1
fixHiRight tya
Part3End
; --- Part 4, handling joystick button
ror
bcs Part4End
lda #$ff; $ff means "pressed"
sta LeftButton
Part4End
; --- Part 5, joystick acceleration
; Restore joystick direction bits and
; check whether to set speed to zero.
txa
and #$0f; Clear unneeded bits
cmp #$0f; Any direction bit ?
bne inctempo
; No direction was used, so reset speed
; and wait counter to normal.
lda #$01
sta JoyStepsize
lda #MaxTime
sta JoyWaittime
jmp Part5End
inctempo
; A direction bit was used, so check
; whether to accelerate: If speed is
; already maximum speed, don't
; accelerate.
JoyStepsize=*+1
lda #$00; (self-modifying)
; If the variable "JoyStepsize" would
; have been defined as a separate
; location (using "!byte"), it would
; have taken a byte of memory. By
; storing the value inside an LDA
; command's argument, we save that one
; byte. It might make a difference. :)
cmp #MaxStep; If speed is max.,
bcs Part5End; don't accelerate.
; Speed isn't maximum yet. Check
; whether we have to wait before
; accelerating.
dec JoyWaittime
bpl Part5End
; Counter has underrun, so accelerate.
inc JoyWaittime; reset counter
inc JoyStepsize; increase speed
Part5End
; --- Part 6, restrict coordinate range
; restrict x value
ldx #$00; 0 means "x stuff"
jsr Restrict
; restrict y value
ldx #$02; 2 means "y stuff"
jsr Restrict
; --- Part 7, positioning sprites
; Set sprites' x positions
lda PointerXnow
clc
adc #SpriteOffset_X
sta SpriteA_X; set both sprites
sta SpriteB_X
lda Sprites_OF; get x overflow
bcs SetOF
ldx PointerXnow+1
bne SetOF
and #Sprites_Bitmask EOR $ff
bcc StoreOF; C is clear here
SetOF ora #Sprites_Bitmask
StoreOF sta Sprites_OF; set x overflow
; Set sprites' y positions
lda PointerYnow
clc
adc #SpriteOffset_Y
sta SpriteA_Y
sta SpriteB_Y
; The y value's high byte is useless in
; this case.
; --- Part 8, making char coordinates
; Convert x coordinate. There are
; different "best" routines for
; different resolutions, so I've given
; the VIC and VDC routines.
lda PointerXnow
lsr
lsr
lsr
ldx PointerXnow+1
beq SetCX; VIC only
ora #$20; VIC only
; ora OrTable,x; VDC only
SetCX sta CharX
; Convert y coordinate.
lda PointerYnow
lsr
lsr
lsr
sta CharY
; --- Add further parts here
; Here you can add further routines,
; for example to use the button states
; to fake keypresses etc.
; --- The end
; The initialisation routine sets the
; argument to the address of the
; previous IRQ routine.
mod16 jmp $ffff; (self-modifying)
; This table is for part 8.
;OrTable !byte 0,32,64; VDC only
; --- "Restrict" subroutine
PointerXmax !word MaximumCoordinateX
PointerYmax !word MaximumCoordinateY
; "y" word must follow directly after
; "x" word in memory.
Restrict
; Restrict internal coordinates to
; configured range. Entry conditions:
; X is direction handle (0 = x, 2 = y)
lda PointerXnow+1,x
bmi SetTo0
cmp PointerXmax+1,x
bcc Eosr
bne ResetCo
lda PointerXmax,x
cmp PointerXnow,x
bcs Eosr
ResetCo lda PointerXmax,x
ldy PointerXmax+1,x
jmp DefCo
SetTo0 lda #0
tay
DefCo sta PointerXnow,x
sty PointerXnow+1,x
Eosr rts
; --- "Pot" subroutine
; This routine computes the mouse
; movements and therefore contains the
; self-calibration stuff and the other
; improvements over the standard 1351
; driver.
PotMax !word 0; max. POTs yet plus 1 !
PotMin !word $ffff; lowest POTs yet
PotOld !word 0; old values
PotWidth !word 0; interval width
HalfPotWidth !word 0; half width
; (buffered for speed increase)
; The above variables are not really
; words: The first byte is the x value,
; the second byte is the y value
; respectively.
PotDelta
; Compute the signed distance of mouse
; movement. Entry conditions:
; X is direction handle (0 = x, 1 = y)
; Exit conditions:
; A/Y are signed distance (low/high)
; First, get new value and clear
; "recalculate signal width" flag.
lda sid_pot,x
ldy #$00
; Check whether new value is lower than
; lowest known.
cmp PotMin,x
bcs m0
; Store new "lowest" und set
; "recalculate signal width" flag.
sta PotMin,x
ldy #$ff
; Check whether new value is higher
; than highest known.
m0 cmp PotMax,x
bcc m1
; Set "recalculate signal width" flag
; and store new "highest".
ldy #$ff
pha; Remember current value
adc #$00; Add one (C is set)
sta PotMax,x
; Value $ff (0 after adding) means that
; there is no mouse connected, so reset
; min/max in that case.
beq ResetMM; Stack is untidy...
pla; Restore current value
; If flag is set, recalculate signal
; width.
m1
iny; Check flag
bne m3
tay; Buffer current value.
lda PotMax,x; Get highest+1
sec; Subtract lowest
sbc PotMin,x
bcc m2
sta PotWidth,x; Store signal
lsr; width and half signal
sta HalfPotWidth,x; width
m2 tya; Restore current value.
; Calculate distance
m3 tay; Buffer current value.
sec
sbc PotOld,x
pha
tya
sta PotOld,x
pla
beq zero; If not moved, exit.
bcc minus; Negative difference
; Positive difference:
; Check whether movement caused a value
; wrap-around.
cmp HalfPotWidth,x
bcc Decrease
beq Decrease
; It did, so calculate "real" distance
; and jump to exit
;sec; C is always set here
sbc PotWidth,x; Fix distance
; We now know that the (fixed) distance
; is really negative, so we finally
; wipe out that annoying bit 0 noise by
; incrementing the value.
Increase
;clc; C is always clear here
adc #$01
beq zero; If increasing
; delivers zero, jump to zero handler.
ldy #$ff; Set up high byte for
; negative values.
rts
; Negative difference:
; Check whether movement caused a value
; wrap-around.
minus eor #$ff; Complement
; If we would do a real negation (by
; adding "1"), then we would need to
; branch using BCC *and* BEQ. So the
; above way might be harder to
; understand, but it is both shorter
; *and* faster - which I like. :)
cmp HalfPotWidth,x
eor #$ff; Restore value
bcc Increase
; Movement caused a value wrap-around,
; so calculate "real" distance and
; exit.
clc
adc PotWidth,x; Fix distance
; We now know that the (fixed) distance
; is really positive, so we finally
; wipe out that annoying bit 0 noise by
; decrementing the value.
Decrease
sec
sbc #$01
; No difference or positive difference;
; both need zero as the high byte.
zero ldy #0
rts
; If there is no mouse, reset "lowest"
; ("highest" will have been reset
; already) and return zero.
ResetMM tay; Set Y to zero.
pla; Tidy stack
lda #$ff; Reset "lowest"
sta PotMin,x
tya; Return with A/Y = 0
rts
; --- Include sprites
; Because the C64 version copies the
; sprite data into the tape buffer on
; initialisation, the data is included
; right here.
; In the C128 version, we skip memory
; until we reach $0e00 - this is where
; the sprites are stored by default.
; !align $ffff,$e00,$0;C128 only
Sprites !binary "pointersprites",, 2