; PLINK.ASM ver 6.5 ; (revised 6/26/81) ; ;PLINK is a CP/M transient command which allows the user to ;establish a communications link with a remote computer. ; ;This program currently supports the following modems or computers ;via conditional assembly: ; ; 1. PMMI modem ; 2. Any serial I/O board (TUART included) ; 3. TRS-80 model 1 ; 4. TRS-80 model 2 ; 5. Heath H8/H89 with 8250 uart at port 330Q ; 6. D.C.Hayes 80-103A or Micromodem 100 ; 7. MITS 2SI/O board, ports 10h &11h = console, 12h & 13h = modem ; 8. Intel SBC or National BLC multi-bus boards using 8251 USART ; ;Originally written by L.E. Hughes (EDCAM) in July, 1977. Many ;modifications have been made since this time, as shown in the ;following summary. ; ;Fixes/updates (in reverse order to minimize reading time): ; ; June 26, 1981. Added message when exiting if last buffer was ; not saved. Ted Shapin. ; ;June 14, 1981, by Keith Petersen, W8SDZ. Changed port ;equate to 'equ' instead of 'set'. ASM doesn't like 'set' ;when later conditionals are based on a label defined that ;way. ; ;June 7, 1981, by Tom Jorgenson (CP-MIG). Changed CP/M ;origin from being via SETs to referenced to BASE, added ;TRUE/FALSE rather than numeric values (for readability), ;changed ^Q function to ^W (write) because some systems ;(notably Micronet) use ^S/^Q to suspend/resume output, ;changed page 0 references in TRS routines to use ;BASE equate properly, changed PORT equates to default ;to TRUE, reinserted Heath equates, and cleaned up code ;in several places. ; ;June 7, 1981, by Keith Petersen, W8SDZ. Fixed problem with ;equates which prevented assembly by 'ASM' when TUART option ;was selected. ; ;June 6, 1981, by Keith Petersen, W8SDZ. Added version number, ;cleaned up file. ; ;May 12, 1981, by T. Shapin. Added code for 8251 USART on Intel ;SBC or National BLC multibus board with modified CP/M origin. ;Added prompt to signon. Added toggle to ^Y to save or ignore ;incoming text. Added ^C abort on file name response. ; ;November 10, 1980, by Kelly Smith. Added conditional assembly ;switch for MITS 2SI/O board, using "standard" MITS ports 10 and ;11 hex for the console, and 12 and 13 hex for the modem. ; ;October 18, 1980, by Keith Petersen, W8SDZ. ; ;Heath equates added by Tom Jorgenson. ; ;TRS-80 model 1 mods by Steve Vinokuroff, Vancouver CBBS. ; ;Optional trigger characters by Steve Vinokuroff. ; ;TRS-80 mods by Dennis Breckenridge, Burnaby CBBS. ; ;D.C.Hayes mods by Bruce Ratoff, Iselin New Jersey Remote CP/M. ; ;NOTE: If you add improvements or otherwise update ;this program, please modem a copy of the new file ;to "TECHNICAL CBBS" in Dearborn, Michigan - phone ;313-846-6127 (110, 300, 450 or 600 baud). Use the ;filename PLINKXX.NEW. ; ;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.) ; ;TRUE/FALSE definitions ; FALSE equ 0 TRUE equ NOT FALSE ; ;Conditional assembly switches <<-- set for your system ;(select only one as true) - (NOTE: use TUART for other ;serial ports not defined). ; MITSIO equ FALSE ;true, if MITS 2SI/O board H84 equ FALSE ;true, if you have H8/H8-4 or H89 TUART equ FALSE ;true, if Cromenco TUART or OTHER SERIAL PMMI equ TRUE ;true, if PMMI (set INITREQ true only ;if orig mode and parity is required) DCH equ FALSE ;true, if D.C.Hayes TRS1 equ FALSE ;true, if TRS-80 model 1 TRSPT equ FALSE ;true, if TRS-80 model 2 ;using pickles & trout CP/M 2.x MULTI equ FALSE ;true, if SBC or BLC 8251 USART ; INITREQ equ FALSE ;true, if port initialization required ; IF NOT TRSPT PORT equ TRUE ;true, on most systems ENDIF ; IF TRSPT PORT equ FALSE ;this is the oddball ENDIF ; ;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 ; IF MULTI mods equ 0DDH ;modem control mtbe equ 1 ;bit to test for send mrda equ 2 ;bit to test for receive mxor equ 3 ;mask to make MTBE and MRDA 'low true' modd equ 0DCH ;modem data port ENDIF ; ;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. ; ;modem i/o port addresses ; IF MITSIO modd equ 13h ;modem data port mods equ 12h ;modem status port modrset equ 03h ;6850 ACIA reset modinit equ 11h ;8 data, no parity, 2 stop ENDIF ; IF H84 modd equ 330Q ;modem data port mods equ 335Q ;modem status port ENDIF ; IF PMMI modd equ 0c1h ;modem data port mods equ 0c0h ;modem status port modinit equ 29h ;initialize byte originate, ;7 data, even parity, 1 stop ENDIF ; IF DCH modd equ 90h ;modem data port mods equ 91h ;modem status port modinit equ 05h ;7 data, even parity, 1 stop ENDIF ; IF TRS1 modd equ 0ebh ;TRS80 mod 1 rs232 data port mods equ 0eah ; and the rs232 status port ENDIF ; IF TUART modd equ 0d6h ;<<--modify for yours mods equ 0d7h ;<<--modify for yours ENDIF ; ;modem status port bit definitions ; IF H84 mtbe equ 40Q ;modem THRE transmit ready bit mrda equ 01Q ;modem RDA rec'd data bit mxor equ 41Q ;mask to make mtbe and mrda 'negative logic' ENDIF ; IF PMMI mtbe equ 01h ;modem trans. buffer ready flag mrda equ 02h ;modem receive data avail. flag mxor equ 03h ;mask to make mtbe and mrda "low true" ENDIF ; IF DCH or MITSIO mtbe equ 02h ;modem trans. buffer ready flag mrda equ 01h ;modem receive data avail. flag mxor equ 03h ENDIF ; IF TRS1 mtbe equ 40h ;TRS80 mod1 rs232 buffer ready mrda equ 80h ;modem receive data avail. mxor equ 0c0h ENDIF ; IF TUART ;<<--or any other serial i/o mtbe equ 1 ;<<--modify for yours mrda equ 2 ;<<--modify for yours mxor equ 3 ;<<--modify for yours ENDIF ; ; **main program** ; org base+100h ; link: 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 $ ; IF MITSIO mvi a,modrset out mods mvi a,modinit out mods ENDIF ; IF H84 mvi a,80h ;set dlab bit in 8250 uart out 0dbh ;8250 at port d8h (330q) nop ! nop ! nop nop ! nop mvi a,01h ;msb of baud rate divisor out 0d9h ;...to uart nop ! nop ! nop nop ! nop mvi a,80h ;lsb of baud rate divisor out 0d8h ;...to uart nop ! nop ! nop nop ! nop mvi a,03h ;8 bits, 1 stop bit, no parity, dlab reset out 0dbh ;...to uart nop ! nop ! nop nop ! nop mvi a,0 ;reset control register out 0dch ;...to uart jmp cont ENDIF ; IF INITREQ and (NOT H84) and (NOT MITSIO) mvi a,modinit out mods ;initialize modem port ENDIF ; IF INITREQ and TUART mvi a,80h ;dsr on bit 7 parl port b out 54h ENDIF ; IF TRSPT ;must set up serial channel reset: lxi h,initr ;store return address push h lhld 1 lxi d,setsio ;sio setup routine dad d push h ;store on stack mvi c,00h ;no parity chan-a mvi d,0e6h ;8 bits ,1 stop mvi e,3 ;300 baud mvi l,00h ;disable ext/ack sio functions mvi h,'S'-40h ;control s (x-on) ret ;trough setup prog ; initr nop ;do it to it ENDIF ; IF TRS1 ;init for TRS80 mod1 rs232 out 0e8h ;reset rs232 in 0e9h ;read the switches ani 0f8h ori 5 out 0eah ;set dsr and cts mvi a,55h ;300 baud out 0e9h ENDIF ; IF PORT in modd ;clear modem uart read buffers in modd ENDIF ; IF MULTI ;initialize 8251 xra a out mods out mods out mods mvi a,40h out mods mvi a,0cfh ;300 baud (this depends on strapping) out mods mvi a,37h out mods ENDIF ; 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,linkms ;print sign-on message call wcs ; ;main loop ; link3: call citest ;jump if no data from console jz link4 call rcc ;else read console data cpi 20h cc pcc ;call pcc if control char jc link4 ;jump if pcc handled char ori 80h ;else set valid data bit sta inch ;and store in input char buffer ; link4: lda outch ;jump if no data for console ora a jp link5 ani 7fh ;else discard valid data bit call wcc ;send char to console xra a ;then clear output char buffer sta outch ; link5: call mitest ;jump if no data from modem jz link6 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 ; link6: call motest ;jump if modem xmit buffer busy jz link7 lda inch ;jump if no data for modem ora a jp link7 ani 7fh ;discard valid data bit ; IF PORT out modd ;output char to modem ENDIF ; IF TRSPT push b ;store registers push h push d call wmc ;send char pop d pop h pop b ENDIF ; xra a ;...then clear input char buffer sta inch ; link7: jmp link3 ;end of main loop ; linkms: db cr,lf,'PLINK ver 6.5' 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 lhld size ; check for something in text buffer mov a,l ; and give warning ora h jz pccex ; before exit lxi h,ays ;print 'do you want to save... call wcs pop h call rcc ;get answer call wcc ;echo it ani 5fh ;make upper case cpi 'Y' ;yes? cz wtb ; write out buffer jmp pccex ;exit ; call wccr ;crlf ; stc ;tell plink to ignore this character ; IF TRSPT pop psw ;gobble up call address jmp reset ;re-initialize sio ENDIF ; IF PORT ret ENDIF ; 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,'Do you want to save the stuff in' db cr,lf,'the buffer before exit to CP/M (Y or N)? ',0 ; IF PMMI or DCH disms: db cr,lf,'Don''t forget - the modem ' db 'is not disconnected',cr,lf db 'use "MODEM D" to disconnect',0 ENDIF ; IF (NOT PMMI) and (NOT DCH) disms: db cr,lf,'+++ Exit to CP/M +++',cr,lf,0 ENDIF ; 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,link ;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 ; ; IF PORT wmc: push psw ; wmcl: in mods xri mxor ani mtbe jnz wmcl pop psw ani 7fh ;strip parity bit out modd ret ENDIF ; IF TRSPT wmc: push h push d push psw ; wmcl: call motest ;test status jz wmcl ;loop till tx empty pop psw ;restore char ani 7fh ;strip parity push b ;store b mov c,a ;put char into c mvi b,00h ;channel a lxi h,wmcre ;store return address push h lhld base+1 ;get base address lxi d,sioout dad d pchl ;jump to it ; wmcre: pop b ;restore it pop d pop h ret ENDIF ; ;rmc - read modem character ; ; exit conditions: ; a - character read ; ; IF PORT rmc: in mods xri mxor ani mrda jnz rmc ; rmc2: in modd ani 7fh ret ENDIF ; IF TRSPT rmc: call mitest ;char available jz rmc ;loop if not ready ; rmc2: push b ;store b push d push h mvi b,00h ;channel a lxi h,rmcre ;return address push h lhld 1 lxi d,sioinp dad d pchl ; rmcre: pop h pop d pop b ani 7fh ;strip parity ret ENDIF ; ;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 ; IF PORT mitest: in mods ;get modem uart status xri mxor ;invert high-true bits ani mrda ;any data available? mvi a,0 jnz mitst1 cma ; mitst1: ora a ret ;zero flag carries answer ENDIF ; IF TRSPT ; mitest: push b push h push d mvi b,00 ;channel a lxi h,mitstr push h lhld base+1 lxi d,siotst dad d pchl ; mitstr: pop d pop h ani 01 ;tx empty pop b ret ;zero flag holds the answer ENDIF ; ;motest - check modem output status ; IF PORT motest: in mods ;get modem uart status xri mxor ;invert high-true bits ani mtbe ;uart ready for character? mvi a,0 jnz motst1 ;zero flag carries answer cma ; motst1: ora a ;set zero flag if ready ret ENDIF ; IF TRSPT motest: push b push h push d mvi b,00 ;channel a lxi h,motstr push h lhld 1 lxi d,siotst dad d pchl ; motstr: ani 02 ;buffer empty pop d pop h pop b ret ENDIF ; ;data area ; 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