sys_return: equ $d003 sys_call: equ $d006 console_status: equ $7fe5 ; console status vector console_output: equ $7fe8 ; console output vector console_input: equ $7feB ; console input vector mon_pdata: equ $c009 mon_out2hs: equ $c012 mon_out4hs: equ $c015 mon_baddr: equ $c01e mon_pcrlf: equ $c021 ;;; Address of cassette interface casport: equ $8060 org $a100 ;;; Go to first argument str_skp_next: ldaa ,x beq str_skp_next_e cmpa #$20 beq str_skp_next_1 inx bra str_skp_next str_skp_next_1: ldaa ,x beq str_skp_next_e cmpa #$20 bne str_skp_next_e inx bra str_skp_next_1 str_skp_next_e: ;;; Save filename to FCS * ldx #tstnam stx fname ldaa ,x ; Check argument bne file_check ldx #txt_argument jsr mon_pdata jmp prog_end ;;; Check if file already exists file_check: ldaa #$01 ; command $01 - check file staa fcs ldx #fcs jsr sys_call tst fcs+1 ; read error code bne *+5 jmp file_exists ; file already exists ;;; Begin data load ldx #txt_press_play jsr mon_pdata ldx #$0100 stx loaddr stx hiaddr jsr cassette_load ;;; Verify ldx hiaddr cpx loaddr bhi save_file ldx #txt_no_data jsr mon_pdata bra prog_end ;;; Save loaded data to file save_file: ldx #txt_saving jsr mon_pdata ldaa #$20 ; command $20 - save file staa fcs ldx loaddr stx fcs+4 ldx hiaddr stx fcs+6 ldaa #$03 ; Set attributes "rw-" staa fcs+8 ldx #fcs jsr sys_call tst fcs+1 ; read error code beq prog_end ; save OK ldx #txt_save_error jsr mon_pdata ldx #fcs+1 jsr mon_out2hs jsr mon_pcrlf prog_end: jmp sys_return * file_exists: ldx #txt_exists jsr mon_pdata bra prog_end ;;; ;;; Load data from cassette ;;; cassette_load: ldx loaddr ;; Start sync sync: clr thresh clr count jsr console_status tsta beq *+5 jmp load_end sync1: jsr cycle tsta beq sync ; resync on timeout adda thresh ; calc running average length lsra ; thresh = (A + thresh ) / 2 staa thresh inc count bne sync1 ;; Calculate threshhold ldaa thresh tab lsrb lsrb sba staa thresh ;; Wait for sync end bit sync2: jsr cycle tsta beq sync ; resync on timeout cmpa thresh bhi sync2 ;; Begin data load load: clr ,x ; prepare destination byte jsr cycle ; start bit cmpa thresh bhi load_end ; exit when no start bit ldaa #8 staa count load1: jsr cycle ; data bit tsta beq load_end ; exit on timeout suba thresh ; carry will be set on overflow ;; Shift bit into memory byte ;; (inverted data bit now in carry) ldaa ,x rora staa ,x dec count bne load1 com ,x inx bra load ;; End of load ;; Inform user and print end address load_end: dex stx hiaddr rts ;;; ;;; Get cycle time in A ;;; (0 on timeout) ;;; cycle: clra ldab casport bmi cycle3 ; if high on entry we are out of sync cycle0: inca beq cycle3 ; timeout ldab casport bpl cycle0 ; wait for positive flank clra cycle1: inca beq cycle3 ; timeout ldab casport bmi cycle1 ; wait for negative flank cycle3: rts ;;; ;;; Texts ;;; txt_argument: fcc "Destination file name missing" fcb $0d,$0a,$04 txt_exists: fcc "File exists" fcb $0d,$0a,$04 txt_press_play: fcc "Press play on tape" fcb $0d,$0a,$04 txt_saving: fcc "Saving file" fcb $0d,$0a,$04 txt_save_error: fcc "Save failed - " fcb $04 txt_no_data: fcc "No data loaded" fcb $0d,$0a,$04 ;;; ;;; Variables ;;; loaddr: rmb 2 ; Lowest address loaded hiaddr: rmb 2 ; Highest address loaded count: rmb 1 ; General counter thresh: rmb 1 ; Cycle threshold *tstnam: fcc "testfile" * fcb #$00 ;;; File Control Structure fcs: rmb 1 ; command rmb 1 ; error code fname: rmb 2 ; file name pointer rmb 14 ; payload