;; #LAYOUT# STD * #TAKE ;; #LAYOUT# CRT KERNAL_0 #TAKE ;; #LAYOUT# M65 KERNAL_1 #TAKE ;; #LAYOUT# * * #IGNORE ; ; Tape (normal) part of the LOAD routine ; ; We have the following possible CPU frequencies: ; - C64    PAL:  CPU frequency 0.985248 MHz ; - C64    NTSC: CPU frequency 1.022727 MHz ; The clock difference is about 4% - it is unlikely to cause problems. ; ; We have to distinguish the following pulse lengths (http://sidpreservation.6581.org/tape-format/): ; - S (short)    tap value $30 (PAL: 352 us) ; - M (medium)   tap value $42 (PAL: 512 us) ; - L (long)     tap value $56 (PAL: 672 us) ; ; The TAP format (http://unusedino.de/ec64/technical/formats/tap.html) uses a resolution of 8 PAL ticks; ; this implementation sets the timer for twice the precision (timer B is triggered every 4 CPU cycles), ; probably an overkill, but in realityy it does not cost us anything. ; ; So - we have the following thresholds: ; - S vs M       $72 (in our units of 4 ticks) ; - M vs L       $98 (in our units of 4 ticks) ; ; We need to recognize the following pulse sequences: ; ; (S,M) = 0 bit ; (M,S) = 1 bit ; (L,M) = new-data marker ; (L,S) = end-of-data marker !ifdef CONFIG_TAPE_NORMAL { !ifndef CONFIG_TAPE_AUTODETECT { load_tape_normal: jsr tape_ditch_verify ; only LOAD is supported, no VERIFY ; Start playing jsr tape_common_prepare_cia jsr tape_ask_play !ifdef CONFIG_TAPE_HEAD_ALIGN { jsr tape_prepare_reading } ; FALLTROUGH load_tape_normal_header: } else { load_tape_normal_takeover: ; entry point for turbo->normal takeover } jsr load_MEMUSS_to_STAL ; Try to load header into tape buffer (we will restore MEMUSS later) jsr tape_normal_get_pilot_header !ifdef CONFIG_TAPE_AUTODETECT { bcs load_tape_normal_switch_turbo ; failed, try turbo } jsr load_TAPE1_to_MEMUSS jsr tape_normal_get_data_1 !ifndef CONFIG_TAPE_AUTODETECT { bcs load_tape_normal_header ; unable to read block, try again } else { bcc load_tape_normal_switch_turbo_skip load_tape_normal_switch_turbo: jsr lvs_STAL_to_MEMUSS jmp load_tape_turbo_takeover ; unable to read block, try turbo instead load_tape_normal_switch_turbo_skip: } jsr load_TAPE1_to_MEMUSS jsr tape_normal_get_data_2 !ifndef CONFIG_TAPE_AUTODETECT { bcs load_tape_normal_header ; block load error, try again } else { bcs load_tape_normal_switch_turbo ; block load error, try turbo instead } ; Check header type ldy #$00 lda (TAPE1),y cmp #$05 +beq tape_load_error ; end of tape mark, nothing to load cmp #$01 beq @1 cmp #$03 !ifndef CONFIG_TAPE_AUTODETECT { bne load_tape_normal_header ; header types 1 and 3 are loadable, see Mapping the C64, page 77 } else { bne load_tape_normal_takeover } lda #$01 sta SA ; this file is non-relocatable; override secondary address with 1 @1: ; Restore MEMUSS, handle header jsr lvs_STAL_to_MEMUSS jsr tape_handle_header !ifndef CONFIG_TAPE_AUTODETECT { bcs load_tape_normal_header ; if name does not match, look for other header } else { bcs load_tape_normal_takeover } ; FALLTROUGH load_tape_normal_payload: ; Retrieve data jsr tape_normal_get_pilot_data ldy #$00 ; no data size limit jsr tape_normal_get_data_1 +bcs tape_load_error jsr lvs_check_EAL +bne tape_load_error ; amount of data read does not match header info jsr lvs_STAL_to_MEMUSS jsr tape_normal_get_data_2 +bcs tape_load_error jmp tape_load_success load_TAPE1_to_MEMUSS: ; set MEMUSS (start address) as tape buffer lda TAPE1+1 sta MEMUSS+1 lda TAPE1+0 sta MEMUSS+0 rts load_MEMUSS_to_STAL: ; preserve MEMUSS lda MEMUSS+1 sta STAL+1 lda MEMUSS+0 sta STAL+0 rts }