Here is my findings so far.
First, a snippet of the key assembly code:
Code:
;start tape motor
.02AF 202 034 64523752 A9 1F LDA #$1F fe0108ee
.02B1 202 036 64523754 85 01 STA $01 1f0108ee
.02B3 202 039 64523757 A0 00 LDY #$00 1f0108ee
.02B5 202 041 64523759 8C F6 02 STY $02F6 1f0100ee
.02B8 202 045 64523763 8C 05 DD STY $DD05 1f0100ee
.02BB 202 049 64523767 8C 07 DD STY $DD07 1f0100ee
.02BE 202 053 64523771 8C 06 DD STY $DD06 1f0100ee
.02C1 202 057 64523775 A9 5A LDA #$5A 1f0100ee
.02C3 202 059 64523777 8D 04 DD STA $DD04 5a0100ee
.02C6 203 000 64523781 20 4A 03 JSR $034A 5a0100ee
;subroutine
==========================
.0128 288 041 67575857 A5 A5 LDA $A5 001200ea
.012A 288 044 67575860 D0 24 BNE $0150 c81200ea
.012C 178 005 67588547 A9 10 LDA #$10 000100ea
.012E 287 001 67575754 2C 0D DC BIT $DC0D 100100ea
.0131 287 005 67575758 F0 FB BEQ $012E 100100ea ; loop till end off pulse
.0133 287 007 67575760 AD 06 DD LDA $DD06 100100ea
.0136 287 011 67575764 4A LSR A ff0100ea
.0137 287 013 67575766 AA TAX 7f0100ea
.0138 287 015 67575768 BD F9 03 LDA $03F9,X 7f7f00ea ; lookup new value to store in timer
.013B 287 020 67575773 8D 06 DD STA $DD06 207f00ea
.013E 287 024 67575777 A9 51 LDA #$51 207f00ea
.0140 287 026 67575779 8D 0E DD STA $DD0E 517f00ea
.0143 287 030 67575783 8D 0F DD STA $DD0F 517f00ea
.0146 287 034 67575787 BD ED 02 LDA $02ED,X 517f00ea
.0149 287 039 67575792 85 A4 STA $A4 dd7f00ea ; value to rotate into A3
.014B 287 042 67575795 BD F1 02 LDA $02F1,X dd7f00ea
.014E 287 047 67575800 85 A5 STA $A5 c97f00ea ; lookup new value to store for looping
.0150 287 050 67575803 C6 A5 DEC $A5 c97f00ea
.0152 287 055 67575808 46 A4 LSR $A4 c97f00ea
.0154 287 060 67575813 26 A3 ROL $A3 c97f00ea
.0156 288 002 67575818 60 RTS c97f00ea
===================================
.034A 288 020 67575836 A9 2C LDA #$2C c91200ec
.034C 288 022 67575838 8D EA 03 STA $03EA 2c1200ec ; change opcode to bit
.034F 288 026 67575842 A9 00 LDA #$00 2c1200ec
.0351 288 028 67575844 8D 20 D0 STA $D020 001200ec
.0354 288 032 67575848 85 9E STA $9E 001200ec
.0356 288 035 67575851 20 28 01 JSR $0128 001200ec
.0359 288 008 67575824 A6 A3 LDX $A3 c97f00ec
.035B 288 011 67575827 E8 INX c91100ec
.035C 288 013 67575829 F0 E7 BEQ $0345 c91200ec
.035E 288 015 67575831 E0 02 CPX #$02 c91200ec
.0360 288 017 67575833 D0 E8 BNE $034A c91200ec
.0362 140 035 68333111 A6 9E LDX $9E 010200ec
.0364 140 038 68333114 D0 E4 BNE $034A 010000ec
.0366 140 040 68333116 20 E3 03 JSR $03E3 010000ec ; Update $9E
.0369 189 056 68336219 C9 66 CMP #$66 666600ec ; and check returned value in Acc
.036B 189 058 68336221 D0 DD BNE $034A 666600ec ; jump back
.036D 189 060 68336223 20 E3 03 JSR $03E3 666600ec
.0370 233 039 68338974 C9 1B CMP #$1B 1b1b00ec ; check returned value
.0372 233 041 68338976 D0 D6 BNE $034A 1b1b00ec ; jump back
.0374 233 043 68338978 A9 EE LDA #$EE 1b1b00ec
.0376 233 045 68338980 8D EA 03 STA $03EA ee1b00ec ; change opcode to INC
.0379 233 049 68338984 A9 00 LDA #$00 ee1b00ec
.037B 233 051 68338986 85 9E STA $9E 001b00ec
.037D 233 054 68338989 20 E3 03 JSR $03E3 001b00ec
.0380 277 017 68341724 CD F5 02 CMP $02F5 000000ec
.0383 277 021 68341728 F0 04 BEQ $0389 000000ec
===================================
;subroutine
.03E3 138 042 68391960 A9 01 LDA #$01 2c2cf4ea
.03E5 138 044 68391962 85 A3 STA $A3 012cf4ea
.03E7 138 047 68391965 20 28 01 JSR $0128 012cf4ea
.03EA 185 037 67589020 2C 20 D0 BIT $D020 9d0000ea
.03ED 185 041 67589024 90 F8 BCC $03E7 9d0000ea
.03EF 190 051 67589349 A6 A3 LDX $A3 960000ea
.03F1 190 054 67589352 38 SEC 960000ea
.03F2 190 056 67589354 8A TXA 960000ea
.03F3 190 058 67589356 65 9E ADC $9E 000000ea
.03F5 190 061 67589359 85 9E STA $9E 010000ea
.03F7 191 001 67589362 8A TXA 010000ea
.03F8 191 003 67589364 60 RTS 000000ea
I got this source code via a raw trace from Vice, so don't worry about the extra numbers.
We start at address 2AF where we switch on the tape motor. At this point in time the tape head is positioned at the beginning of a 3 second pulse.
Eventually the subroutine at 128 will get called, which will spend most of its time waiting till we are passed the 3 second pulse.
It might not be obvious from the code, but the tape loader makes use of timer A and B from CIA 2.
Timer A is set to always count 90 o2 pulses before underflow.
Timer B is set to count Timer A underflows. How much Timer B counts before underflow is always set at the end of a tape pulse via a lookup table. The value of timer B at the end of the pulse is used as index into the lookup table.
It should be noted that the first time we get a value from timer B, we are dependant on initial startup conditions of the C64. Therefore the first value we will get from timer B will always be $ff. In the lookup table this will translate to a new timer value for timer B of $20.
If you go through the code, you will see the use of two lookup tables. I am listing them here:
Code:
03f0 a3 38 8a 65 9e 85 9e 8a 60 08 0a 08 0a 00 00 00
0400 0c 0f 01 04 20 20 20 20 20 20 20 20 20 20 20 20
0410 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0420 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0430 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0440 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0450 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0460 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0470 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0480 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
0490 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
04a0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
04b0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
04c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
04d0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
04e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
02e0 68 8d 20 d0 a9 07 85 c0 a6 ae a4 af 60 02 00 01
02f0 00 02 02 01 01 00 00 a4 9e 20 e3 03 c4 a3 60 00
0300 d1 03 83 a4 7c a5 1a a7 e4 a7 86 ae 00 00 00 00
0310 4c 48 b2 00 31 ea c1 fe c1 fe 4a f3 91 f2 0e f2
0320 50 f2 33 f3 57 f1 ca f1 b1 f1 3e f1 2f f3 66 fe
0330 a7 02 a2 01 8e 20 d0 a9 3f 85 01 a9 10 24 01 f0
0340 fc a9 1f 85 01 a2 01 20 38 01 a9 2c 8d ea 03 a9
0350 00 8d 20 d0 85 9e 20 28 01 a6 a3 e8 f0 e7 e0 02
0360 d0 e8 a6 9e d0 e4 20 e3 03 c9 66 d0 dd 20 e3 03
0370 c9 1b d0 d6 a9 ee 8d ea 03 a9 00 85 9e 20 e3 03
0380 cd f5 02 f0 04 90 c3 b0 a9 20 e3 03 cd f6 02 f0
0390 04 90 b7 b0 9d a8 f0 14 a0 00 20 e3 03 91 ae ea
03a0 c8 d0 f7 20 f7 02 d0 a2 e6 af ea 60 20 e3 03 85
03b0 ae 20 e3 03 85 af 20 e3 03 85 15 20 e3 03 85 14
03c0 20 f7 02 f0 03 4c 4a 03 a9 00 85 9e a4 14 4c 9a
03d0 03 8a 10 03 4c 8b e3 99 e3 03 c8 d0 fa ee d9 03
03e0 4c d7 03 a9 01 85 a3 20 28 01 2c 20 d0 90 f8 a6
03f0 a3 38 8a 65 9e 85 9e 8a 60 08 0a 08 0a 00 00 00
Another interesting happening is the modification of the opcode at 3EA.