Files
open-roms/src/kernal/iec_fast/jiffydos_load.s
T

335 lines
6.0 KiB
ArmAsm

;; #LAYOUT# STD * #TAKE
;; #LAYOUT# * KERNAL_0 #TAKE
;; #LAYOUT# * * #IGNORE
;
; JiffyDOS protocol support for IEC - optimized load loop
;
!ifdef CONFIG_IEC_JIFFYDOS { !ifndef CONFIG_MEMORY_MODEL_60K {
; Note: original JiffyDOS LOAD loop checks for RUN/STOP key every time a sector is read,
; see description at https://sites.google.com/site/h2obsession/CBM/C128/JiffySoft128
;
; For simplicity and some space savings, our routine does not check the RUN/STOP key at all;
; the protocol is fast enough (especially with modern flash mediums) that probably nobody
; will want to terminate the loading.
jiffydos_load:
!ifdef CONFIG_IEC_JD_TEST {
; XXX test implementation, not ready yet
; Switch to optimized LOAD protocol
jsr UNTLK
lda FA
jsr TALK
bcs jiffydos_load_error
lda #$61
jsr TKSA
; XXX flow below most likely takes too much time...
; Timing is critical, do not allow interrupts
sei
!ifdef CONFIG_IEC_JIFFYDOS_BLANK {
!ifdef CONFIG_MB_U64 {
; XXX implement for non-blank mode, use jiffydos_prepare_no_preserve_bits
; Check if turbo register is available
lda U64_TURBOCTL
cmp #$FF
beq @1
; Store turbo register content, disable badlines
sta TBTCNT
lda #$80
sta U64_TURBOCTL
bne @2
; Normal flow - no turbo register
}
@1:
; Preserve register with screen status (blank/visible)
lda VIC_SCROLY
sta TBTCNT
; Blank screen to make sure no sprite/badline will interrupt
jsr screen_off
@2:
; Preserve 3 lowest bits of CIA2_PRA
jsr jiffydos_preserve_bits
} else {
@1:
; Store previous sprite status in temporary variable
jsr jiffydos_prepare
sta TBTCNT
@2:
}
; A trick to shorten EAL update time
ldy #$FF
!ifdef CONFIG_MB_M65 {
; If in native mode, switch to 1 MHz
jsr m65_iec_fast
}
; FALLTROUGH
jiffydos_load_loop_esc:
; We are now in 'escape mode' - release DATA, wait till receiver releases CLK
jsr iec_release_clk_data
jsr iec_wait_for_clk_release
; Check DATA line
bmi jiffydos_load_check_status
+panic $01
; XXX finish the implementation
jiffydos_load_check_status:
; Check if a device pulls CLK within the next 1100us (at least 1125 cycles, to be sure for NTSC)
ldx #$67 ; 2 cycles
; FALLTROUGH
jiffydos_load_check_loop:
lda CIA2_PRA ; 4 cycles
bvc jiffydos_load_end ; 2 cycles if not taken
dex ; 2 cycles
bne jiffydos_load_check_loop ; 3 cycles if taken
; FALLTROUGH
jiffydos_load_error:
+panic $03
; XXX finish the implementation
jiffydos_load_end:
+panic $FF
; XXX finish the implementation
} else {
; XXX implement JiffyDOS optimized LOAD protocol, this one is ineffective
; Timing is critical, do not allow interrupts
sei
!ifdef CONFIG_IEC_JIFFYDOS_BLANK {
!ifdef CONFIG_MB_U64 {
; XXX implement for non-blank mode, use jiffydos_prepare_no_preserve_bits
; Check if turbo register is available
lda U64_TURBOCTL
cmp #$FF
beq @1
; Store turbo register content, disable badlines
sta TBTCNT
lda #$80
sta U64_TURBOCTL
bne @2
; Normal flow - no turbo register
}
@1:
; Preserve register with screen status (blank/visible)
lda VIC_SCROLY
sta TBTCNT
; Blank screen to make sure no sprite/badline will interrupt
jsr screen_off
@2:
; Preserve 3 lowest bits of CIA2_PRA
jsr jiffydos_preserve_bits
} else {
@1:
; Store previous sprite status in temporary variable
jsr jiffydos_prepare
sta TBTCNT
@2:
}
; A trick to shorten EAL update time
ldy #$FF
!ifdef CONFIG_MB_M65 {
; If in native mode, switch to 1 MHz
jsr m65_iec_slow
}
; FALLTROUGH
jiffydos_load_loop:
; Wait until device is ready to send (releases CLK)
jsr iec_wait_for_clk_release
; Prepare 'start sending' message
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT ; release
!ifdef CONFIG_IEC_JIFFYDOS_BLANK {
; It seems JiffyDOS needs some time here; waste few cycles
+nop
jsr iec_wait_rts
; Ask device to start sending bits
sta CIA2_PRA
} else {
; Wait for appropriate moment, ask device to start sending bits
tax
jsr jiffydos_wait_line
stx CIA2_PRA ; cycles: 4
}
; Prepare 'data pull' byte, cycles: 3 + 2 + 2 = 7
lda C3PO
ora #BIT_CIA2_PRA_DAT_OUT ; pull
tax
; Delay, JiffyDOS needs some time, 4 cycles
+nop
+nop
; Get bits, cycles: 4 + 2 + 2 = 8
lda CIA2_PRA ; bits 0 and 1 on CLK/DATA
lsr
lsr
; Delay, JiffyDOS needs some time, 2 cycles
+nop
; Get bits, cycles: 4 + 2 + 2 = 8
ora CIA2_PRA ; bits 2 and 3 on CLK/DATA
lsr
lsr
; Get bits, cycles: 3 + 4 + 2 + 2 = 11
eor C3PO
eor CIA2_PRA ; bits 4 and 5 on CLK/DATA
lsr
lsr
; Get bits, cycles: 3 + 4 = 7
eor C3PO
eor CIA2_PRA ; bits 6 and 7 on CLK/DATA
; Store retrieved byte, cycles: 2 + 6 = 8
iny ; NTSC needs this delay
sta (EAL),y ; not compatible with CONFIG_MEMORY_MODEL_60K
; Retrieve status bits, cycles: 4
bit CIA2_PRA
; Pull DATA at the end, cycles: 4
stx CIA2_PRA
; If CLK line not active - this was the last byte
bvs jiffydos_load_end
; Handle EAL
cpy #$FF
bne jiffydos_load_loop
inc EAL+1
+bra jiffydos_load_loop
jiffydos_load_end:
!ifdef CONFIG_MB_M65 {
; If in native mode, switch back to fast mode
jsr m65_iec_fast
}
; Save last byte
tax
; Update EAL
sec
jsr iec_update_EAL_by_Y
; Indicate that no byte waits in output buffer
lda #$00
sta C3PO
; Restore proper IECPROTO value
lda #IEC_JIFFY
sta IECPROTO
!ifdef CONFIG_IEC_JIFFYDOS_BLANK {
!ifdef CONFIG_MB_U64 {
; Check if turbo register is available
lda U64_TURBOCTL
cmp #$FF
beq @3
; Restore turbo register content
lda TBTCNT
sta U64_TURBOCTL
jmp @4
; Normal flow - no turbo register
}
@3:
; Restore screen state
lda TBTCNT
sta VIC_SCROLY
@4:
} else {
@3:
; Re-enable sprites
lda TBTCNT
sta VIC_SPENA
@4:
}
; Store last byte as unoptimized LOAD routine would
stx TBTCNT
; No need to re-enable interrupts; other IEC routines
; called by LOAD will do this nevertheless
; End of load loop
jmp load_iec_loop_end
} } ; CONFIG_IEC_JIFFYDOS and not CONFIG_MEMORY_MODEL_60K
}