home *** CD-ROM | disk | FTP | other *** search
- .title 'Program to microcommunicate with other computer systems'
- .sbttl ' Version of 10-Jul-81'
- .ident talk
- .entry start
- .if1,[ .prntx 'TALK v1.5 - CP/M to host file transfer program']
- ;
- ; Simple program that can send and receive characters
- ; from the CP/M console or floppy disk to another
- ; computer/ acoustic modem/ or terminal that is connected
- ; to a Z80 SIO or DART (serial asynchronous interface).
- ;
- ; It is my first attempt at writing a program using
- ; interrupts so that I can fully utilise my hardware's
- ; capabilities. (I have a Godbout DISK 1 DMA floppy disk
- ; controller, Wire-wrapped 4 MHz IEEE 696 Z80 CPU with
- ; 2x Z80 SIO's, Z80 CTC and Z80 PIO allowing use of Mode 2
- ; vectored interrupts, 64Kbytes RAM and a Fulcrum VIO-X2
- ; intelligent video board).
- ;
- ; Sorry the source is in TDL Macro assembly language and
- ; requires Phoenix Software Associates PASM or TDL/Xitan
- ; Macroassembler to assemble. Conversion to ASM should
- ; be straight forward, though you lose all the nice
- ; features of this assembler.
- ;
- ; Author: Anthony Nicholson
- ;
- ; Address: 54 Carnley Avenue,
- ; New Lambton, NSW, 2305,
- ; Australia.
- ;
- ; Phone: 049-526017
- ;
- ; Date written: 20-Dec-1981
- ;
- ; Modification history:
- ;
- ; * Rev 5 10-Jul-1982
- ; Tidy up and add Z80 processor check
- ; for submission to 'Public Domain'.
- ;
- ; * Rev 4 13-Jun-1982
- ; Add log file feature and change
- ; abort character to ^^ (so I can
- ; communicate with a VAX-11/780 which
- ; uses ^Y).
- ;
- ; * Rev 3 21-Mar-1982
- ; Add delay to SENDFILE to allow
- ; host computer to catch up when
- ; using fast (2400baud) transmission,
- ; and echo what is sent for testing
- ; (This was found to be necessary when
- ; TALKing to a timesharing host PDP-11/70
- ; which required time to process its
- ; input buffer).
- ;
- ; * Rev 2 07-Mar-1982
- ; Implement file send to host.
- ;
- ; * Rev 1 27-Jan-1982
- ; Fix GETFCB filename scan. Also
- ; add conditional assembly for use
- ; with the Ferguson Big Board and
- ; for testing using my hardware.
- ;
- ; * Rev 0 20-Dec-1981
- ; Initial version for my hardware.
- ;
- ;
- ;
- ; C P / M D E F I N I T I O N S
- ;
- bdos == 5 ;CP/M entry address
- base == 0 ;CP/M base re-entry address
- ;
- conwr$ == 2 ;Console write
- dirio$ == 6 ;Direct console i/o
- print$ == 9 ;Print string
- rdbuf$ == 10 ;Read console buffer
- openf$ == 15 ;Open file
- close$ == 16 ;Close file
- delet$ == 19 ;Delete file
- readf$ == 20 ;Read file
- write$ == 21 ;Write file
- creat$ == 22 ;Create file
- sdma$ == 26 ;Set DMA address
- ;
- ; G E T B U F F E R S I Z E
- ;
- bufsiz =\ 'File blocking buffer size (must be multiple of 128)'
- .ifn bufsiz @ 128,[
- .error '?ILLEGAL BUFFER SIZE'
- ]
- ;
- ; C O N T R O L C H A R A C T E R S
- ;
- ; Command characters to
- ctrld == 04h ; - download file
- ctrle == 05h ; - send file
- ctrlf == 06h ; - log file
- ctrlq == 11h ; - XON to host
- ctrls == 13h ; - XOFF to host
- ctrly == 1eh ; - Abort (really ^^)
- ctrlz == 1ah ; - EOF char
- ;
- lf == 0ah
- cr == 0dh
- ;
- noparity== 07fh ;parity bit mask
- ;
- false == 0
- true == # false
- .opsyn .ife,.ifnot
- .opsyn .ifn,.if
- ;
- testing =\ 'Version required (TEST=1, Bigboard=0) '
- ;
- baudc =\ 'Baud rate for Z80 SIO <Default=300> '
- ;
- opt.delay=\ 'Is a delay required after sending a line (Yes=1, No=0) '
- ;
- .ifnot testing,[
- ;
- ; Ferguson BIG BOARD equates
- ;
- bauda == 0ch ;Baud rate generator
- ; Value output to baud
- ; rate generator is
- ; determined below with
- ; a default of 300baud.
- ;For other baud rates,
- ; extend the conditional
- ; making sure to match
- ; all parentheses.
- .ife baudc-2400,[
- baudr == 1010b
- ]
- [.ife baudc-1200,[
- baudr == 1000b
- ]
- [.ife baudc-600,[
- baudr == 0110b
- ]
- [
- baudr == 0101b
- ]
- ]
- ]
- delcnt == 2*1000 ;delay count for 2MHz Z80
- siobc == 07h ;Uses Z80 SIO channel B
- siobd == 05h ; at ports 05 & 07h
- intvec == 0ff00h ; and its associated interrupt
- rx.v == intvec+4; vectors for rx char
- rxe.v == intvec+6; and rx char error
- ]
- .if testing,[
- ;
- ; Test equates using my hardware
- ;
- intvec: .word ierror ;I need to set up an
- .word ierror ; interrupt vector table
- .word ierror ; for the Z80 SIO
- .word ierror
- .word ierror
- .word ierror
- .word ierror
- .word ierror
- ;
- ierror: lxi d,imsg ; This routine will
- call prints ;handle anything funny
- hlt ;that may occur by HALTing!!!
- jmpr ierror
- ;
- imsg: .ascii [cr][lf]'?SPURIOUS INTERRUPT$'
- ;
- rx.v == intvec+4;vector assignment for SIO
- rxe.v == intvec+6; channel B
- ctcb == 11h ;CTC controls the baud rate
- .ife baudc-2400,[
- baudr == 00011000b
- ]
- [.ife baudc-1200,[
- baudr == 00110000b
- ]
- [.ife baudc-600,[
- baudr == 01100000b
- ]
- [
- baudr == 11000000b
- ]
- ]
- ]
- siobd == 01h ;data register of SIO
- siobc == 03h ;control register of SIO
- delcnt == 4*1000 ;delay count for 4MHz Z80
- ]
- ;
- ; B E G I N P R O G R A M ' T A L K '
- ;
- start: mvi a,7fH ;Identify processor
- add a ; cause overflow
- jpe Z80 ; conclusive proof of Z80
- lxi d,z80msg;Give them the bad news
- call prints
- jmp base ;Return to CP/M
- ;
- z80msg: .ascii '?TALK - This program requires a Z80 processor$'
- ;
- z80: lxi d,signon ;print("TALK V1.n")
- call prints
- call rxecho
- call inisio ;initialise SIO
- ;
- next1: call getch ;get a character
- ora a ; from console.
- jrnz proc1 ;if we get one then off we go...
- call prxch ;otherwise print any character
- jmp next1 ; we got down the line.
- ;
- proc1: cpi ctrld ;if ch="^D" then
- jrz ..6 ; transfer file to CP/M
- cpi ctrlf ;else if ch="^F" then
- jrnz ..2 ; do log file function
- mvi a,true ; by setting log flag
- sta log.flag
- lxi d,logmsg; and getting prompt
- jmpr ..7 ; message ready.
- ;
- ..6: lxi d,filmsg
- ;
- ..7: call prints ; print "filename ?"
- call inputl ; get filename
- lxi d,newlin
- call prints
- lxi h,conbuf+2
- lxi d,fcb
- call getfcb ; set up file control
- ; block
- jrz ..1 ;if not ok then
- ..0: lxi d,fnerrm ; print "filename error"
- call prints
- jmpr ..8 ;else
- ;
- ..1: call getfile ; transfer file
- ;
- ..8: mvi a,false ;when done, reset
- sta log.flag; log flag
- jmp next1
- ..2:
- cpi ctrly ;if ch="^Y" then
- jrnz ..3
-
- lxi d,byemsg; print "exiting..."
- call prints
- call close ; close files and
- call rxdint ; disable host rx interrupts
- jmp base ;Return to CP/M
- ..3:
- cpi ctrle ;if ch="^E" then
- jrnz ..4
- lxi d,sndmsg; print "filename to send?"
- call prints
- call inputl ; get filename
- lxi d,newlin
- call prints
- lxi h,conbuf+2
- lxi d,fcb
- call getfcb
- jrz ..5
-
- lxi d,fnerrm; print "filename error"
- call prints
- jmp next1
-
- ..5: call sendfile
- jmp next1
- ..4:
- call send ;send character to host
- jmp next1
- ;
- signon:
- .ascii 'TALK V1.5 Program to talk to host computer via serial data line'[cr][lf]
- .if testing,[ .ascii 'TESTING VERSION'[cr][lf]]
- .ascii 'Command characters are:'[cr][lf][cr][lf]
- .ascii ' ^^ abort current process (returns to CP/M)'[cr][lf]
- .ascii ' ^D prompt for CP/M filename to receive characters'[cr][lf]
- .ascii ' from host and initiate the transfer (by'[cr][lf]
- .ascii ' sending a <return> to host) (^F logfile)'[cr][lf]
- .ascii ' ^E prompt for CP/M filename to send to host'[cr][lf]
- .ascii ' and initiate the transfer (assumes host is'[cr][lf]
- .ascii ' ready to receive characters)'[cr][lf]
- .ascii ' ^Z when in file transfer mode causes the'[cr][lf]
- .ascii ' current operation to terminate'[cr][lf][cr][lf]
- .ascii 'You are now talking to the host...'[cr][lf]'$'
- ;
- filmsg: .ascii [cr][lf]'filename to receive?$'
- ;
- newlin: .ascii [cr][lf]'$'
- ;
- fnerrm: .ascii [cr][lf]'filename error, ignoring input...'[cr][lf]'$'
- ;
- byemsg: .ascii [cr][lf]'exiting...$'
- ;
- sndmsg: .ascii [cr][lf]'filename to send?$'
- ;
- logmsg: .ascii [cr][lf]'log filename?$'
- ;
- ;-----------------------
- ;
- ; S U B R O U T I N E S
- ;
- ;-----------------------
- ;
- ; getch - get a character from console
- ;
- ; exit: character -> a
- ;
- getch: mvi c,dirio$
- mvi e,0ffh
- bdose: push b
- push d
- push h
- call bdos
- pop h
- pop d
- pop b
- ret
- ;-----------------------
- ;
- ; prints - print ascii string on console
- ;
- ; entry: de -> address of string
- ;
- prints: mvi c,print$
- jmp bdose
- ;
- ; inputl - input line from console
- ;
- ; flushes buffer with spaces
- ;
- inputl: mvi b,cbfsiz;initialise console
- lxi h,conbuf; input buffer CONBUF
- mov m,b ; and fill with spaces
- inx h
- xra a
- mov m,a
- inx h
- ..0: mvi m,' '
- inx h
- djnz ..0
- mvi c,rdbuf$ ;read chars into buffer
- lxi d,conbuf
- jmp bdose
- ;-----------------------
- ;
- ; getfcb - build a CP/M filename from input string
- ;
- ; entry: HL -> ascii filename string
- ; DE -> FCB
- ; exit: z flag <- 0 if error (A<>0)
- ; 1 if ok (A=0)
- ;
- getfcb: xra a ;Set result status=OK
- sta ..okfl ; and get File Control Block
- push d
- mov b,m ;first char might be
- inx h ; drivename
- mov a,m ;if this is a ":" then we
- cpi ':' ; have a drivename
- jrnz ..nodv
- mov a,b
- call ..cpan ;check alphanumeric drive name
- inx h ; point past colon
- ani 7 ; mask drive A to H
- jmpr ..stdv
- ;
- ..nodv:
- dcx h ;no drivename so
- xra a ; set to default drive
- ..stdv:
- stax d ;store drivename
- inx d ; in first byte of FCB
- mvi b,8 ;get filename (8 chars)
- call ..name
- mov a,m
- cpi '.' ;check optional '.'
- jrnz ..ext
- inx h
- ..ext: mvi b,3 ;get extension (3 chars)
- call ..name
- mvi b,24 ;clear rest of FCB
- xra a
- ..crst: stax d
- inx d
- djnz ..crst
- lda ..okfl ;Get return status
- ana a ; set flag bits
- pop d ; and return
- ret
- ;
- ..okfl: .byte 0
- ;
- ..cpan: cpi ' ' ;if space or '.' then
- jrz ..cnok ; return z bit reset.
- cpi '.'
- jrz ..cnok
- cpi 'Z'+1 ;convert lower case
- jrc ..0 ; alpha to upper case
- sui 020h
- ..0: cpi '0' ;check for numeric
- jrc ..cper
- cpi '9'+1
- jrc ..cok
- cpi 'A' ;check for alpha
- jrc ..cper
- cpi 'Z'+1
- jrnc ..cper
- ..cok: cmp a ;return with z flag
- ret ; set if alphanumeric
-
-
- ..cper: push psw ;not alphanumeric
- mvi a,0ffh ; so set flag to
- sta ..okfl ; signify error
- pop psw
- ..cnok: ori 0ffh ;reset zero flag
- ret
- ;
- ..name: mov a,m ;get char from buffer
- call ..cpan ; and check it
- jrnz ..nr ;if error change to ' '
- inx h
- stax d ;put it to FCB (we
- inx d ; don't check errors
- djnz ..name ; 'til end)
- ret
- ..nr: mvi a,' '
- stax d
- inx d
- djnz ..nr
- ret
- ;-----------------------
- ;
- ; send - send character to host
- ;
- ; entry: A <- character
- ;
- send:
- push psw ;output the character
- ..wait: in siobc ; to sio channel B
- ani 00000100b; when the TxRDY bit
- jrz ..wait ; is set
- pop psw
- out siobd
- ret
- ;-----------------------
- ;
- ; conout - output character to console
- ;
- ; entry: A <- character
- ;
- conout: mov e,a
- mvi c,conwr$
- jmp bdose
- ;-----------------------
- ;
- ; inisio - initialise Z80 SIO for interrupt
- ; input from host
- ;
- inisio:
- di
- lxi h,intvec;set the interrupt
- mov a,h ; vector on the cpu
- stai ; and store the low
- mov a,l ; byte in sio control
- sta ivec ; data area
- lxi h,init$t;point to i/o init table
- ..1: mov b,m ; get # bytes,
- inx h
- mov c,m ; i/o port
- inx h
- outir ; and output
- bit 7,m
- jrz ..1
-
- lxi h,rxdvr ; interrupt vectors
- shld rx.v ; Rx channel B
- lxi h,rxerra
- shld rxe.v ; Rx error channel B
-
- im2 ;make sure its mode 2
- ei ; interrupts
-
- ret
- ;
- ; init$t - Z80 SIO and baud rate initialise
- ; data for Ferguson BIG BOARD
- ;
- init$t:
- .ifnot testing,[
- .byte 1 ;Baud rate for
- .byte bauda ; channel B on the
- .byte baudr ; Big board.
- ]
- .if testing,[
- .byte 2
- .byte ctcb ;My system uses a Z80 CTC
- .byte 01000111b; as a clock for the Z80 SIO
- .byte baudr
- ]
- .byte 12 ;SIO channel B
- .byte siobc
-
- .byte 0,00011000b ;channel B reset
- .byte 4,01000100b ;16x clock, 1 stopbit, no parity
- .byte 1,00011100b ;Rx interrupt enable
- .byte 3,11000001b ;8bits / Rx character, Rx enable
- .byte 5,11101010b ;8bits / Tx character, DTR, RTS, Tx enable
- .byte 2
- ivec: .byte 0 ;interrupt vector
-
- .byte -1 ;end of table marker
-
- ;-----------------------
- ;
- ; rxinten - set flag so characters received
- ; from host are buffered
- ;
- rxinten:
- mvi a,true
- sta buf.active
- jmp sendq
- ;-----------------------
- ;
- ; rxecho - set flag so characters received
- ; from host are echoed
- ;
- rxecho: mvi a,false
- sta buf.active
- sendq: mvi a,ctrlq ;send ^Q to host
- jmp send
- ;-----------------------
- ;
- ; rxdint - disable host receive
- ; character interrupts
- ;
- rxdint: mvi a,1 ;turn off so that
- out siobc ; when we return to
- mvi a,00000000b; CP/M we won't
- out siobc ; bomb out (RXDVR is
- ret ; overlayed)
- ;-----------------------
- ;
- ; prxch - print the last received character
- ; from the host
- ;
- prxch: di ;let's not get any
- lda rxchar ; interruptions while
- mov c,a ; we talk a copy of
- xra a ; the last character
- sta rxchar ; received and clear
- ei ; it
- mov a,c ;has a character been
- ora a ; received ?
- rz ;no
- jmp conout ;yes, print it so he
- ; can see that something
- ; is happening.
- ;-----------------------
- ;
- ; rxdvr - receive host character interrupt
- ; driver.
- ;
- rxdvr:
- push psw ;save registers
- push b
- push d
- push h
-
- rxdvr2: lda buf.active;check for buffered
- ora a ; mode
- jrnz rxbufi ;yes
- in siobd ;no, just get the
- ani noparity; character and save
- sta rxchar ; it
- jmpr retdvr
- rxbufi:
- lhld free.ptr;buffered mode.
- in siobd ;get character
- ani noparity; mask parity bit
- mov m,a ; and store
- sta rxchar
- inx h ;bump pointer
- shld free.ptr; and store.
- lda buf.sub ;get end of buffer
- ora a ; address depending
- lxi d,buf2 ; on buffer subscript
- jrz ..a
- lxi d,bufend
- ..a: mov a,h ;is the current buffer
- cmp d ; full (ie: is free.ptr
- jrnz ..ret ; now pointing past
- mov a,l ; current buffer) ?
- cmp e
- jrnz ..ret ;no.
- ..full:
- lda buf.sub ;swap buffer pointers
- ana a ; to other buffer
- jrz ..0 ; (using buffer
- lxi h,buf1 ; subscript)
- mvi a,0
- jmpr ..1
- ..0: lxi h,buf2
- mvi a,1
- ..1: sta buf.sub ;record new buffer
- shld buf.ptr ; pointers
- shld free.ptr
-
- mvi a,true ;signal that write
- sta buf.rdy ; buffer is ready
-
- ..ret: lda rxchar ;if character from
- cpi ctrlz ; host was a "^Z"
- jrnz retdvr ; then also set the
- mvi a,true ; end of file flag
- sta eof.flag
-
- retdvr: pop h ;restore registers
- pop d
- pop b
- pop psw
- ei ; and return
- reti
- ;
- rxchar: .byte 0
- ;
- ;-----------------------
- ;
- ; rxerra - receive host character error
- ; interrupt driver.
- ;
- rxerra:
- push psw ;if by some means
- push b ; a parity or
- push d ; framing error is
- push h ; detected then
- mvi a,00010000b
- out siobc
- mvi a,00110000b; error reset
- out siobc
- jmp rxdvr2 ; and process character
- ;-----------------------
- ;
- ; getfile - get a CP/M file from host computer
- ;
- ; entry: FCB is file to get
- ;
- getfile:
- lxi h,buf1 ;initialise buffer pointers
- shld free.ptr; and subscripts for
- shld buf.ptr ; transfer.
- shld write.ptr
- mvi a,0
- sta buf.sub
- sta wr.sub
- mvi a,false ;clear done.flag, eof.flag,
- sta done.flag; buf.rdy indicator and
- sta eof.flag; err.flag
- sta buf.rdy
- sta err.flag
- call make ;open file
- rnz ; abort if error
- call rxinten ;enable receive buffer interrupts
- lda log.flag;if log file operation
- ana a ; then skip sending a <CR>
- jrnz ..1
- mvi a,cr ;send <CR>
- call send
- ..1: lda buf.rdy ;if buf.ready.flag set then
- ana a
- jrz ..2
- mvi a,false
- sta buf.rdy
- call stopsend; stop host from sending
- call write ; write to file
- mvi a,ctrlq ; send host resume
- call send
- jmpr ..3
- ..2:
- lda eof.flag;else if end.of.file then
- ora a
- jrz ..3
- call stopsend; stop host from sending
- call puteofch; and put an end of file mark
- ; in the buffer.
- call write
- call close
- mvi a,true ; set done.flag
- sta done.flag
- ..3:
- lda done.flag
- ora a ;if done.flag set then
- jrnz getexit; exit
- lda err.flag;if err.flag set then
- ora a ; abort
- jrnz ..4
- call prxch
- call getch ;get char (if any) from
- ana a ; console. Skip the
- jrz ..1 ; tests if nothing typed
- cpi ctrly ;test character and abort
- jrz ..4 ; if ^Y is struck
- cpi ctrlz
- jrz ..9
- push psw
- lda log.flag;if log file active
- ana a ; then we want to send
- jrnz ..8 ; characters typed
- pop psw
- jmpr ..1
- ..8: pop psw
- call send
- jmpr ..1
- ..9: mvi a,true
- sta eof.flag
- jmpr ..1
- ..4:
- call rxecho
- lxi d,sabmsg; print "file transfer aborted"
- call prints ; and return
- ret
- getexit:
- call rxecho ;disable host buffer Rx
- lxi d,sdnmsg;print "file transferred"
- call prints ; and return
- ret
- ;
- sabmsg: .ascii [cr][lf]'file transfer aborted'[cr][lf]'$'
- ;
- sdnmsg: .ascii [cr][lf]'file transferred from host'[cr][lf]'$'
- ;
- ;-----------------------
- ;
- ; sendfile - send CP/M file to host
- ;
- sendfile:
- call open ;open file
- rnz ; and return if error
- lxi d,senmsg;print "sending file
- call prints ; to host"
- mvi a,cr ;send a <CR> to
- call send ; host
- ..rdlp: mvi c,readf$;read next sector from
- lxi d,fcb ; file to RBUF
- call bdose
- ora a ;CP/M end of file?
- jrnz ..eof ;yes
- xra a ;no, clear newline
- sta crflag ; flag so we only send
- ; a <CR> for each <CR><LF>
- lxi h,rbuf ;set address and
- mvi b,128 ; number of bytes
-
- ..slp: lda crflag ;was last char a <CR>?
- ora a
- jrz ..sn ;no
- xra a ;yes, reset flag
- sta crflag
- .if opt.delay,[
- push h ;delay 250ms to allow
- lxi h,250 ; host to process the
- call delay ; last line.
- pop h
- ]
- mov a,m ;get next character
- inx h
- cpi lf ;ignore next linefeed
- jrz ..keep
- jmpr ..sn2
- ..sn: mov a,m ;get next char from
- inx h ; read buffer
- ..sn2: cpi cr ;if it's a <CR> then
- jrnz ..sn1 ; set flag
- sta crflag
- ..sn1: call send ; and send it to host
- .if testing,[
- push h ;echo what we send
- push d ; to the console.
- push b
- push psw
- call conout
- pop psw
- pop b
- pop d
- pop h
- ]
- cpi ctrlz ;was it a ^Z?
- jrz ..eof ;yes
- ..keep: djnz ..slp ;no, keep sending...
- call getch ;check for ^Y from
- cpi ctrly ; console
- jrnz ..rdlp ; none, so keep going
- lxi d,sabmsg;print "file transfer
- call prints ; aborted"
- call close
- ret
- ..eof: call close ;close input file
- lxi d,fstmsg;print "file sent
- call prints ; to host successfully"
- ret
- ;
- senmsg: .ascii [cr][lf]'Sending file to host...'[cr][lf]'$'
- ;
- fstmsg: .ascii [cr][lf]'File sent to host successfully'[cr][lf]'$'
- ;
- ;-----------------------
- ;
- ; make - create new CP/M file
- ;
- make: lxi d,fcb ;delete any old
- mvi c,delet$; file
- call bdose
- lxi d,fcb ; and open a new
- mvi c,creat$; one
- call bdose
- cpi 0ffh ;any errors ?
- jrz ..0 ;yes
- mvi a,false ;no, return status
- ora a ; OK
- ret
- ..0: lxi d,opnmsg;error, print "open failure"
- call prints
- mvi a,true ;and return with status
- ora a ; not OK
- ret
- ;
- opnmsg: .ascii [cr][lf]'?CP/M file create failure'[cr][lf]'$'
- ;
- ;-----------------------
- ;
- ; open - open file (which must already exist)
- ;
- open: mvi c,sdma$ ;set buffer address
- lxi d,rbuf ; for reads
- call bdose
- mvi c,openf$
- lxi d,fcb
- call bdose
- cpi 0ffh ;find it?
- jrz ..opnf
- xra a
- ret
- ..opnf: lxi d,opfmsg;no, print "can't find
- call prints ; file"
- mvi a,0ffh
- ora a
- ret
- ;
- opfmsg: .ascii [cr][lf]"?Can't find CP/M file"[cr][lf]'$'
- ;
- ;-----------------------
- ;
- ; close - close file
- ;
- close:
- lxi d,fcb
- mvi c,close$
- jmp bdose
- ;-----------------------
- ;
- ; stopsend - stop host from sending
- ;
- stopsend:
- mvi a,ctrls ;send ^S
- call send
- ..0:
- lhld free.ptr; copy free.ptr
- shld sav.ptr
- lxi h,1000 ; delay 1 second
- call delay
- lhld sav.ptr ; if free.pointer
- lded free.ptr; hasn't moved then
- ana a ; return, else
- dsbc d ; keep waiting
- jrnz ..0
- ret
- ;
- sav.ptr:.blkb 2
- ;
- ;-----------------------
- ;
- ; write - write buffer to CP/M disk file
- ;
- write:
- lda eof.flag;if not end.of.file then
- ora a ; write out a whole buffer
- jrz ..3
- lded write.ptr; otherwise calculate
- lhld free.ptr; the number of sectors
- ora a ; = ((free.ptr - write.ptr)*2/256)+1
- dsbc d
- dad h
- mov a,h
- inr a
- jmpr ..2
- ;
- ..3: mvi a,numsec;set number of sectors
- ..2: sta ..nsec ; to write.
-
- ..wnxt:
- lded write.ptr;set disk buffer
- mvi c,sdma$ ; address
- call bdose
-
- lxi d,fcb ;write next sector
- mvi c,write$
- call bdose
- ana a ;abort if write error
- jrnz ..err ; status returned.
-
- lhld write.ptr;point to next logical
- lxi b,128 ; sector
- dad b
- shld write.ptr
- lda ..nsec ;repeat until all sectors
- dcr a ; have been written
- sta ..nsec
- jrnz ..wnxt
-
- lda wr.sub ;swap write.ptr and
- ora a ; wr.sub to the
- jrz ..4 ; other buffer so
- lxi h,buf1 ; we write it next
- mvi a,0 ; time.
- jmpr ..5
- ..4: lxi h,buf2
- mvi a,1
- ..5: sta wr.sub
- shld write.ptr
- ret
-
- ..err: lxi d,wremsg;print "write error"
- call prints
- call close ;close CP/M file
- mvi a,true ; and set error flag
- sta err.flag
- ret
- ;
- ..nsec: .byte 0
- ;
- wremsg: .ascii [cr][lf]'?CRITICAL ERROR - Disk full'[cr][lf]'$'
- ;
- ;-----------------------
- ;
- ; puteofch - Put an end-of-file marker (^Z)
- ; at the end of the current buffer.
- ;
- puteofch:
-
- di
- lhld free.ptr
- mvi m,ctrlz
- inx h
- shld free.ptr
- ei
-
- ret
- ;-----------------------
- ;
- ; delay - delay the millisecond count
- ; passed in the HL register pair
- ;
- delay: mvi a,delcnt/26
- ..0: dcx h
- inx h
- dcr a
- jnz ..0
- dcx h
- mov a,l
- ora h
- jnz delay
- ret
- ;
- ; G L O B A L F L A G S
- ;
- done.flag:
- .byte 0 ;set when transfer complete
- eof.flag:
- .byte 0 ;set when ^Z received from host
- buf.rdy:
- .byte 0 ;set when rx buffer full
- err.flag:
- .byte 0 ;set if a fatal error occurs
- buf.active:
- .byte 0 ;set when buffer i/o is active
-
- crflag: .byte 0 ;set to filter <LF> from sent file
- log.flag:
- .byte 0 ;set to store characters received
- ; in a log file.
- ;
- ; B U F F E R P O I N T E R S
- ;
- free.ptr: ;points to next free byte to
- ; receive a character from
- .word buf1 ; the host.
- buf.ptr: ;points to start of current
- .word buf1 ; receive buffer.
- write.ptr: ;points to start of the next
- .word buf1 ; buffer to write to disk.
- buf.sub: ;subscript into buffer
- .byte 0 ;( 0=buf1, 1=buf2 )
- wr.sub: .byte 0
- ;
- ; fcb - CP/M file control block
- ;
- fcb: .blkb 36
- ;
- ; B U F F E R S
- ;
- ;
- ; conbuf - console input buffer
- ;
- cbfsiz = 64
- conbuf: .byte cbfsiz
- nchrs: .byte 0
- .blkb cbfsiz
- ;
- numsec == bufsiz/128
- ;
- buf1: .blkb bufsiz
- buf2: .blkb bufsiz
- bufend:
- ;
- rbuf: .blkb 128 ;CP/M file read buffer
- ;
- .end start
-