Use CC65 runtime for Atari and C64 timer functions

This is just for the "C" interface of IP65. clk_timer.s replaces
atr_timer.s (on Atari) and is new for the C64 (there wasn't an
implementation for the "C" interface before).
This commit is contained in:
Christian Groessler 2018-02-02 20:34:59 +01:00
parent 673e2da011
commit afada39f9a
4 changed files with 188 additions and 144 deletions

View File

@ -55,7 +55,8 @@ C64OBJS=\
cbmcharconv.o
C64_OBJS=\
c64timer.o \
clk_timer.o \
c64_cps.o \
c64_input.o
A2OBJS=\
@ -82,11 +83,11 @@ ATROBJS=\
atrcharconv.o
ATR_OBJS=\
atr_timer.o \
clk_timer.o \
atr_input.o
ATRXL_OBJS=\
atr_timer.xl.o \
clk_timer.xl.o \
atr_input.xl.o
VIC20OBJS=\

View File

@ -1,141 +0,0 @@
; timer routines
;
; the timer should be a 16-bit counter that's incremented by about
; 1000 units per second. it doesn't have to be particularly accurate.
.include "atari.inc"
.include "../inc/common.i"
.export timer_init
.export timer_read
.export timer_seconds
.import _atexit
.bss
current_time_value: .res 2
current_seconds: .res 1
current_jiffies: .res 1
timer_freq: .res 1 ; VBLANK frequency: 50 - PAL, 60 - NTSC
timer_freq_reciproc:.res 1 ; reciprocal for timer_freq in ms: 20 - PAL, ~17 - NTSC
.data
vbichain: .word 0
.code
; reset timer to 0 and install handler
; inputs: none
; outputs: none
timer_init:
lda vbichain+1
bne @done
lda PAL ; hardware register describing TV system of GTIA
and #$0e ; mask out irrelevant bits
bne @ntsc
; PAL system
lda #50
sta timer_freq
lda #20
sta timer_freq_reciproc
bne @system_set
@ntsc:
; NTSC system
lda #60
sta timer_freq
lda #17
sta timer_freq_reciproc
@system_set:
lda #0 ; initialize time variables
sta current_time_value
sta current_time_value+1
sta current_seconds
sta current_jiffies
ldax VVBLKI ; IMMEDIATE VERTICAL BLANK NMI VECTOR
stax vbichain ; save old immediate vector
ldy #<timer_vbl_handler
ldx #>timer_vbl_handler
lda #6 ; STAGE 1 VBI
jsr SETVBV ; vector to set VBLANK parameters
@done:
ldax #timer_exit
jmp _atexit
timer_exit:
lda vbichain+1
beq @handler_not_installed
ldy vbichain
ldx vbichain+1
lda #6 ; STAGE 1 VBI
jsr SETVBV ; vector to set VBLANK parameters
lda #0
sta vbichain
sta vbichain+1
@handler_not_installed:
rts
; read the current timer value
; inputs: none
; outputs: AX = current timer value (roughly equal to number of milliseconds since the last call to 'timer_init')
timer_read:
ldax current_time_value
rts
; tick over the current timer value - should be called 50 or 60 times per second, depending on the TV system
; inputs: none
; outputs: none (all registers preserved, but carry flag can be modified)
timer_vbl_handler:
pha
lda timer_freq_reciproc ; ms per tick
clc
adc current_time_value
sta current_time_value
bcc :+
inc current_time_value+1
: inc current_jiffies
lda current_jiffies
cmp timer_freq ; full second?
bne @done ; no, we're done
lda #0 ; yes, increment "seconds" counter
sta current_jiffies
sed
clc
lda #$01
adc current_seconds
cld
cmp #$60
bne :+
lda #$00
: sta current_seconds
@done:
pla
jmp SYSVBV ; vector to process immediate VBLANK
timer_seconds:
lda current_seconds
rts
;-- LICENSE FOR atr_timer.s --
; The contents of this file are subject to the Mozilla Public License
; Version 1.1 (the "License"); you may not use this file except in
; compliance with the License. You may obtain a copy of the License at
; http://www.mozilla.org/MPL/
;
; Software distributed under the License is distributed on an "AS IS"
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
; License for the specific language governing rights and limitations
; under the License.
;
; The Original Code is ip65.
;
; The Initial Developer of the Original Code is Jonno Downes,
; jonno@jamtronix.com.
; Portions created by the Initial Developer are Copyright (C) 2009
; Jonno Downes. All Rights Reserved.
; -- LICENSE END --

13
drivers/c64_cps.s Normal file
View File

