diff --git a/drivers/Makefile b/drivers/Makefile index a799114..0d24b7e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -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=\ diff --git a/drivers/atr_timer.s b/drivers/atr_timer.s deleted file mode 100644 index 40ba3b3..0000000 --- a/drivers/atr_timer.s +++ /dev/null @@ -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 - 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 -- diff --git a/drivers/c64_cps.s b/drivers/c64_cps.s new file mode 100644 index 0000000..dbecd6f --- /dev/null +++ b/drivers/c64_cps.s @@ -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 diff --git a/drivers/clk_timer.s b/drivers/clk_timer.s new file mode 100644 index 0000000..53a473b --- /dev/null +++ b/drivers/clk_timer.s @@ -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 + bne @timerset ; jmp always +@timer50: + lda #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 --