diff --git a/c64/kernal/iec/acptr.s b/c64/kernal/iec/acptr.s index 4c9756e4..f31bfc74 100644 --- a/c64/kernal/iec/acptr.s +++ b/c64/kernal/iec/acptr.s @@ -14,7 +14,11 @@ ACPTR: jsr kernalstatus_reset #if CONFIG_IEC +#if CONFIG_IEC_JIFFYDOS + jmp iec_rx_dispatch +#else // no turbo supported jmp iec_rx_byte +#endif #else jmp kernalerror_ILLEGAL_DEVICE_NUMBER #endif diff --git a/c64/kernal/iec/ciout.s b/c64/kernal/iec/ciout.s index 9250c55c..4c6137bd 100644 --- a/c64/kernal/iec/ciout.s +++ b/c64/kernal/iec/ciout.s @@ -33,7 +33,11 @@ ciout_store_in_buffer: ciout_send_byte: clc // don't send with EOI +#if CONFIG_IEC_JIFFYDOS + jsr iec_tx_dispatch +#else // no turbo supported jsr iec_tx_byte +#endif inc C3PO // iec_tx_byte sets it to 0, but we still have something to send jmp ciout_store_in_buffer diff --git a/c64/kernal/iec/f000.iec_jiffydos.s b/c64/kernal/iec/f000.iec_jiffydos.s index b9c6104b..c7528db4 100644 --- a/c64/kernal/iec/f000.iec_jiffydos.s +++ b/c64/kernal/iec/f000.iec_jiffydos.s @@ -1,184 +1,173 @@ - -// -// JiffyDOS protocol support for IEC -// - -// XXX finish this - - - -#if CONFIG_IEC_JIFFYDOS - - -// JiffyDOS timing regime is very strict - before transmitting anything -// we need to disable sprites and (if screen is not disabled) wait for -// appropriate moment, so that no badline interruption can happen - - -iec_tx_byte_jiffydos: - - // We need to preserve 3 lowest bits of CIA2_PRA - as they encode - // Use C3PO for this, as afterwards we have to set there 0 nevertheless - lda CIA2_PRA - and #%00000111 - sta C3PO - - // Hide sprites, store their previous status on stack - jsr jiffydos_hide_sprites - pha - - // Prepare nibbles to send - lda TBTCNT - and #$0F - pha - lda TBTCNT - and #$F0 - pha - - // Wait till receiver is ready - jsr iec_wait_for_data_release - -__jd_check1: - - // Wait till it is safe to send data - jsr jiffydos_wait_line - - // Notify device that we are going to send byte by releasing everything - // Cycles: 3 + 4 = 7 - lda C3PO - sta CIA2_PRA - - // Send high nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21 - pla // retrieve high nibble from stack - ora C3PO // restore VIC-II and RS-232 bits - sta CIA2_PRA // bits 4 and 5 on CLK/DATA - ror // move bits 6 and 7 to positions 4 and 5 - ror - and #%00110000 // clear everything but CLK/DATA - sta CIA2_PRA // bits 6 and 7 on CLK/DATA - - // Send low nibble; cycles: XXX - - // XXX something strange seems to happen with low nibble: - - // $0 -> $00 - // $1 -> $80 = $10 + $70 - // $2 -> $20 - // $3 -> $A0 = $30 + $70 - // $4 -> $40 - // $5 -> $C0 = $50 + $70 - // $6 -> $60 - // $7 -> $E0 = $70 + $70 - - // $8 -> $10 = $80 - $70 - // $9 -> $90 - // $A -> $30 = $A0 - $70 - // $B -> $B0 - // $C -> $50 = $C0 - $70 - // $D -> $D0 - // $E -> $70 = $E0 - $70 - // $F -> $F0 - - // XXX why??? how this is calculated??? - - // XXX EOI signalled by early CLK (20us delay for non-CLK?) - - - // Re-enable sprites - pla - lda VIC_SPENA - - // Mark TX buffer as empty - lda #$00 - sta C3PO - - rts - - -iec_rx_byte_jiffydos: - - // Hide sprites, store their previous status on stack - jsr jiffydos_hide_sprites - pha - - // Wait until device is ready to send - jsr iec_wait_for_clk_release - - // Prepare 'start sending' message - lda CIA2_PRA - and #$FF - BIT_CIA2_PRA_DAT_OUT // release - pha - - // Wait for appropriate moment - jsr jiffydos_wait_line - - // Ask device to start sending bits - pla - sta CIA2_PRA - - - // XXX retrieve byte - - - // Re-enable sprites - pla - lda VIC_SPENA - - rts - - -jiffydos_wait_line: - - lda VIC_SCROLY - and #$10 - beq jiffydos_wait_line_done // screen is disabled, no need to watch for badlines - - // To give the transfer routine as much time as possible, - // wait till a badline - - // XXX this is probably overkill, most likely it is enough to avoid 2 (3?) lines - // before badline - to be adjusted in the future -!: - sec - lda VIC_SCROLY - sbc VIC_RASTER - and #$07 // we want 8 lowest bits - bne !- - -jiffydos_wait_line_done: - rts - - -__jd_check2: - - -jiffydos_hide_sprites: - - lda VIC_SPENA - ldx #$00 - stx VIC_SPENA - - rts - - -.function SAME_PAGE_CHECK(label_1, label_2) -{ -#if PASS_SIZETEST - .return (label_1 - label_1 % 256) == (label_2 - label_2 % 256) -#else - .return true -#endif -} - -.if (!SAME_PAGE_CHECK(__jd_check1, __jd_check2)) -{ - // To meet the strict JiffyDOS timing, we need to make sure - // it does not span across multiple pages, as this would add - // 1 cycle to some jump instructions - maybe this wont cause - // problems, but better safe than sorry. - - .error "JiffyDOS code can't span across multiple pages" -} - - -#endif // CONFIG_IEC_JIFFYDOS + +// +// JiffyDOS protocol support for IEC +// + +// XXX finish this + + + +#if CONFIG_IEC_JIFFYDOS + + +// JiffyDOS timing regime is very strict - before transmitting anything +// we need to disable sprites and (if screen is not disabled) wait for +// appropriate moment, so that no badline interruption can happen + + +iec_tx_byte_jiffydos: + + // We need to preserve 3 lowest bits of CIA2_PRA - as they encode + // Use C3PO for this, as afterwards we have to set there 0 nevertheless + lda CIA2_PRA + and #%00000111 + sta C3PO + + // Hide sprites, store their previous status on stack + jsr jiffydos_hide_sprites + pha + + // Prepare nibbles to send + lda TBTCNT + and #$0F + tax + lda iec_jiffydos_bittable, X // low nibble has to be encoded + pha + lda TBTCNT + and #$F0 + pha + + // Wait till receiver is ready + jsr iec_wait_for_data_release + +__jd_check1: + + // Wait till it is safe to send data + jsr jiffydos_wait_line + + // Notify device that we are going to send byte by releasing everything + // Cycles: 3 + 4 = 7 + lda C3PO + sta CIA2_PRA + + // Send high nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21 + pla // retrieve high nibble from stack + ora C3PO // restore VIC-II and RS-232 bits + sta CIA2_PRA // bits 4 and 5 on CLK/DATA + ror // move bits 6 and 7 to positions 4 and 5 + ror + and #%00110000 // clear everything but CLK/DATA + sta CIA2_PRA // bits 6 and 7 on CLK/DATA + + // Send low nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21 + pla // retrieve low nibble from stack + ora C3PO // restore VIC-II and RS-232 bits + sta CIA2_PRA + ror + ror + and #%00110000 // clear everything but CLK/DATA + sta CIA2_PRA + + + + // XXX EOI signalled by early CLK (20us delay for non-CLK?) + + + // Re-enable sprites + pla + lda VIC_SPENA + + // Mark TX buffer as empty + lda #$00 + sta C3PO + + rts + + +iec_rx_byte_jiffydos: + + // Hide sprites, store their previous status on stack + jsr jiffydos_hide_sprites + pha + + // Wait until device is ready to send + jsr iec_wait_for_clk_release + + // Prepare 'start sending' message + lda CIA2_PRA + and #$FF - BIT_CIA2_PRA_DAT_OUT // release + pha + + // Wait for appropriate moment + jsr jiffydos_wait_line + + // Ask device to start sending bits + pla + sta CIA2_PRA + + + // XXX retrieve byte + + + // Re-enable sprites + pla + lda VIC_SPENA + + rts + + +jiffydos_wait_line: + + lda VIC_SCROLY + and #$10 + beq jiffydos_wait_line_done // screen is disabled, no need to watch for badlines + + // To give the transfer routine as much time as possible, + // wait till a badline + + // XXX this is probably overkill, most likely it is enough to avoid 2 (3?) lines + // before badline - to be adjusted in the future +!: + sec + lda VIC_SCROLY + sbc VIC_RASTER + and #$07 // we want 8 lowest bits + bne !- + +jiffydos_wait_line_done: + rts + + +__jd_check2: + + +jiffydos_hide_sprites: + + lda VIC_SPENA + ldx #$00 + stx VIC_SPENA + + rts + + +.function SAME_PAGE_CHECK(label_1, label_2) +{ +#if PASS_SIZETEST + .return (label_1 - label_1 % 256) == (label_2 - label_2 % 256) +#else + .return true +#endif +} + +.if (!SAME_PAGE_CHECK(__jd_check1, __jd_check2)) +{ + // To meet the strict JiffyDOS timing, we need to make sure + // it does not span across multiple pages, as this would add + // 1 cycle to some jump instructions - maybe this wont cause + // problems, but better safe than sorry. + + .error "JiffyDOS code can't span across multiple pages" +} + + +#endif // CONFIG_IEC_JIFFYDOS diff --git a/c64/kernal/iec/iec_jiffydos_bittable.s b/c64/kernal/iec/iec_jiffydos_bittable.s new file mode 100644 index 00000000..0cc99ed9 --- /dev/null +++ b/c64/kernal/iec/iec_jiffydos_bittable.s @@ -0,0 +1,33 @@ + +// +// Helper table for encoding lower nibble for JiffyyDOS, +// values found by observing the actual transfer +// + +#if CONFIG_IEC_JIFFYDOS + + + // XXX consider calculating the values on-the-fly + +iec_jiffydos_bittable: + + .byte $00 + .byte $80 // $10 + $70 + .byte $20 + .byte $A0 // $30 + $70 + .byte $40 + .byte $C0 // $50 + $70 + .byte $60 + .byte $E0 // $70 + $70 + + .byte $10 // $80 - $70 + .byte $90 + .byte $30 // $A0 - $70 + .byte $B0 + .byte $50 // $C0 - $70 + .byte $D0 + .byte $70 // $E0 - $70 + .byte $F0 + + +#endif // CONFIG_IEC_JIFFYDOS diff --git a/c64/kernal/iec/iec_rx_dispatch.s b/c64/kernal/iec/iec_rx_dispatch.s new file mode 100644 index 00000000..78a3690a --- /dev/null +++ b/c64/kernal/iec/iec_rx_dispatch.s @@ -0,0 +1,32 @@ + +// +// Arbitration code for normal/turbo transfer +// + + +#if CONFIG_IEC_JIFFYDOS + + +iec_rx_dispatch: + + lda IECPROTO +#if CONFIG_IEC_JIFFYDOS + cmp #$01 + beq iec_rx_dispatch_jiffydos +#endif // CONFIG_IEC_JIFFYDOS + + // FALLTROUGH + +iec_rx_dispatch_normal: + + plp + jmp iec_rx_byte + +#if CONFIG_IEC_JIFFYDOS +iec_rx_dispatch_jiffydos: + plp + jmp iec_rx_byte_jiffydos +#endif // CONFIG_IEC_JIFFYDOS + + +#endif // any turbo supported diff --git a/c64/kernal/iec/iec_tx_byte.s b/c64/kernal/iec/iec_tx_byte.s index 02e28f81..bed60be5 100644 --- a/c64/kernal/iec/iec_tx_byte.s +++ b/c64/kernal/iec/iec_tx_byte.s @@ -68,21 +68,21 @@ iec_tx_common_sendbit: cpx #$00 bne !+ // branch if not sending the last bit - ldy #$1B // 400us is nearly 410 cycles on NTSC - // loop iteration below is 15 cycles, + ldy #$25 // 400us is nearly 410 cycles on NTSC + // loop iteration below is 11 cycles, // and several cycles were already used iec_jiffydos_detect_loop: lda CIA2_PRA // 4 cycles bpl iec_jiffydos_detected // 2 cycles dey // 2 cycles - bne iec_jiffydos_detect_loop // 2 cycles + bne iec_jiffydos_detect_loop // 3 cycles if branch - lda #$00 // 2 cycles - beq iec_jiffydos_store_proto // 3 cycles, branch always + lda #$00 // normal protocol + skip_2_bytes_trash_nvz iec_jiffydos_detected: - - panic #$FF // WHOAAAA! He wants to speak jiffy, but I do not know this language yet! + + lda #$01 // JiffyDOS protocol iec_jiffydos_store_proto: sta IECPROTO diff --git a/c64/kernal/iec/iec_tx_dispatch.s b/c64/kernal/iec/iec_tx_dispatch.s new file mode 100644 index 00000000..4222e6a8 --- /dev/null +++ b/c64/kernal/iec/iec_tx_dispatch.s @@ -0,0 +1,33 @@ + +// +// Arbitration code for normal/turbo transfer +// + + +#if CONFIG_IEC_JIFFYDOS + + +iec_tx_dispatch: + + php // preserve C flag for EOI indication + lda IECPROTO +#if CONFIG_IEC_JIFFYDOS + cmp #$01 + beq iec_tx_dispatch_jiffydos +#endif // CONFIG_IEC_JIFFYDOS + + // FALLTROUGH + +iec_tx_dispatch_normal: + + plp + jmp iec_tx_byte + +#if CONFIG_IEC_JIFFYDOS +iec_tx_dispatch_jiffydos: + plp + jmp iec_tx_byte_jiffydos +#endif // CONFIG_IEC_JIFFYDOS + + +#endif // any turbo supported diff --git a/c64/kernal/iec/load_iec.s b/c64/kernal/iec/load_iec.s index df68986b..23f647b8 100644 --- a/c64/kernal/iec/load_iec.s +++ b/c64/kernal/iec/load_iec.s @@ -71,10 +71,18 @@ load_iec: // Get load address +#if CONFIG_IEC_JIFFYDOS + jsr iec_rx_dispatch +#else // no turbo supported jsr iec_rx_byte +#endif bcs load_iec_file_not_found sta EAL+0 +#if CONFIG_IEC_JIFFYDOS + jsr iec_rx_dispatch +#else // no turbo supported jsr iec_rx_byte +#endif bcs load_iec_file_not_found sta EAL+1 @@ -92,7 +100,11 @@ load_iec: iec_load_loop: // We are now ready to receive bytes +#if CONFIG_IEC_JIFFYDOS + jsr iec_rx_dispatch +#else // no turbo supported jsr iec_rx_byte +#endif bcs load_iec_error // Handle the byte (store in memory / verify) diff --git a/c64/kernal/iec/save_iec.s b/c64/kernal/iec/save_iec.s index 35f3b74f..e06d4a9e 100644 --- a/c64/kernal/iec/save_iec.s +++ b/c64/kernal/iec/save_iec.s @@ -1,102 +1,114 @@ - -// -// IEC part of the SAVE routine -// - - -#if CONFIG_IEC - - -save_iec_dev_not_found: - jmp lvs_device_not_found_error - - -save_iec: - - // Check file name - lda FNLEN - beq_far kernalerror_FILE_NAME_MISSING - - // Display SAVING - jsr lvs_display_saving - - // Call device to LISTEN - lda FA - jsr LISTEN - bcs save_iec_dev_not_found - - // Open channel 1 (reserved for file writing) - lda #$01 - jsr iec_cmd_open - bcs save_iec_dev_not_found - - // Send file name - jsr iec_send_file_name - bcs save_iec_dev_not_found - - // Call device to LISTEN once again - lda FA - jsr LISTEN - bcs save_iec_dev_not_found - - lda #$61 // open channel / data (p3) , required according to p13 - sta TBTCNT - jsr iec_tx_command - bcs save_iec_dev_not_found - - // Save start address - lda STAL+0 - sta TBTCNT - clc - jsr iec_tx_byte - - lda STAL+1 - sta TBTCNT - clc - jsr iec_tx_byte - - jsr lvs_setup_MEMUSS - ldy #$00 -iec_save_loop: - - // Retrieve byte to send -#if CONFIG_MEMORY_MODEL_60K - ldx #