@ -0,0 +1,13 @@
; implementation of __clocks_per_sec for C64
; CC65's C64 runtime library doesn't provide this function
; this file provides a version in order that clk_timer.s works without 'ifdefs'
.export __clocks_per_sec
.code
__clocks_per_sec:
lda #60
rts
.end

171
drivers/clk_timer.s Normal file
View File

@ -0,0 +1,171 @@
; timer routines
; this implementation is for Atari and C64.
; it uses parts of the C runtime library
;
; the timer should be a 16-bit counter that's incremented by about
; 1000 units per second. it doesn't have to be particularly accurate.
.include "../inc/common.i"
.export timer_init
.export timer_read
.export timer_seconds
.import __clocks_per_sec, _clock
.import tosumodeax, tosudiveax
.import pusheax, incsp4
.importzp sp, sreg
.bss
timer_freq: .res 1 ; VBLANK frequency: 50 - PAL, 60 - NTSC (Atari); always 60 (C64)
mult_temp: .res 2 ; temp var for multiplication routines
mult_temp_x:.res 1 ; another temp var for multiplication routines
.data
mult: .byte $4C ; JMP opcode
.res 2 ; address
.code
; get timer frequency and patch multiplication routine pointer
; inputs: none
; outputs: none
timer_init:
jsr __clocks_per_sec
sta timer_freq
cmp #50
beq @timer50
lda #<mult17
ldx #>mult17
bne @timerset ; jmp always
@timer50:
lda #<mult20
ldx #>mult20
@timerset:
sta mult+1
stx mult+2
rts
; read the current timer value
; inputs: none
; outputs: AX = current timer value in milliseconds
timer_read = mult
; get current seconds clock hand
; inputs: none
; outputs: A = seconds hand (in BCD, range $00..$59)
timer_seconds:
jsr _clock ; return current tick count in sreg:AX (high:low 16bits)
jsr pusheax ; push tick count onto stack
ldx #0
stx sreg
stx sreg+1
lda timer_freq
jsr tosudiveax ; dividend on stack, divisor in sreg:AX
jsr pusheax
ldx #0
stx sreg
stx sreg+1
lda #60
jsr tosumodeax ; result modulo 60
; convert to BCD, a poor man's conversion here....
cmp #50
bcs @rs_50
cmp #40
bcs @rs_40
cmp #30
bcs @rs_30
cmp #20
bcs @rs_20
cmp #10
bcs @rs_10
rts
@rs_10:
sbc #10
ora #$10
rts
@rs_20:
sbc #20
ora #$20
rts
@rs_30:
sbc #30
ora #$30
rts
@rs_40:
sbc #40
ora #$40
rts
@rs_50:
sbc #50
ora #$50
rts
; get the current tick count, multiply it by 20, and return the lower 16 bits
; x*20 = x*16 + x*4
; inputs: none
; outputs: AX - tick count times 20 ('milliseconds')
mult20:
jsr _clock ; return current tick count in sreg:AX (high:low 16bits)
stx mult_temp_x ; remember high byte of lower 16bits
asl a
rol mult_temp_x
asl a
rol mult_temp_x
sta mult_temp
ldx mult_temp_x
stx mult_temp+1 ; mult_temp = ticks * 4
asl a
rol mult_temp_x
asl a
rol mult_temp_x ; mult_temp_x:A = 'ticks * 16'
clc ; AX - tick count * 16, mult_temp - tick count * 4
adc mult_temp
sta mult_temp
lda mult_temp+1
adc mult_temp_x
tax
lda mult_temp
rts
; get the current tick count, multiply it by 17, and return the lower 16 bits
; x*17 = x*16 + x
; inputs: none
; outputs: AX - tick count times 17 ('milliseconds')
mult17:
jsr _clock ; return current tick count in sreg:AX (high:low 16bits)
sta mult_temp
stx mult_temp+1
stx mult_temp_x
.repeat 4
asl a
rol mult_temp_x
.endrepeat ; mult_temp_x:A = 'ticks * 16'
clc
adc mult_temp
sta mult_temp
lda mult_temp+1
adc mult_temp_x
tax
lda mult_temp
rts
;-- LICENSE FOR clk_timer.s --
; The contents of this file are subject to the Mozilla Public License
; Version 1.1 (the "License"); you may not use this file except in
; compliance with the License. You may obtain a copy of the License at
; http://www.mozilla.org/MPL/
;
; Software distributed under the License is distributed on an "AS IS"
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
; License for the specific language governing rights and limitations
; under the License.
; -- LICENSE END --