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 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 ldx #txt_sends19 jsr mon_pdata ;;; Begin S19 load ldx #$ffff stx loaddr ; set loaddr = $ffff inx stx hiaddr ; set loaddr = $0000 load_loop: jsr console_input cmpa #'S bne load_loop jsr console_input cmpa #'9 beq load_end cmpa #'1 bne load_loop clr chksum ;;; Get byte count jsr inbyte tab addb chksum stab chksum suba #2 staa bytcnt ;;; Get address jsr inbyte staa addr tab addb chksum stab chksum jsr inbyte staa addr+1 tab addb chksum stab chksum ;;; Check address range ldx addr cpx #$0025 ; address below safe limit? bhi load_chklo ldx #txt_range_error jsr mon_pdata jmp prog_end_flush load_chklo: cpx loaddr ; address lower than loaddr? bhi load_chkhi stx loaddr load_chkhi: ldab bytcnt subb #2 abx cpx hiaddr ; address highter than hiaddr? bls load_data stx hiaddr ;;; Get data load_data: ldx addr load_data_loop: jsr inbyte tab addb chksum stab chksum dec bytcnt ; All bytes read? beq load_chksum staa ,x inx bra load_data_loop ;;; Verify checksum load_chksum: inc chksum bne *+5 jmp load_loop ldx #txt_chksum ; Bad checksum jsr mon_pdata jmp prog_end_flush ; End program ;;; Load complete load_end: ldx loaddr cpx hiaddr blo load_ok: ldx #txt_range_error jsr mon_pdata jmp prog_end_flush ;;; Print confimation load_ok: ldx #txt_loadok jsr mon_pdata ldx #loaddr jsr mon_out4hs ldx #hiaddr jsr mon_out4hs jsr mon_pcrlf ldx #txt_save jsr mon_pdata confirm: ldaa #$03 staa attr ; Set file attributes -WR jsr console_input anda #$df ; To upper case cmpa #'Y beq save_file cmpa #'X beq add_exe_header cmpa #'N beq prog_end bra confirm ;;; Make file executable by adding exe header add_exe_header: ldx loaddr stx entry ; Set default entry address ldx #txt_exe jsr mon_pdata jsr mon_baddr bcc add_exe_header_do stx entry add_exe_header_do: jsr mon_pcrlf ldx loaddr dex dex dex dex dex dex ldaa #$47 staa ,x clra staa 1,x ldaa loaddr staa 2,x ldaa entry staa 4,x ldaa loaddr+1 staa 3,x ldaa entry+1 staa 5,x stx loaddr ldaa #$07 staa attr ; Set file attributes XWR ;;; 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 attr 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 * prog_end_flush: ldx #txt_xtoexit jsr mon_pdata prog_end_flush_l: jsr console_input anda #$DF cmpa #'X bne prog_end_flush_l jmp sys_return * file_exists: ldx #txt_exists jsr mon_pdata bra prog_end ;;; ;;; Read byte from console ;;; inbyte: jsr inhex bcc inbyte1 asla asla asla asla tab jsr inhex bcc inbyte1 aba sec ; Good input rts inbyte1: clc ; Bad input rts ;;; ;;; Read hex from console ;;; inhex: jsr console_input suba #$30 bmi nothex cmpa #$09 ble in1hg anda #$DF ; Convert to upper case cmpa #$11 bmi nothex cmpa #$16 bgt nothex suba #7 in1hg: sec ; Input OK. Set carry rts nothex: clc ; Input bad. Clear carry rts ;;; Texts txt_argument: fcc "Destination file name missing" fcb $0d,$0a,$04 txt_sends19: fcc "Send S19" fcb $0d,$0a,$04 txt_exists: fcc "File exists" fcb $0d,$0a,$04 txt_range_error: fcc "S19 range error" fcb $0d,$0a,$04 txt_loadok: fcc "S19 OK" fcb $0d,$0a,$0a fcc "Beg End" fcb $0d,$0a,$04 txt_chksum: fcc "Checksum fail" fcb $0d,$0a,$04 txt_save: fcc "Y - Save binary file" fcb $0d,$0a fcc "X - Save executable file" fcb $0d,$0a fcc "N - Abort" fcb $0d,$0a,$04 txt_exe: fcc "Creating exec header" fcb $0d,$0a fcc "Entry point: " fcb $04 txt_saving: fcc "Saving file" fcb $0d,$0a,$04 txt_save_error: fcc "Save failed - " fcb $04 txt_xtoexit: fcc "Press X to exit" fcb $0d,$0a,$04 ;;; Variables chksum: rmb 1 ; S19 checksum bytcnt: rmb 1 ; S19 byte count addr: rmb 2 ; S19 address loaddr: rmb 2 ; Lowest address loaded hiaddr: rmb 2 ; Highest address loaded entry: rmb 2 ; Excutable entry point attr: rmb 1 ; File attributes *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