diff --git a/c64/kernal/tape/load_tape_normal.s b/c64/kernal/tape/load_tape_normal.s index e9e69370..056ebaa6 100644 --- a/c64/kernal/tape/load_tape_normal.s +++ b/c64/kernal/tape/load_tape_normal.s @@ -7,17 +7,19 @@ // We have the following possible CPU frequencies: // - C64    PAL:  CPU frequency 0.985248 MHz // - C64    NTSC: CPU frequency 1.022727 MHz -// - VIC-20 PAL:  CPU frequency 1.108405 MHz -// - VIC-20 NTSC: CPU frequency 1.022727 MHz -// Since VIC-20 tapes are not expected to be loaded often, routine will be optimized for C64 timings - +// Average is 1.0039875 MHz and we will take this value for calculation (but it really does not change much). +// // We have to distinguish the following pulse lengths (http://sidpreservation.6581.org/tape-format/): // - S (short)    352 us // - M (medium)   512 us // - L (long)     672 us -// This gives us the following thresholds (where average CPU frequency is 1.0039875 MHz): -// - S vs M       432 us (54 8-cycle periods) -// - M vs L       592 us (74 8-cycle periods) +// +// This gives us the following thresholds +// - S vs M       432 us (108 or $6C 4-tick periods) +// - M vs L       592 us (149 or $95 4-tick periods) +// +// 4-tick periods should be enough - TAP file format description (http://unusedino.de/ec64/technical/formats/tap.html) +// tells it uses exactly 8 PAL ticks as a resolution // The following encoding is used: // (S,M) = 0 bit @@ -30,7 +32,50 @@ load_tape_normal: - STUB_IMPLEMENTATION() + + jsr tape_ditch_verify // only LOAD is supported, no VERIFY + + // Setup CIA #2 timers + + ldx #$03 // set timer A to 4 ticks + stx CIA2_TIMALO // $DD04 + ldx #$00 + stx CIA2_TIMAHI // $DD05 + + stx CIA2_TIMBHI // $DD07 + dex // puts $FF - for running timer B as long as possible + stx CIA2_TIMBLO // $DD06 + + // Let timer A run continuously + + ldx #%00010001 // start timer, force latch reload + stx CIA2_CRA // $DD0E + + // Start playing + + jsr tape_clean_sid + jsr tape_ask_play + + // FALLTROUGH + +load_tape_normal_header: + + // XXX replace this placeholder by a real routine + + + jsr tape_load_get_pulse + ldx #$00 + cmp #($100 - $6C - $05) + + bcs !+ +#if CONFIG_COLORS_BRAND && CONFIG_BRAND_ULTIMATE_64 + ldx #$0B +#else + ldx #$06 +#endif +!: + stx VIC_EXTCOL + jmp load_tape_normal_header #endif diff --git a/c64/kernal/tape/load_tape_turbo.s b/c64/kernal/tape/load_tape_turbo.s index a676d6d5..59eb619a 100644 --- a/c64/kernal/tape/load_tape_turbo.s +++ b/c64/kernal/tape/load_tape_turbo.s @@ -98,88 +98,5 @@ load_tape_turbo_loop: beq_far tape_load_success jmp tape_load_error -tape_turbo_get_byte: - - lda #$01 - sta ROPRTY // init the to-be-read byte with 1 -!: - jsr tape_turbo_get_bit - rol ROPRTY - bcc !- // is the initial 1 shifted into carry already? - lda ROPRTY // much nicer than ldx #8: dex: loop - - rts - - -tape_turbo_get_bit: - - lda #$10 -!: - bit CIA1_ICR // $DC0D - beq !- // busy loop to detect signal - lda CIA2_ICR // $DD0D - pha - lda #$19 - sta CIA2_CRA // $DD0E - pla - - pha // audio/video effects - asl - sta SID_SIGVOL - beq !+ -#if CONFIG_COLORS_BRAND && CONFIG_BRAND_ULTIMATE_64 - lda #$0B -#else - lda #$06 -#endif -!: - sta VIC_EXTCOL - pla - - lsr - rts - -tape_turbo_sync_common: - - jsr tape_turbo_get_bit - rol ROPRTY - lda ROPRTY - cmp #$02 - bne tape_turbo_sync_common - rts - -tape_turbo_sync_header: - - ldx #$FF -!: - ldy #$03 -!: - jsr tape_turbo_sync_common - dey - bne !- - dex - bne !-- - - // FALLTROUGH - -tape_turbo_sync_payload: - - jsr tape_turbo_sync_common -!: - ldx #$09 // 9,8,... is real turboTape -!: // I sometimes used 8,7,6... to avoid it being listed in vice :) - jsr tape_turbo_get_byte - cmp #$02 - beq !- - ldy #$00 -!: - cpx ROPRTY - bne tape_turbo_sync_payload - jsr tape_turbo_get_byte - dex - bne !- - - rts - #endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_normal_get_pulse.s b/c64/kernal/tape/tape_normal_get_pulse.s new file mode 100644 index 00000000..bd69e013 --- /dev/null +++ b/c64/kernal/tape/tape_normal_get_pulse.s @@ -0,0 +1,42 @@ + +// +// Tape (turbo) helper routine - pulse reading +// +// Returns pulse length (with a bias, see comments) in .A +// + + +#if CONFIG_TAPE_NORMAL + + +tape_load_get_pulse: + + // Contrary to original ROM implementation we do not use interrupts + // (see http://unusedino.de/ec64/technical/formats/tap.html) - busy wait + // implementation is probably just shorter + + lda #$10 +!: + bit CIA1_ICR // $DC0D + bne !- +!: + bit CIA1_ICR // $DC0D + beq !- // busy loop to detect signal, restart timer afterwards + lda CIA2_TIMBLO // $DD06 + ldx #%01010001 // start timer, force latch reload, count timer A underflows + stx CIA2_CRB // $DD0F + + // Since the signal appeared to the point of timer restart we used: + // bit - 4 cycles + // beq - 2 cycles + // lda - 4 cycles + // ldx - 2 cycles + // stx - 4 cycles + // plus approx. 3 cycles (bit + beq time divided by 2) from value change to 'bit' instruction, + // this is total 19 cycles, or $5 periods of 4 ticks (timer A) each - we need to take it into account + // every time we check the pulse length + + rts + + +#endif diff --git a/c64/kernal/tape/tape_turbo_get_bit.s b/c64/kernal/tape/tape_turbo_get_bit.s new file mode 100644 index 00000000..b900528d --- /dev/null +++ b/c64/kernal/tape/tape_turbo_get_bit.s @@ -0,0 +1,42 @@ + +// +// Tape (turbo) helper routine - bit reading +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +#if CONFIG_TAPE_TURBO + + +tape_turbo_get_bit: + + lda #$10 +!: + bit CIA1_ICR // $DC0D + beq !- // busy loop to detect signal + lda CIA2_ICR // $DD0D + pha + lda #%00011001 // start timer, one-shot, force latch reload + sta CIA2_CRA // $DD0E + pla + + pha // audio/video effects + asl + sta SID_SIGVOL + beq !+ +#if CONFIG_COLORS_BRAND && CONFIG_BRAND_ULTIMATE_64 + lda #$0B +#else + lda #$06 +#endif +!: + sta VIC_EXTCOL + pla + + lsr + rts + + +#endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_turbo_get_byte.s b/c64/kernal/tape/tape_turbo_get_byte.s new file mode 100644 index 00000000..22a54110 --- /dev/null +++ b/c64/kernal/tape/tape_turbo_get_byte.s @@ -0,0 +1,26 @@ + +// +// Tape (turbo) helper routine - byte reading +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +#if CONFIG_TAPE_TURBO + + +tape_turbo_get_byte: + + lda #$01 + sta ROPRTY // init the to-be-read byte with 1 (canary bit to mark loop end) +!: + jsr tape_turbo_get_bit + rol ROPRTY + bcc !- // is the initial 1 shifted into carry already? + lda ROPRTY // much nicer than ldx #8: dex: loop + + rts + + +#endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_turbo_sync.s b/c64/kernal/tape/tape_turbo_sync.s new file mode 100644 index 00000000..a7dde565 --- /dev/null +++ b/c64/kernal/tape/tape_turbo_sync.s @@ -0,0 +1,56 @@ + +// +// Tape (turbo) helper routine - synchronization handling +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +#if CONFIG_TAPE_TURBO + + +tape_turbo_sync_common: + + jsr tape_turbo_get_bit + rol ROPRTY + lda ROPRTY + cmp #$02 + bne tape_turbo_sync_common + rts + +tape_turbo_sync_header: + + ldx #$FF +!: + ldy #$03 +!: + jsr tape_turbo_sync_common + dey + bne !- + dex + bne !-- + + // FALLTROUGH + +tape_turbo_sync_payload: + + jsr tape_turbo_sync_common +!: + ldx #$09 // 9,8,... is real turboTape +!: // I sometimes used 8,7,6... to avoid it being listed in vice :) + jsr tape_turbo_get_byte + cmp #$02 + beq !- + ldy #$00 +!: + cpx ROPRTY + bne tape_turbo_sync_payload + jsr tape_turbo_get_byte + dex + bne !- + + rts + + +#endif // CONFIG_TAPE_TURBO