1; Delays in CPU clocks, milliseconds, etc. All routines are re-entrant 2; (no global data). No routines touch X or Y during execution. 3; Code generated by macros is relocatable; it contains no JMPs to itself. 4 5zp_byte delay_temp_ ; only written to 6 7; Delays n clocks, from 2 to 16777215 8; Preserved: A, X, Y, flags 9.macro delay n 10 .if (n) < 0 .or (n) = 1 .or (n) > 16777215 11 .error "Delay out of range" 12 .endif 13 delay_ (n) 14.endmacro 15 16 17; Delays n milliseconds (1/1000 second) 18; n can range from 0 to 1100. 19; Preserved: A, X, Y, flags 20.macro delay_msec n 21 .if (n) < 0 .or (n) > 1100 22 .error "time out of range" 23 .endif 24 delay ((n)*CLOCK_RATE+500)/1000 25.endmacro 26 27 28; Delays n microseconds (1/1000000 second). 29; n can range from 0 to 100000. 30; Preserved: A, X, Y, flags 31.macro delay_usec n 32 .if (n) < 0 .or (n) > 100000 33 .error "time out of range" 34 .endif 35 delay ((n)*((CLOCK_RATE+50)/100)+5000)/10000 36.endmacro 37 38.align 64 39 40; Delays A clocks + overhead 41; Preserved: X, Y 42; Time: A+25 clocks (including JSR) 43: sbc #7 ; carry set by CMP 44delay_a_25_clocks: 45 cmp #7 46 bcs :- ; do multiples of 7 47 lsr a ; bit 0 48 bcs :+ 49: ; A=clocks/2, either 0,1,2,3 50 beq @zero ; 0: 5 51 lsr a 52 beq :+ ; 1: 7 53 bcc :+ ; 2: 9 54@zero: bne :+ ; 3: 11 55: rts ; (thanks to dclxvi for the algorithm) 56 57 58; Delays A*256 clocks + overhead 59; Preserved: X, Y 60; Time: A*256+16 clocks (including JSR) 61delay_256a_16_clocks: 62 cmp #0 63 bne :+ 64 rts 65delay_256a_11_clocks_: 66: pha 67 lda #256-19-22 68 jsr delay_a_25_clocks 69 pla 70 clc 71 adc #-1 72 bne :- 73 rts 74 75 76; Delays A*65536 clocks + overhead 77; Preserved: X, Y 78; Time: A*65536+16 clocks (including JSR) 79delay_65536a_16_clocks: 80 cmp #0 81 bne :+ 82 rts 83delay_65536a_11_clocks_: 84: pha 85 lda #256-19-22-13 86 jsr delay_a_25_clocks 87 lda #255 88 jsr delay_256a_11_clocks_ 89 pla 90 clc 91 adc #-1 92 bne :- 93 rts 94 95max_short_delay = 41 96 97 ; delay_short_ macro jumps into these 98 .res (max_short_delay-12)/2,$EA ; NOP 99delay_unrolled_: 100 rts 101 102.macro delay_short_ n 103 .if n < 0 .or n = 1 .or n > max_short_delay 104 .error "Internal delay error" 105 .endif 106 .if n = 0 107 ; nothing 108 .elseif n = 2 109 nop 110 .elseif n = 3 111 sta <delay_temp_ 112 .elseif n = 4 113 nop 114 nop 115 .elseif n = 5 116 sta <delay_temp_ 117 nop 118 .elseif n = 6 119 nop 120 nop 121 nop 122 .elseif n = 7 123 php 124 plp 125 .elseif n = 8 126 nop 127 nop 128 nop 129 nop 130 .elseif n = 9 131 php 132 plp 133 nop 134 .elseif n = 10 135 sta <delay_temp_ 136 php 137 plp 138 .elseif n = 11 139 php 140 plp 141 nop 142 nop 143 .elseif n = 13 144 php 145 plp 146 nop 147 nop 148 nop 149 .elseif n & 1 150 sta <delay_temp_ 151 jsr delay_unrolled_-((n-15)/2) 152 .else 153 jsr delay_unrolled_-((n-12)/2) 154 .endif 155.endmacro 156 157.macro delay_nosave_ n 158 ; 65536+17 = maximum delay using delay_256a_11_clocks_ 159 ; 255+27 = maximum delay using delay_a_25_clocks 160 ; 27 = minimum delay using delay_a_25_clocks 161 .if n > 65536+17 162 lda #^(n - 15) 163 jsr delay_65536a_11_clocks_ 164 ; +2 ensures remaining clocks is never 1 165 delay_nosave_ (((n - 15) & $FFFF) + 2) 166 .elseif n > 255+27 167 lda #>(n - 15) 168 jsr delay_256a_11_clocks_ 169 ; +2 ensures remaining clocks is never 1 170 delay_nosave_ (<(n - 15) + 2) 171 .elseif n >= 27 172 lda #<(n - 27) 173 jsr delay_a_25_clocks 174 .else 175 delay_short_ n 176 .endif 177.endmacro 178 179.macro delay_ n 180 .if n > max_short_delay 181 php 182 pha 183 delay_nosave_ (n - 14) 184 pla 185 plp 186 .else 187 delay_short_ n 188 .endif 189.endmacro 190 191