; Delays in CPU clocks, milliseconds, etc. All routines are re-entrant ; (no global data). No routines touch X or Y during execution. ; Code generated by macros is relocatable; it contains no JMPs to itself. zp_byte delay_temp_ ; only written to ; Delays n clocks, from 2 to 16777215 ; Preserved: A, X, Y, flags .macro delay n .if (n) < 0 .or (n) = 1 .or (n) > 16777215 .error "Delay out of range" .endif delay_ (n) .endmacro ; Delays n milliseconds (1/1000 second) ; n can range from 0 to 1100 usec. ; Preserved: A, X, Y, flags .macro delay_msec n .if (n) < 0 .or (n) > 1100 .error "time out of range" .endif delay ((n)*CLOCK_RATE+500)/1000 .endmacro ; Delays n microseconds (1/1000000 second). ; n can range from 0 to 100000. ; Preserved: A, X, Y, flags .macro delay_usec n .if (n) < 0 .or (n) > 100000 .error "time out of range" .endif delay ((n)*((CLOCK_RATE+50)/100)+5000)/10000 .endmacro .align 64 ; Delays A clocks + overhead ; Preserved: X, Y ; Time: A+25 clocks (including JSR) : sbc #7 ; carry set by CMP delay_a_25_clocks: cmp #7 bcs :- ; do multiples of 7 lsr a ; bit 0 bcs :+ : ; A=clocks/2, either 0,1,2,3 beq @zero ; 0: 5 lsr a beq :+ ; 1: 7 bcc :+ ; 2: 9 @zero: bne :+ ; 3: 11 : rts ; (thanks to dclxvi for the algorithm) ; Delays A*256 clocks + overhead ; Preserved: X, Y ; Time: A*256+16 clocks (including JSR) delay_256a_16_clocks: cmp #0 bne :+ rts delay_256a_11_clocks_: : pha lda #256-19-22 jsr delay_a_25_clocks pla clc adc #-1 bne :- rts ; Delays A*65536 clocks + overhead ; Preserved: X, Y ; Time: A*65536+16 clocks (including JSR) delay_65536a_16_clocks: cmp #0 bne :+ rts delay_65536a_11_clocks_: : pha lda #256-19-22-13 jsr delay_a_25_clocks lda #255 jsr delay_256a_11_clocks_ pla clc adc #-1 bne :- rts max_short_delay = 41 ; delay_short_ macro jumps into these .res (max_short_delay-12)/2,$EA ; NOP delay_unrolled_: rts .macro delay_short_ n .if n < 0 .or n = 1 .or n > max_short_delay .error "Internal delay error" .endif .if n = 0 ; nothing .elseif n = 2 nop .elseif n = 3 sta 65536+17 lda #^(n - 15) jsr delay_65536a_11_clocks_ ; +2 ensures remaining clocks is never 1 delay_nosave_ (((n - 15) & $FFFF) + 2) .elseif n > 255+27 lda #>(n - 15) jsr delay_256a_11_clocks_ ; +2 ensures remaining clocks is never 1 delay_nosave_ (<(n - 15) + 2) .elseif n >= 27 lda #<(n - 27) jsr delay_a_25_clocks .else delay_short_ n .endif .endmacro .macro delay_ n .if n > max_short_delay php pha delay_nosave_ (n - 14) pla plp .else delay_short_ n .endif .endmacro