;LCOMM/ASM - COMM Communications Program TITLE SUBTTL '' ; BUFFRD EQU -1 ;Set true BREAK EQU 80H ;Char fm keyboard LF EQU 10 CR EQU 13 XOFF EQU 'S'&1FH ; *GET SVCMAC:3 ;SVC Macro equivalents *GET COPYCOM:3 ;Copyright messages ; BASE EQU 3000H ORG BASE ; $EXIT LD HL,0 ;Init no error QUIT$ LD SP,$-$ ;P/u original stack STACK EQU $-2 @@CKBRKC ;Clear break bit RET ; $ABORT LD HL,-1 ;Set abort code JR QUIT$ ; $OPEN PUSH HL LD HL,$-$ ;Address of SFLAG$ SFLG EQU $-2 SET 0,(HL) ;Set open inhibit bit POP HL @@OPEN ;Do the open RET ;Return with status ; $ERROR PUSH BC OR 0C0H ;Set short,return LD C,A ;Error code to C @@ERROR ; for error display POP BC RET ; MAINLP LD A,0 ;Test warning flag set OR A ; by OUTPUT on NEXTAP JR Z,ENUFPG ;Go if > 2K of space LD HL,LILPG$ ;Display warning @@DSPLY LD A,XOFF ;Schedule a forced PUT XOFFP2 EQU $-1 LD (FRCPUT+1),A XOR A LD (MAINLP+1),A ;Inhibit until next page ENUFPG LD IX,KIVCTR ;Get key from buffer if CALL PGMGET ; available JR NZ,SENDIT ;Bypass if got one FSSW LD A,0 ;FS On/Off (XMIT File) OR A JR Z,FSOFF ;Bypass if not XMTG CKFREPG LD A,(FREEPG) ;Don't get from file CP 12 ; if < 3K buffer space JP C,FSOFF ;Go if less LD DE,FS_FCB ;Get sending FCB FSSWGO @@GET ;Get a byte to XMIT JR Z,SENDIT ;Bypass if got byte CP 1CH ;EOF encountered? JR Z,EOFFS ;Bypass if EOF CALL $ERROR ;Output error message EOFFS CALL FS_OFF ;Turn off XMIT JP SKIPREC ; and ignore this round SENDIT LD C,A ;Xfer byte XLTS1 CP 0 ;Single character send JR NZ,DPLXSW ; translate table XLTS2 LD C,0 DPLXSW LD B,0 ;Duplex On/Off INC B DEC B ;Display on our devices CALL NZ,DEVOUT ; if duplex on (half) LCMON LD A,(TASK8A+2) ;Ck CL on OR A CALL NZ,SNDOUT ;Send char if ON FSOFF LD A,(TASK8A+2) ;Test for CL ON OR A JP Z,SKIPREC ;Go if not LD IX,CLREC CALL PGMGET ;Ck for char avail JP Z,SKIPREC ;Go if no char DSPCTRL LD B,0 ;Ck if display of control INC B ; codes is in effect DEC B JR Z,SAVCHR ;Go if no ctrl display CP 20H JR NC,SAVCHR ;Go if not ctrl PUSH AF ;Save the char LD HL,BRAKET+1 ;Pt to control char msg LD C,A @@HEX8 ;Cvrt char & stuff in buf LD HL,BRAKET ;Start of msg string @@DSPLY ;Display ASCII control value POP AF ;Rcvr char SAVCHR LD C,A ;Save char SHAKE LD B,0 ;Handshake On/Off INC B DEC B JR Z,ECHOSW ;Go if off CP 'Q'&1FH ;Ctrl-Q? XONP1 EQU $-1 ;Modify if PARM JR Z,CTLQ ;Go if so CP 'S'&1FH ;Ctrl-S? XOFFP1 EQU $-1 ;Modify if parm entered JR NZ,NOSQ ;Go if neither LD B,0 ;Turn off CTLQ LD A,B ; or on LD (TASK8B+1),A ;*CL send task JR SKIPREC ;Discard ctrl code NOSQ CP 'R'&1FH ;Ctrl-R? JR Z,CTLR ;Go if so CP 'T'&1FH ;Ctrl-T? JR NZ,ECHOSW ;Go if neither LD B,0 ;Turn off CTLR LD A,B ; or on LD (FRSW+1),A ;FR device JR SKIPREC ;Discard ctrl code ; ; Test for ECHO after checking for handshake chars ; ECHOSW LD B,0 ;Echo On/Off? INC B DEC B CALL NZ,CLOUT ;Send char back if ON LD A,C CP CR ;Was it a CR? JR NZ,NOTCR CALL ECLF1 ;Send LF back if needed LD HL,CRSW+1 ;Flag for CR recvd ; ; Move state of ACCEPT LF switch into CRSW+1 when CR recv'd ; ACCLFSW LD A,0 ;Show CR found if accept LD (HL),A ; LF switch is off JR TAKEREC ;Dsp CR ; ; When LF rcv'd, delete if ACCLFSW is off & last char was CR ; NOTCR LD A,C ;Check char CRSW LD B,0FFH ;P/u del LF switch LD HL,CRSW+1 ;Pt to switch LD (HL),0FFH ; (flip off switch -not CR) CP LF ;Is line feed the char? JR NZ,TAKEREC ;Go if not LF LD A,(EIGHT+1) ;Also skip if 8 bit OR B ; switch is off JR Z,SKIPREC ;Skip LF if so ; TAKEREC CALL DEVOUT ;Out to active devices SKIPREC CALL TASKS ;Do 3 tasks (incl kbd) JP MAINLP ; & FRIO test then loop ; CLOUT LD A,C ;Get char LD IX,CLSEND ;Set buffer pointers JP OUTPGM ;Put in output buffer ; SNDOUT CALL CLOUT ;Send this character LD A,C ;Is it CR? CP CR RET NZ ;Done if not ; ECLF1 LD A,$-$ ;Is echo linefeed on? ECOLF EQU $-1 OR A RET Z ;Done if not LD A,LF ;Otherwise load a LF LD IX,CLSEND JP OUTPGM ;Add to buffer/ret to caller ; ; Output to video ; DEVOUT LD A,0FFH ;Is *DO On/Off? OR A JR Z,FRSW ;Bypass if off LD A,C CP 0CH ;If formfeed, LD C,A PUSH BC JR NZ,NOTCLS ; clear the screen LD C,1CH ;Cursor home @@DSP LD C,1FH ;Clear to end-of-frame NOTCLS @@DSP POP BC ; ; Send char to our disk if FR on ; FRSW LD A,0 ;FR On/Off - receive file OR A JR Z,PUTPR ;Bypass if FR off LD A,C LD IX,FRVCTR ;Put away into the CALL OUTPGM ; FR buffer ; ; Place char into printer buffer if PR on ; PUTPR LD A,0 ;PR On/Off? OR A JR Z,FRIOSW ;Go if off LD A,C LD IX,PRVCTR ;Place the char in CALL OUTPGM ; the printer buffer ; ; Check if FR to disk is engaged ; FRIOSW LD A,-1 ;Ck if FR-to-disk is on OR A RET Z ;Go if not engaged LD IX,FRVCTR ;Is a char available CALL PGMGET ; for the disk? RET Z ;Go if none for disk LD HL,FR_FCB ;Put char to disk BIT 7,(HL) ;OPEN FCB? RET Z ;Skip if not EX DE,HL LD C,A ;Place char in "C" @@PUT ; and do the write RET Z ;Back if good CALL $ERROR CALL FRIO_OFF ;Turn FRIO to disk off JP FR_OFF ;Turn FR off and return ; ; command function entered - decode it ; CMDKEY LD BC,0 ;Init no device vector LD DE,0 ;Init no File FCB LD HL,DSPCTRL+1 ;Pt to ctrl char dsply parm IF @MOD4 CP 27H!80H ;Display control chars? ENDIF IF @MOD2 CP '&'+80H ENDIF JP Z,QFUNC ; LD HL,DPLXSW+1 CP '!'+80H ;Ck duplex JP Z,QFUNC ; LD HL,ECHOSW+1 IF @MOD4 CP '"'+80H ;Ck echo ENDIF IF @MOD2 CP '@'+80H ENDIF JP Z,QFUNC ; LD HL,SHAKE+1 ;Check handshake IF @MOD4 CP '*'+80H ENDIF IF @MOD2 CP '_'+80H ENDIF JP Z,QSHAKE ; LD HL,ECOLF CP '#'+80H ;Echo line feed? JP Z,QFUNC ; LD HL,ACCLFSW+1 ;Check accept-LF CP '$'+80H JP Z,QFUNC ; LD HL,EIGHT+1 ;Check 8-bit IF @MOD4 CP ')'+80H ENDIF IF @MOD2 CP '('+80H ENDIF JP Z,QFUNC ; LD BC,KIVCTR ;Init *KI put/get index LD HL,KISW+1 CP '1'+80H ;CK *KI JP Z,QFUNC ; LD BC,0 ;No *DO put/get index LD HL,DEVOUT+1 CP '2'+80H ;CK *DO JR Z,QFUNC ; LD BC,PRVCTR ;Init *PR put/get index LD HL,PUTPR+1 CP '3'+80H ;CK *PR JR Z,QFUNC ; LD BC,CLSEND ;Init *CL-S put/get index LD HL,TASK8A+2 CP '4'+80H ;CK *CL JR Z,QCL ; LD BC,FSVCTR ;Init *FS put/get index LD DE,FS_FCB ;Init *FS FCB LD IX,XMTBUF ;Point to buffer LD HL,FSSW+1 CP '5'+80H ;CK FS JR Z,QFUNC ; LD BC,FRVCTR ;P/u *FR put/get index LD DE,FR_FCB ;P/u *FR FCB LD IX,RCVBUF ;Pt to buffer LD HL,FRSW+1 CP '6'+80H ;CK FR JR Z,QFUNC ; LD HL,FRIOSW+1 LD DE,0 ;No FCB here CP '7'!80H ;Check FR IO to disk? JR Z,QFUNC ; CP '8'!80H ;Menu request? JP Z,MENU ; IF @MOD4 CP '('!80H ;Local clear screen? ENDIF IF @MOD2 CP '*'+80H ENDIF JP Z,CLS ; IF @MOD4 CP 20H!80H ;Clr-shf-0? ENDIF IF @MOD2 CP ')'+80H ENDIF JP Z,DOSCMD ;Do CMDR ; IF @MOD4 CP '='+80H ;CK LDOS exit ENDIF IF @MOD2 CP '+'+80H ENDIF JP NZ,CMDERR ; ; ; Exit from LCOMM - Remove task vectors ; EXIT IF .NOT.BUFFRD LD C,8 ;Remove comm line scan task @@RMTSK ; LD C,9 ;Rmv printer task if used @@RMTSK ENDIF ; IF BUFFRD LD DE,CLDCB ;Turn off wakeup feature LD IY,$-$ OLDVEC EQU $-2 ;Restoring previous state LD C,4 @@CTL ENDIF ; CALL FR_OFF ;Turn off any receive file LD DE,FR_FCB LD A,(DE) BIT 7,A ;Is it an open file? JP Z,$EXIT ;Exit if not else @@CLOSE ; make sure it's closed JP Z,$EXIT ;Exit if no error CALL $ERROR JP $ABORT ;Terminate ; ; Query function ON or OFF ; QFUNC CALL QONOFF ;Get On or Off response LD (HL),A ;Save which one RET ; ; Query *CL on or off ; QCL CALL QONOFF LD (HL),A OR A ;On or off? RET Z ;Quit if off LD (TASK8B+1),A ;Force CL-send on as well RET ; ; Query handshake on or off ; QSHAKE PUSH DE @@KEY ;Get one key POP DE AND A ;Be sure flags are set JP M,QSHAKE1 ;Go if PF key LD (AUTXOFF+1),A ;Save key as auto XOFF LD (HL),0FFH ;Turn on handshake RET QSHAKE1 CALL QONOFF1 ;Parse ON or OFF LD (HL),A ;Turn on or off XOR A ;Turn off auto XOFF LD (AUTXOFF+1),A RET QONOFF PUSH DE ;Hang on to register @@KEY ;Get the operand key POP DE ;Restore the register QONOFF1 EQU $ IF @MOD4 CP '-'+80H ;Ck OFF ENDIF IF @MOD2 CP '='+80H ENDIF JR Z,TURNOF ; and go if off IF @MOD4 CP ':'+80H ;Ck ON ENDIF IF @MOD2 CP '-'+80H ENDIF JR Z,TURNON ; and go if on POPERR EX (SP),HL ;Discard ret address POP HL CP '9'+80H ;Ck ID JP Z,FILID ; CP '0'+80H ;Ck RESET JP Z,FILRES ; CP '%'+80H ;Ck REWIND JP Z,FILREW ; IF @MOD4 CP '&'+80H ;Ck PEOF ENDIF IF @MOD2 CP '^'+80H ENDIF JP Z,FILEOF ; CMDERR LD HL,CMDERR$ ;None of above, dsply @@DSPLY ; "Unacceptable command... RET ; ; Process OFF ; TURNOF XOR A ;Off = 0 RET ; ; Process ON ; TURNON EX DE,HL ;Shift "FCB" to HL BIT 7,(HL) ;FCB on or non-file? EX DE,HL ;If non-file, HL now LD A,0FFH ; points to X'0000' RET NZ ; which contains X'F3' JR POPERR ;Is an error ; ; Process Clear Screen ; CLS LD C,1CH ;Cursor home @@DSP LD C,1FH ;Clear to end-of-frame @@DSP RET ; ; Process MENU ; MENU EQU $ LD HL,STAT1 ;Clear top row status LD DE,STAT1+1 ;1st char always a space LD BC,66 LDIR LD HL,STAT2 ;Clear bottom row status LD DE,STAT2+1 LD C,38 LDIR LD B,15 ;Init loop count LD HL,STATAB ;Words where status stored STATLP1 LD E,(HL) ;P/u lo-switch INC HL LD D,(HL) ;P/u hi-switch INC HL LD A,(HL) ;P/u lo-stuff INC HL PUSH HL ;Save pointer LD H,(HL) ;P/u hi-stuff LD L,A ;Xfer lo-stuff LD A,(DE) ;Get status OR A ;Active or not? JR Z,$+4 ;Go if not LD (HL),'*' ; else stuf an '*' POP HL ;Rcvr pointer INC HL ;Bump to next pos DJNZ STATLP1 LD A,(DE) ;P/u shake again OR A JR Z,STATLP2 ;Go if off LD A,(AUTXOFF+1) ;Check if xoff char set OR A JR Z,STATLP2 ;Skip if not special char LD HL,STAT1+63 ;Auto x-off char posn LD C,A @@HEX8 ;Cvrt to ASCII for display STATLP2 LD HL,MNUMSG ;Ptr to Comm menu @@DSPLY ;Display prelim status LD HL,FS_FCB ;FS file open? BIT 7,(HL) JR Z,STATLP3 ;Go if closed LD DE,DUMMY ;Recover its name w/o PUSH DE ; changing the FCB LD BC,32 LDIR ; by creating a duplicate POP DE ; open FCB LD BC,(DUMMY+6) ;Get drive and DEC PUSH DE @@FNAME ;Call for name recover LD HL,FSNAME$ ;Output "FS-SPEC: " @@DSPLY POP HL ;Rcvr fcb pointer and @@DSPLY ; display the filespec STATLP3 LD HL,FR_FCB ;Is the FR file open? BIT 7,(HL) JR Z,STATLP4 ;Go if closed LD DE,DUMMY ;Similar to above PUSH DE LD BC,32 LDIR ;Create a duplicate FCB POP DE LD BC,(DUMMY+6) ;P/u Drive & DEC PUSH DE @@FNAME ;Call for name recover LD HL,FRNAME$ ;"FR-SPEC:" @@DSPLY POP HL ;P/u name start @@DSPLY ; and dsply it STATLP4 LD A,(FREEPG) ;How much buffer left RRCA ;Divide by 4 to show RRCA ; in K AND 3FH ;No bit 7 nor 6 LD HL,PAGSPR$+10 ;Where to stuff LD B,-1 ;Init to count 10's CVD1 INC B SUB 10 ;How many tens? JR NC,CVD1 ;Go if no more CVD2 PUSH AF ;Save remainder LD A,B ;P/u tens OR A ;Was it zero tens? LD B,' ' ;Init for space JR Z,$+4 ;Go if no tens LD B,'0' ;Init for ASCII ADD A,B ;Convert to ASCII LD (HL),A ;Stuff & bump INC HL POP AF ;Get remainder ADD A,3AH ;Adjust units place LD (HL),A LD HL,PAGSPR$ ;"Memory: K" @@DSPLY RET ; ; Process RESET of a "device" ; FILRES LD A,B ;Check if a device vector OR C ; was passed JP Z,CMDERR ;Go if not - is error LD A,D ;Check for a possible OR E ; FCB for disk JR NZ,FILR4 ;Go if disk else device ; ; Reset the page buffer(s) for the device ; FILR1 DI ;No interrupts until done LD H,B ;Xfer vector table entry LD L,C ; to grab put/get index LD C,(HL) ;P/u the PUT pointer INC HL ; and make the GET LD B,(HL) ; pointer equal so INC HL ; buffer contents show LD (HL),C ; as empty INC HL LD A,(HL) ;P/u the GET pointer to LD (HL),B ; check if in same page FILR2 CP B ;Is put/get in same page? JR Z,FILR3 ;Go if it is LD H,A ; else set up to free this CALL FNPIU ; page by finding next JR FILR2 ;Loop until next = 1st FILR3 EI ;Interrupts back on RET ; ; Reset a file device ; FILR4 LD HL,FR_FCB ;Turn off the FR or FS XOR A SBC HL,DE ;Is this the FR? LD HL,FSSW+1 JR NZ,OFFS LD (FRIOSW+1),A ;Turn off FR IO to disk LD HL,FRSW+1 ;Turn off FR to buffer OFFS LD (HL),A ;Turn off FR or FS @@CLOSE ;Close the file CALL NZ,$ERROR ;Show any close error RET ; ; Process REWIND ; FILREW LD A,D ;Rewind the specified OR E ; file (FCB given) if JP Z,CMDERR ; it is in use @@REW RET ; ; Process PEOF ; FILEOF LD A,D ;Check if a file device OR E ; was specified JP Z,CMDERR ;Go if not - is error @@PEOF ; else position to end RET ; ; Process ID request ; FILID LD A,D ;Bad command if not OR E ; FS or FR specified JP Z,CMDERR ;Go on error LD A,(DE) ;Make sure that it is RLCA ; not already open JR C,NOTNOW ;CF=already open PUSH DE PUSH IX ;Save buffer pointer LD HL,FILEPMT ;Prompt for filespec @@DSPLY POP HL ;Take file name LD BC,31<8 ;31 chars max @@KEYIN ;Get the filespec PUSH AF ;Save flag state LD C,0EH ;Turn the cursor back on @@DSP POP AF ;Rcvr KEYIN exit state POP DE RET C ;Ret if BREAK from KEYIN PUSH HL ;Save ptr to buffer @@FSPEC ;Fetch & parse filespec LD HL,FS_FCB ;Ck if FILID req from XOR A ; FS or FR SBC HL,DE ;What's the FCB? POP HL ;Recover buffer LD B,0 ;LRL=256 JR NZ,FILFR ;Go if req from FR CALL $OPEN ;Only OPEN a FS JR $+5 ;Branch around INIT FILFR @@INIT ;Open the receive file CALL NZ,$ERROR ;Show any open error RET ; NOTNOW LD HL,OPENMSG ;"File already open" @@DSPLY ;Show why ID failed RET ; ; Routines to turn off file devices ; FS_OFF XOR A ;File send LD (FSSW+1),A RET FR_OFF XOR A ;File receive LD (FRSW+1),A RET FRIO_OFF XOR A ;Dump to disk LD (FRIOSW+1),A RET ; ; Call various tasks (on each main loop) ; TASKS DI ; IF .NOT.BUFFRD ;W fcn does this if bfrd CALL TASK8A ;Try to receive from *CL ENDIF ; CALL TASK8B ;Try to send to *CL EI CALL TASKK ;Allow interrupts here IF .NOT.BUFFRD DI ;If RS232 does not interrupt ENDIF ;Printer must be task CALL TASK9 EI JP FRIOSW ;Check on dump to disk ; ; INTERRUPT TASK 8 ; WO/buffer A is done once per main loop + int rate ; B is done once per main loop + int rate ; W/buffer A is done by wakeup feature + int rate ; B is done once per main loop + int rate ; IF .NOT.BUFFRD TCB8 DW TASK8 TASK8 CALL TASK8A JP TASK8B ENDIF ; TASK8A DI LD A,0FFH ;CL recv On/Off OR A RET Z ;Done if CL recv off ; ; @GET handler to keep interrupts off if possible ; LD DE,CLDCB ;=> OPEN DCB FNDDVR LD H,D ;Xfer to HL LD L,E LD A,(HL) ;Get DCB type BIT 5,A ;Is it linked? JR NZ,LNKD ;Need CHNIO if so INC HL ;=>address field of DCB LD E,(HL) ;If routed, address is INC HL ; next DCB to use LD D,(HL) ; else EP of driver BIT 4,A ;Z = not routed JR NZ,FNDDVR ;Loop till not routed AND 00001000B ;Can't talk to NIL device RET NZ EX DE,HL ;Address to HL LD DE,RETADD ;Put RET address on stack PUSH DE ; CP 2 ;Set C,NZ for input request JP (HL) ;Go to driver ; LNKD @@GET ;Use SVC if LINKED RETADD RET NZ ;NZ means no char rcv'd ; EIGHT LD B,0 ;Eight bit mode switch INC B DEC B JR NZ,XLTR1 ;Go if 8 bit AND 7FH ;Strip bit 7 RET Z ;Always ignore nulls CP 7FH ; & DELETE if not 8-bit RET Z ; ; Do XLATER after stripping high bit ; XLTR1 CP $-$ ;Character to translate? JR NZ,TSTNUL ;Go if not a match XLTR2 LD A,$-$ ;Replace with xlated char ; ; NULL Parm now only affects 8-bit mode ; TSTNUL OR A ;Is char a null? JR NZ,KEEPCH ;Go if not ACCNUL LD B,0FFH ;Default to accept nulls INC B ;NZ=nulls wanted DEC B ;Z=don't accept nulls RET Z ; KEEPCH PUSH IX ;Place in CL input buf LD IX,CLREC CALL OUTPUT ;Out to the buffer if POP IX ; non-null or want nulls RET ; TASK8B LD A,0FFH ;CL send On/Off for OR A ; handshaking RET Z LD C,0 ;Now xmit a CTL0 to LD DE,CLDCB ;Ck the status of the @@CTL ; CL RET NZ ;Indicates not ready FRCPUT LD C,$-$ ;Force a char out? XOR A ;Clear it after p/u LD (FRCPUT+1),A OR C ;Check original status JR NZ,FRCIT ;Go if force on PUSH IX LD IX,CLSEND ;Do we have a char to CALL BUFGET ; send to the CL? POP IX RET Z ;RET if not LD C,A ;Save character FRCIT @@PUT ;Put it out ; AUTXOFF LD A,0 ;Check for auto XOFF OR A ;On? RET Z ;Quit if not SUB C ;Matched char? RET NZ ;Quit if not LD (TASK8B+1),A ;Pause xmit (XOFF) RET ; TASKK @@KBD ;Scan the keyboard RET NZ ;Error (or no key depressed) CP BREAK ;Ck for brk 1st JR Z,ISBRK ;Go on a Break OR A ;Then for high bit set JP M,CMDKEY ;Go if FN key KISW LD B,0FFH ;KI On/Off INC B DEC B RET Z ;Ret if KI is off NOTBRK PUSH IX LD IX,KIVCTR ; else put key into CALL OUTPGM ; the output buffer POP IX RET ; ISBRK DI LD DE,CLDCB ;Pt to *CL LD C,1 ;Send CTL 1, a @@CTL ; Break request EI LD BC,CLSEND CALL FILR1 ;Reset the CL buffer CALL FS_OFF ;Turn off the *FS LD BC,2000H ;Time delay @@PAUSE @@CKBRKC ;Reset the break bit LD C,0 ;Init the character LD DE,CLDCB ;P/u the CL DCB DI @@PUT ;Send the 0 EI RET ; ; INTERRUPT TASK 9 ; Only if RS232 does not interrupt ; IF .NOT.BUFFRD TCB9 DW TASK9 ;Task ept ENDIF TASK9 LD B,3 ;Max chars/pass PRLOOP LD C,0 ;Test printer status LD DE,$-$ ;PDCB$ PRDCB EQU $-2 @@CTL ;Check the status RET NZ ;Ret if unavailable PUSH IX LD IX,PRVCTR ;Get char from printer IF BUFFRD CALL PGMGET ELSE CALL BUFGET ;Buffer if available ENDIF POP IX RET Z ;None to get, back LD C,A @@PRT ;Output to printer DJNZ PRLOOP ;Loop if more RET ; ; Common routine to stuff various buffers ; OUTPUT LD L,(IX) ;P/u pointer to LD H,(IX+1) ; buffer PUT LD (HL),A ;Write char into buffer INC (IX) ;Bump buffer pointer RET NZ ;Go if still in same page CALL NEXTAP ;Find next avail page JR Z,DUMPCHR ;Go if no pages available LD (IX+1),A ;Set index to new page LD HL,FREEPG ;Reduce the amount of DEC (HL) ; free pages LD A,7 ;Less than 2K available? CP (HL) RET C ; & return with NZ LD (MAINLP+1),A ;Set flag for warning OR A ;Ensure NZ return RET ; ; No more pages available - keep last page ; DUMPCHR DEC (IX) ;Dump character and XOR A ; return RET ; ; The following code is not executed, as it is too ; slow at rates >= 1200 baud because interuppts are on. ; DE must be loaded with KIVCTR. ; DB 0 PUSH IX ;Dev requesting the output POP HL XOR A ;The difference will be SBC HL,DE ; the offset into the LD DE,DEVICE$ ; name table ADD HL,DE LD BC,4 LD DE,OVRRUN$+3 LDIR LD HL,OVRRUN$ ;Display the buffer @@DSPLY ; overrun error XOR A ; reuse current page RET ; ; Check for character available in dynamic buffer ; BUFGET LD L,(IX+2) ;P/u pointer to next LD H,(IX+3) ; buffer GET LD A,L ;Check on in=out lo-order CP (IX) JR NZ,INNEOUT ;Go if in not equal out LD A,H ;Check on in=out hi-order CP (IX+1) RET Z ;Ret if none to i/o ; ; Buffer is not empty - Get next character ; INNEOUT LD A,(HL) ;Get a char from buffer INC (IX+2) ;Advance lo-order pointer RET NZ ;Ret if still same page PUSH AF ;Save the character CALL FNPIU ;Find next page in use LD (IX+3),A ;Stuff new page index POP AF ;Recover the character DEC H ;Set NZ return for rcvd RET ; ; Routine to find next available page buffer ; NEXTAP LD L,H ;Point to page buffer LD H,LINKS<-8 ; index LD A,(LINKS) ;Get next empty link PUSH HL ;Save this index pointer LD L,A ;Point to new link LD A,(HL) ;Get what it links to OR A ;Test if none left JR NZ,GOTNAP ;Go if still more POP HL ;Restore reg & return RET ; with Z-flag for error ; ; Found the next available page - set the links ; GOTNAP LD (LINKS),A ;Update new next avail LD A,L ;Xfer index of new page POP HL ;Rcvr pointer to index LD (HL),A ; of old & link to new LD L,A ;Repoint to new page's LD (HL),0 ; index & show it is RET ; the last one ; ; Find next page in use ; FNPIU LD A,(FREEPG) ;Show one additional INC A ; page is free LD (FREEPG),A LD A,(HIPAGE) ;P/u highest page avail LD L,A ;Set HL to its index LD A,H LD H,LINKS<-8 ;Show that page links to LD (HL),A ; the one we just emptied LD (HIPAGE),A ;Now update the new end LD L,A ;Set HL to the emptied LD A,(HL) ; page, p/u what it LD (HL),0 ; linked to, & show old RET ; is end. Ret A=link ; ; Execute a DOS command ; DOSCMD LD HL,BASE-1 LD B,1 ;Set LOW$ @@HIGH$ LD HL,CMDPMT ;Issue prompt @@DSPLY LD BC,80<8 ;Max characters LD HL,DUMMY ;=>input buffer @@KEYIN ;Get command request RET C ;Back on Break INC B DEC B RET Z ; or CR only EX DE,HL LD HL,$-$ ;Pt to CFLAG$ CFLAG EQU $-2 BIT 0,(HL) ;Get current status PUSH HL PUSH AF ;Save memory freeze status SET 0,(HL) ;Freeze memory EX DE,HL @@CMNDR ;Do the command LD HL,CMPLTD ;Show cmd finished @@DSPLY POP AF ;Get the previous status POP HL ; and CFLAG$ location RET NZ ;Back if was set before RES 0,(HL) ; else restore it RET CMDPMT DB LF,LF,'Enter command:',CR CMPLTD DB LF,'Command completed',CR ; ; Messages ; BRAKET DB '{ }',3 ;Brackets around hex byte FILEPMT DB 29,10,'File name: ',3 OPENMSG DB 29,10,'File already open',CR MNUMSG DB LF STAT1 DB ' ' DB ' ',LF DB 'DUPLX ECHO ECOLF ACCLF REWND PEOF ' DB ' DCC CLS 8-B CMD HNDSH EXIT',LF DB '==1== ==2== ==3== ==4== ==5== ==6== ' DB '==7== ==8== ==9== ==0== ' IF @MOD4 DB '==:== ==-==' ENDIF IF @MOD2 DB '==-== =====' ENDIF DB LF DB ' *KI *DO *PR *CL *FS *FR ' DB ' DTD ??? ID RES ON OFF',LF STAT2 DB ' ' DB ' ',CR STATAB DW KISW+1,STAT2+2,DEVOUT+1,STAT2+8 DW PUTPR+1,STAT2+14,TASK8B+1,STAT2+19 DW TASK8A+2,STAT2+21,FSSW+1,STAT2+26 DW FRSW+1,STAT2+32,FRIOSW+1,STAT2+38 DW DPLXSW+1,STAT1+2,ECHOSW+1,STAT1+8 DW ECOLF,STAT1+14,ACCLFSW+1,STAT1+20 DW DSPCTRL+1,STAT1+38,EIGHT+1,STAT1+50 DW SHAKE+1,STAT1+61 FSNAME$ DB 'FS-Spec: ',3 FRNAME$ DB ' FR-Spec: ',3 PAGSPR$ DB ' Memory: K',CR CMDERR$ DB '** Invalid command sequence **',CR LILPG$ DB 'Warning! Less than 2K of buffer left ' DB ' X-OFF transmitted',CR ; ; File control blocks ; CLDCB DS 32 FS_FCB DS 32 FR_FCB DS 32 DUMMY DS 81 ;Used for dos cmd buffer also ; ; Put/Get index pointers ; KIVCTR DW 0,0 PRVCTR DW 0,0 CLREC DW 0,0 CLSEND DW 0,0 FSVCTR DW 0,0 FRVCTR DW 0,0 FREEPG DS 1 ; ; Routines to buffer I/O in pgm loop ; OUTPGM DI CALL OUTPUT EI RET PGMGET DI CALL BUFGET EI RET ; ; Page buffer Link table ; ORG $<-8+1<+8 LINKS DS 1 ;Link to next available HIPAGE DS 1 ;Link to last available DS 1 ;Init to 1st avail DS 1 ;Init to last avail DS 252 ;Space for linkage tables ; ; Transmit and Receive File buffers ; XMTBUF DS 256 RCVBUF DS 256 ; SUBTTL <'COMM initialization code'> PAGE OFF *GET LCOMMA:3 ;Initialization code ; END LCOMM