home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
OSBORNE
/
OSBPLINK.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
16KB
|
817 lines
; PLINK.ASM ver 6.4
; (revised 6/14/81)
;
;PLINK is a CP/M transient command which allows the user to
;PLINK currently supports two way transfer of text files between
;the CP/M disk and the remote computer. The following control
;codes may be initiated from the console keyboard:
;
;Control-E Exit PLINK to CP/M "warm-boot".
;
;Control-T Transmit ASCII file to remote system, asks for
; drive (A, B, etc.) and filename.typ.
;
;Control-C Aborts transmission of file to remote system.
;
;Control-Y Switches between saving and ignoring
; incoming ASCII data in RAM buffer,
; for later transfer to disk.
;
;Control-W Writes RAM buffer to disk, and asks for drive
; and filename.typ.
;
;Del (delete) Backspace when in command mode (e.g. ^T or ^W).
;
;Control-U Aborts current line when in command mode.
;
;(Note: all other control codes are passed to modem output, and
;may be interpreted by the remote system as various control
;functions.)
;
;
;bdos entry point and function codes
;
base equ 0 ;<<-- set to offset of CP/M for your
;system, standard systems are 0, some
;'alternate' systems are 4200H
;
bdos equ base+5
resdsk equ 13 ;reset disk system
offc equ 15 ;open file
cffc equ 16 ;close file
dffc equ 19 ;delete file
rrfc equ 20 ;read record
wrfc equ 21 ;write record
mffc equ 22 ;make file
;
;TRS80 pickles and trout sio calls
;offset by -3 that is add 3 to all calls
;
setsio equ 30h ;set up z80 sio
siotst equ 33h ;read sio status
sioinp equ 36h ;input a char
sioout equ 39h ;output a char
;
;
;default fcb and field definitions
;
fcb equ base+5ch
fn equ 1 ;file name field (rel)
ft equ 9 ;file type field (rel)
ex equ 12 ;file extent field (rel)
nr equ 32 ;next record field (rel)
dbuf equ base+80h ;default disk buffer address
;
;ascii control characters
;
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
del equ 7fh ;delete (rubout)
bell equ 07h ;bell signal
tab equ 09h ;horizontal tab
xon equ 11h ;x-on character
null equ 00h ;null char
;
;the following "trigger" equate is set to "lf" (linefeed)
;by default. an optional trigger char may be passed via fcb1
;
; ie: PLINK B will set trigger to "bell"
;
;the following options are allowed
;
; 1. B = bell 07h
; 2. X = xon 11h
; 3. U = upload no trigger check at all
;
;any other ascii character may be passed through fcb1
;
;
trigger equ LF ;default value
;
;
;warning character for low memory
;
wrnsig equ BELL ;if you have one, put 'BELL' here
;...else put '*' here.
;
;
; **main program**
;
org base+100h
;
jmp 4000h
org base+4000h
lnki: lxi sp,stack+64 ;create local stack
lhld base+1 ;point to CP/M jmp table
lxi d,3 ;get ready to add 3
dad d ;point to con status jmp
shld citcal+1 ;modify call adrs
dad d ;point to con in jmp
shld rccal+1 ;modify call adrs
dad d ;point to con out jmp
shld wccal+1 ;modify call adrs
lda fcb+1 ;see if optional trigger char
cpi 20h ;blank.. ?
jz skp ;..blank so use default "lf"
cpi 'B' ;bell wanted
jz trgbel
cpi 'X' ;xon wanted
jz trgxon
cpi 'U' ;uploading no checking for trigger
jz trgupl
;
settrg sta overly+1 ;store the character as is then
jmp skp
;
trgbel mvi a,bell
jmp settrg
;
trgxon mvi a,xon
jmp settrg
;
trgupl xra a ;zero out jump
sta overl1+1 ;change check for c/r to null
sta overl2+1 ;and send linefeeds as well
jmp skp
;
skp: equ $
;
;
cont:
xra a ;clear char buffers
sta inch
sta outch
sta flag ;clear text save flag
lxi h,tbuf ;set ptr to tbuf
shld ptr
lxi h,0 ;size = 0
shld size
lxi h,lnkims ;print sign-on message
call wcs
;
;main loop
;
lnki3: call citest ;jump if no data from console
jz lnki4
call rcc ;else read console data
cpi 20h
cc pcc ;call pcc if control char
jc lnki4 ;jump if pcc handled char
ori 80h ;else set valid data bit
sta inch ;and store in input char buffer
;
lnki4: lda outch ;jump if no data for console
ora a
jp lnki5
ani 7fh ;else discard valid data bit
call wcc ;send char to console
xra a ;then clear output char buffer
sta outch
;
lnki5: call mitest ;jump if no data from modem
jz lnki6
call rmc2 ;else read modem data
call save ;save char in text buffer if flag on
ori 80h ;set data valid bit
sta outch ;store in output char buffer
;
lnki6: call motest ;jump if modem xmit buffer busy
jnz lnki7
lda inch ;jump if no data for modem
ora a
jp lnki7
ani 7fh ;discard valid data bit
call wmc
;
xra a ;...then clear input char buffer
sta inch
;
lnki7: jmp lnki3 ;end of main loop
;
lnkims: db cr,lf,'PLINK ver 6.4'
db cr,lf,cr,lf
db '[^T]ransmit, [^Y]ank, [^W]rite, [^E]xit, [^C]ancel'
db cr,lf,'Ready',cr,lf,lf,0
;
;pcc - process control character
;
pcc: cpi 'E'-40h ;jump out if ctrl e
jnz pcc1
push h
lxi h,ays ;print 'are you sure'
call wcs
pop h
call rcc ;get answer
call wcc ;echo it
ani 5fh ;make upper case
cpi 'Y' ;yes?
jz pccex ;exit
call wccr ;crlf
stc ;tell plink to ignore this character
;
;
pcc1: cpi 'T'-40h ;jump if not control-t
jnz pcc2
call stf ;transmit text file to modem
stc ;tell plink to ignore this character
ret
;
pcc2: cpi 'Y'-40h ;jump if not control-y
jnz pcc3
lda flag
dcr a ;was it zero?
jnz pcc2a ;yes
sta flag ;no, was 1, now 0
lxi h,pcmnix ;print ignore incoming stuff
jmp pcc2b
;
pcc2a: mvi a,1 ;turn on text save flag
sta flag
lxi h,pccmr ;print 'saving incoming text in memory'
;
pcc2b: call wcs
stc ;tell plink to ignore this character
ret
;
pcc3: cpi 'W'-40h ;jump if not control-W
jnz pcc4
xra a ;turn off text save flag
sta flag
call wtb ;write text buffer to disk
stc
ret
;
pcc4: stc ;let plink handle all other cont. codes
cmc
ret
;
pccex: lxi h,disms ;print 'modem not disconnected'
call wcs
jmp base ;exit to warm boot
;
ays: db cr,lf,'Exit to CP/M - are you sure (Y or N)? ',0
;
disms: db cr,lf,'+++ Exit to CP/M +++',cr,lf,0
;
pccmr: db cr,lf,'Saving incoming text in memory',cr,lf,0
pcmnix: db cr,lf,'Ignoring incoming text',cr,lf,0
;
;stf - send text file (to modem)
;
stf: call gfn ;get name of disk file to send
jc stf6 ;jump if file name error
call open ;try to open specified file
cpi 255 ;jump if file not found
jz stf7
;
stf1: call read ;read next record into dbuf
cpi 1 ;jump if end-of-file
jz stf5
lxi h,dbuf ;point to disk buffer
mvi c,128
;
stf2: mov a,m ;fetch next char from dbuf
inx h
cpi 'Z'-40h ;jump if end-of-file character
jz stf5
;
overl2 cpi lf ;ignore line feeds
jz stf4
call wmc ;write character to modem
call wcc ;write character to console
;
overl1 cpi cr ;jump if not carriage return
jnz stf4
;
stf3: call citest ;check console data ready
jz stf3a ;no data there
call rcc ;get console character
cpi 'C'-40h ;control c aborts it
jz stf8
;
stf3a: call mitest ;wait for next modem character
jz stf3
call rmc2 ;check modem for trigger char.
;
overly cpi trigger
jnz stf3
call wccr ;send crlf to console
;
stf4: dcr c ;loop thru rest of dbuf
jnz stf2
jmp stf1 ;go get next record from disk
;
stf5: lxi h,stfsm ;print 'file send complete'
call wcs
ret
;
stf6: lxi h,stfs1 ;print 'file name error'
call wcs
ret
;
stf7: lxi h,stfs2 ;print 'file not found'
call wcs
ret
;
stf8: lxi h,stfsa ;print 'file send aborted'
call wcs
ret
;
stfsm: db 'File send complete',cr,lf,0
stfs1: db 'File name error or abort',cr,lf,0
stfs2: db 'File not found',cr,lf,0
stfsa: db cr,lf,'File send aborted',cr,lf,0
;
;save - save char in text buffer if flag on
;
; entry conditions
; a - character to save
;
save: push psw
lda flag
ora a
jnz save1
pop psw
ret
;
save1: pop psw
cpi del ;rubout (del) ?
rz ;yes, ignore it
cpi 20h ;test for control characters
jnc save2 ;jump if not control char.
cpi cr ;allow cr to be saved
jz save2
cpi lf ;allow lf to be saved
jz save2
cpi tab ;allow tab to be saved
jz save2
ret ;ignore all other control chars.
;
save2: push h
lhld size ;size = size + 1
inx h
shld size
lhld ptr
mov m,a
inx h
shld ptr
push psw
lda base+7 ;get system size
sui 1 ;so we dont crash CP/M
cmp h ;are we out of room?
jz saveab ;yes, abort
sui 4 ;leave some room (1k)
cmp h
mvi a,wrnsig ;signal console running out of space
cc wcc
pop psw
pop h
ret
;
;saveab - ran out of room, issue message and flow
; through to disk save routine
;
savend: db bell,cr,lf,'Aborting - no room left',0
;
saveab: lxi sp,stack+64 ;reinitialize stack
lxi h,savend ;print 'aborting - no room left'
call wcs
lxi h,lnki ;set up return address
push h ;leave it on the stack
;
;wtb - write text buffer to disk
;
wtb: lhld size ;jump if text buffer empty
mov a,l
ora h
jz wtb5
mvi c,resdsk ;reset in case read-only
call bdos
call gfn ;get file name
jc wtb6 ;jump if file name error
call delt ;delete old file, if any
call make ;make new file
lhld size ;de = tbuf size
xchg
lxi h,dbuf ;top of stack points to dbuf
push h
lxi h,tbuf ;hl points to tbuf
;
wtb1: mvi c,128 ;disk buffer size
;
wtb2: mov a,m ;fetch next byte of tbuf
inx h
xthl
mov m,a ;store in dbuf
inx h
xthl
dcx d ;size = size - 1
mov a,d ;exit loop if size = 0
ora e
jz wtb3
dcr c ;loop until dbuf full
jnz wtb2
call write ;write full dbuf to disk
xthl ;top of stack points to dbuf
lxi h,dbuf
xthl
jmp wtb1 ;loop until end of tbuf
;
wtb3: pop h ;hl points to current place in dbuf
;
wtb4: mvi m,'Z'-40h ;store eof code
inx h
dcr c ;loop thru rest of dbuf
jnz wtb4
call write ;write last sector to disk
call close ;clean up act and go home
lxi h,tbuf ;clear text buffer
shld ptr
lxi h,0
shld size
lxi h,wtbsm ;print 'buffer saved on disk'
call wcs
ret
;
wtb5: lxi h,wtbs1 ;print 'text buffer empty'
call wcs
ret
;
wtb6: lxi h,wtbs2 ;print 'file name error'
call wcs
ret
;
wtbsm: db cr,lf,'Buffer saved on disk',cr,lf
db 'Memory save cancelled',cr,lf,0
wtbs1: db 'Text buffer empty',cr,lf,0
wtbs2: db 'File name error or abort',cr,lf,0
;
;wcs - write console string
;
; entry conditions
; hl - points to string (term by zero byte)
;
wcs: mov a,m
inx h
ora a
rz
call wcc
jmp wcs
;
;wccr - write console carriage return (and line feed)
;
wccr: mvi a,cr
call wcc
mvi a,lf
;
;wcc - write console character
;
; entry conditions:
; a - character to write
;
wcc: push psw
push b
push d
push h
mov c,a ;get character for cbios
wccal: call $-$ ;modified by init.
pop h
pop d
pop b
pop psw
ret
;
;rcs - read console string (with echo)
;
; exit conditions
; b - number of characters read (<255)
; hl - points to last char stored (cr)
;
rcs: lxi h,ibuf
mvi b,0
;
rcs1: call rcc ;read next char from console
cpi del ;jump if not del
jnz rcs2
inr b ;ignore del if ibuf already empty
dcr b
jz rcs1
dcx h ;else discard last char
mov a,m ;echo discarded char to console
call wcc
dcr b ;decrement count
jmp rcs1 ; and loop
;
rcs2: cpi 'U'-40h ;jump if not control u
jnz rcs3
call wccr ;else abort current line
jmp rcs ; and start over
;
rcs3: call wcc ;echo char to console
mov m,a ;store char in ibuf
inr b ;increment count
cpi cr ;jump if carriage return
jz rcs4
inx h ;else advance pointer
jmp rcs1 ; and loop
;
rcs4: mvi a,lf ;issue line feed and return
call wcc
ret
;
;rcc - read console character
;
; exit conditions
; a - character read
;
rcc: push b
push d
push h
rccal: call $-$ ;modified by init.
pop h
pop d
pop b
ret
;
;wmc - write modem character
;
; entry conditions
; a - character to write
;
;
wmc:
ani 7fh
sta xyz
di
out 0
mvi a,0
sta 0ef08h
lda xyz
sta 2a01h
out 1
mvi a,1
sta 0ef08h
ei
ret
;
;rmc - read modem character
;
; exit conditions:
; a - character read
di
out 0
mvi a,0
sta 0ef08h
rmc:
lda 2a00h
ani 01h
cpi 00h
jz rmc
out 1
mvi a,1
sta 0ef08h
ei
rmc2: di
out 0
mvi a,0
sta 0ef08h
lda 2a01h
sta xyz
out 1
mvi a,1
sta 0ef08h
ei
lda xyz
ani 7fh
ret
;
;
;
;gfn - get file name
;
gfn: lxi h,gfnsd ;print 'which drive?'
call wcs
call rcc ;get answer from console
call wcc ;echo it to console
ani 5fh ;make upper case
cpi 'C'-40h ;^C means abort
jz gfn6
sui 'A'-1
jc gfn ;require alphabetic
jz gfn
cpi 17 ;allow 16 drives (as in CP/M 2.x)
jnc gfn
sta fcb
;
gfnb: lxi h,gfns1 ;print 'filename? '
call wcs
call rcs ;read response into ibuf
lxi h,fcb+fn ;blank fill fn and ft fields
mvi c,11
;
gfn1: mvi m,' '
inx h
dcr c
jnz gfn1
lxi h,ibuf ;point to input buffer
lxi d,fcb+fn ;scan off fn field
mvi c,9
;
gfn2: mov a,m ;fetch next char from ibuf
inx h
cpi 61h ;if lc, convert to uc
jc gfn2a
sui 20h
;
gfn2a: cpi cr ;jump if end of line
jz gfn5
cpi '.' ;jump if end of name
jz gfn3
stax d ;else store char in fn field
inx d
dcr c ;loop if 8 or less chars so far
jnz gfn2
jmp gfn6 ;else take error exit
;
gfn3: lxi d,fcb+ft ;scan off ft field
mvi c,4
;
gfn4: mov a,m ;fetch next char from ibuf
inx h
cpi 61h ;if lc, convert to uc
jc gfn4a
sui 20h
;
gfn4a: cpi cr ;jump if end of line
jz gfn5
stax d ;else store char in ft field
inx d
dcr c ;loop if 3 or less chars so far
jnz gfn4
jmp gfn6 ;else take error exit
;
gfn5: xra a
sta fcb+ex ;set extent number to zero
sta fcb+nr ;set record number to zero
stc ;clear error flag and return
cmc
ret
;
gfn6: stc ;set error flag and return
ret
;
gfnsd: db cr,lf,'Which drive? ',0
gfns1: db cr,lf,'Filename? ',0
;
;open - open disk file
;
open: push h
push d
push b
lxi d,fcb
mvi c,offc
call bdos
pop b
pop d
pop h
ret
;
;read - read record from disk file
;
read: push h
push d
push b
lxi d,fcb
mvi c,rrfc
call bdos
pop b
pop d
pop h
ret
;
;close - close disk file
;
close: push h
push d
push b
lxi d,fcb
mvi c,cffc
call bdos
pop b
pop d
pop h
ret
;
;delt - delete disk file
;
delt: push h
push d
push b
lxi d,fcb
mvi c,dffc
call bdos
pop b
pop d
pop h
ret
;
;write - write record to disk
;
write: push h
push d
push b
lxi d,fcb
mvi c,wrfc
call bdos
pop b
pop d
pop h
ret
;
;make - make new disk file
;
make: push h
push d
push b
lxi d,fcb
mvi c,mffc
call bdos
pop b
pop d
pop h
ret
;
;citest - check console input status
;
citest: push b
push d
push h
citcal: call $-$ ;modified by init.
ora a ;set zero flag
pop h
pop d
pop b
ret ;zero flag carries answer
;
;mitest - check modem input status
mitest: di
out 0
mvi a,0
sta 0ef08h
lda 2a00h
sta xyz
out 1
mvi a,1
sta 0ef08h
ei
lda xyz
ani 01h
cpi 00h
jnz mitst1
ora a
jmp mitst2
mitst1 cma
ora a
mitst2 ret
;
;
;motest - check modem output status
;
motest:
di
out 0
mvi a,0
sta 0ef08h
lda 2a00h
sta xyz
out 1
mvi a,1
sta 0ef08h
ei
lda xyz
xri 02h
ani 02h
mvi a,0
jz motst1 ;zero flag carries answer
cma
;
motst1: ora a ;set zero flag if ready
ret
;
;data area
;
xyz: db 00
inch: ds 1 ;input char buffer (to cyber)
outch: ds 1 ;output char buffer (from ciber)
stack: ds 80 ;local stack
ibuf: ds 256 ;input buffer
;
;text buffer
;
flag: ds 1 ;text save flag
ptr: ds 2 ;text buffer pointer
size: ds 2 ;text buffer size
tbuf: equ $ ;start of text buffer
;
end