home *** CD-ROM | disk | FTP | other *** search
- ;
- ;MODEM.ASM V4.0, BY WARD CHRISTENSEN
- ; (Revised 8/6/79)
- ;
- ;CP/M - CP/M FILE TRANSFER PROGRAM, AND
- ;TERMINAL PROGRAM.
- ;
- ;NOTE: THIS FILE WILL ASSEMBLE, WITHOUT NEED FOR
- ;EDITING, TO WORK WITH A PMMI MM-103 MODEM. SEE
- ;EQUATES FOR OTHER OPTIONS INCLUDING SYSTEM CLOCK
- ;FREQUENCY.
- ;
- * * * * * * * * * * * * * * * * * * * * * * * * *
- * *
- * THIS PROGRAM DOCUMENTED IN "MODEM.DOC" *
- * *
- * * * * * * * * * * * * * * * * * * * * * * * * *
- * THIS PROGRAM WAS "MODEM.ASM" BUT IS *
- * TEMPORARILY NAMED "MODEM2.ASM" SO PEOPLE *
- * WILL REALIZE IT IS AN ENHANCEMENT OF *
- * THE ORIGINAL PROGRAM "MODEM.ASM" ON CP/M *
- * USER'S GROUP DISK 25. *
- * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- ;PLEASE PASS ON MODS, BUGS, ETC, SO YOUR
- ;FIXES OR ENHANCEMENTS MAY BE SHARED BY ALL,
- ; TO:
- ; Ward Christensen
- ; 688 E. 154th St. #5D
- ; Dolton, Il. 60419
- ;
- ; (312) 849-6279
- ;
- ;You may send a self-addressed stamped postcard
- ;to be informed of changes/bugs as they become
- ;known.
- ;
- ; --------------
- ;
- ; 09/23/77
- ;ORIGINALLY WRITTEN BY WARD CHRISTENSEN
- ;
- ; 04/26/79
- ;REWRITTEN BY WARD CHRISTENSEN TO COMBINE
- ;IMPROVEMENTS TO THE ORIGINAL MADE BY WARD
- ;AND BY KEITH PETERSEN, W8SDZ, AND SUGGESTIONS
- ;BY JIM BELL WHICH KEITH IMPLEMENTED. SEE
- ;MODEM.DOC FOR ADDITIONAL HISTORICAL
- ;INFORMATION AND DOCUMENTATION.
- ;
- ; 05/09/79
- ;ALLOW 'T' AND 'E' SUB-OPTIONS TO GO TO TERMINAL
- ;OR ECHO MODEM AFTER TRANSFERRING A FILE. (WLC)
- ;
- ; 05/22/79
- ;ADD FEATURE TO MAKE RECEIVE FILE ROUTINE SAY
- ;FILE SUCCESSFULLY OPENED, WHEN IN QUIET MODE.
- ;MOVE INITIAL GOBBLE GARBAGE INPUTS TO BEFORE
- ;COMMAND CPI'S SO ALL MODES ARE CLEARED. CHANGE
- ;INITIAL SEND WAIT TO 80 SECS TO ALLOW MORE TIME
- ;FOR RECEIVING END TO COME UP. ADD 'H' AFTER MSG
- ;THAT SHOWS NUMBER OF SECTORS IN EXTENT ABOUT TO
- ;BE SENT. (KBP)
- ;
- ; 05/24/79
- ;FIX MISSING RETURN INSTRUCTION AT END OF
- ;INITIALIZATION ROUTINE. (KBP)
- ;
- ; 07/01/79
- ;MODIFIED PROGRAM TO ALLOW FOR NON-STANDARD VERSIONS OF
- ;CP/M. ALL REFERENCES TO ENTRIES INTO CP/M SHOULD BE MADE
- ;RELATIVE TO THE VARIABLE SYMBOL CALL "BASE". FOR EXAMPLE,
- ;THE EQUATE TO BDOS SHOULD BE BASE+5 INSTEAD OF 5. BASE
- ;WILL BE SET TO 0 WHEN THE VARIABLE STDCPM IS SET TO TRUE.
- ;(BOB MATHIAS).
- ;
- ; 07/24/79
- ;MOVE INITIALIZE LOCAL STACK TO BEGINNING OF PROGRAM
- ;SO DEFAULT STACK IS NOT USED. ADD CONDITIONAL ASSEMBLY
- ;OPTION TO TERMINAL ROUTINE FOR TIMESHARE SYSTEMS.
- ;CORRECT ERROR IN LOCAL ABORT ROUTINE (WAS LOOKING FOR
- ;CONTROL E - NOW CORRECTLY LOOKS FOR CONTROL X). ADD
- ;REGISTER SAVES TO CONOUT, KEYIN AND AND KEYBOARD STATUS
- ;ROUTINES, AS SOME CBIOS ROUTINES CLOBBER THEM. (KBP)
- ;
- ; 08/05/79
- ;ADDED D. C. HAYES MODEM SUPPORT BY JIM BELL (KBP)
- ;
- ; 08/06/79
- ;ADDED EQUATES FOR EXTERNAL MODEM (NOT S-100 PLUG-IN)
- ;(KBP)
- ;
- STDCPM EQU 1 ;TRUE, IS STANDARD CP/M
- H8CPM EQU 0 ;TRUE, IS HEATH H8 CP/M
- ;
- IF STDCPM
- BASE EQU 0 ;CP/M BASE ADDRESS
- ENDIF
- ;
- IF H8CPM
- BASE EQU 4200H ;CP/M BASE ADDRESS FOR HEATH H8
- ENDIF
- ;
- PMMI EQU 1 ;TRUE, IS PMMI
- ;
- DCH EQU 0 ;TRUE, IS D.C. HAYES
- ;
- IF STDCPM AND PMMI
- MODCTLP EQU 0C0H ;PMMI VALUES
- MODSNDB EQU 1 ;BIT TO TEST FOR SEND
- MODSNDR EQU 1 ;VALUE WHEN READY
- MODRCVB EQU 2 ;BIT TO TEST FOR RECEIVE
- MODRCVR EQU 2 ;VALUE WHEN READY
- MODDATP EQU 0C1H ;DATA PORT
- BAUDRP EQU 0C2H ;BAUD RATE OUTPUT
- MODCTL2 EQU 0C3H ;SECOND CTL PORT
- ENDIF
- ;
- IF STDCPM AND DCH
- MODCTLP EQU 82H ;D. C. HAYES VALUES
- MODSNDB EQU 2 ;BIT TO TEST FOR SEND
- MODSNDR EQU 2 ;VALUE WHEN READY
- MODRCVB EQU 1 ;BIT TO TEST FOR RECEIVE
- MODRCVR EQU 1 ;VALUE WHEN READY
- MODDATP EQU 80H ;DATA PORT
- MODCTL2 EQU 81H ;SECOND CTL PORT
- ENDIF
- ;
- IF H8CPM
- MODCTLP EQU 05H ;H84 VALUES
- MODSNDB EQU 20H ;BIT TO TEST FOR SEND
- MODSNDR EQU 20H ;VALUE WHEN READY
- MODRCVB EQU 01H ;BIT TO TEST FOR RECEIVE
- MODRCVR EQU 01H ;VALUE WHEN READY
- MODDATP EQU 00H ;DATA PORT
- ENDIF
- ;
- ;IF YOU ARE USING AN EXTERNAL MODEM (NOT S-100 PLUG-IN)
- ;CHANGE THESE EQUATES FOR YOUR MODEM PORT REQUIREMENTS
- ;
- INITREQ EQU 0 ;TRUE, IF MODEM PORT INIT. REQ'D
- INITC1 EQU 64H ;FIRST INIT CHAR TO CTL PORT
- INITC2 EQU 64H ;2ND INIT CHAR TO CTL PORT
- ;
- IF STDCPM AND NOT PMMI AND NOT DCH
- MODCTLP EQU 02H ;PUT YOUR MODEM CONTROL PORT HERE
- MODSNDB EQU 80H ;YOUR BIT TO TEST FOR SEND
- MODSNDR EQU 80H ;YOUR VALUE WHEN READY
- MODRCVB EQU 40H ;YOUR BIT TO TEST FOR RECEIVE
- MODRCVR EQU 40H ;YOUR VALUE WHEN READY
- MODDATP EQU 03H ;YOUR MODEM DATA PORT
- ENDIF ;END OF EXTERNAL MODEM EQUATES
- ;
- IF PMMI
- ORIGMOD EQU 1DH ;8 DATA, NO PARITY, ORIG
- ANSWMOD EQU 1EH ;8 DATA, NO PARITY, ANSW
- ENDIF
- ;
- ;NOTE: IF DC HAYES THEN BAUD RATE DEFAULTS TO
- ;300 - 1 STOP BIT. DO NOT CHANGE NEXT EQUATES
- IF DCH
- ORIGMOD EQU 86H ;OFF HOOK, 110 BAUD, CAR. ON, ORIG.
- ANSWMOD EQU 82H ;OFF HOOK, 110 BAUD, CAR. ON, ANSW.
- ENDIF
- ;
- ERRLIM EQU 10 ;MAX ALLOWABLE ERRORS
- EXITCHR EQU 'E'-40H ;CTL-E EXIT FROM T OR C
- DISCCHR EQU 'D'-40H ;CTL-D DISCONNECTS MODEM T/C
- ;
- FASTCLK EQU 0 ;PUT 1 HERE FOR 4 MHZ CLOCK
- ;
- ;SOME TIME-SHARE COMPUTERS REQUIRE TERMINALS TO
- ;HAVE BIT 7 HIGH (MARKING), SO IN THE TERMINAL
- ;MODE WE FORCE IT TO HIGH IF THE FOLLOWING OPTION
- ;IS SELECTED:
- ;
- TIMESHR EQU 0 ;PUT 1 HERE TO MAKE BIT 7 HIGH
- ;
- ;DEFINE ASCII CHARACTERS USED
- ;
- SOH EQU 1 ;START OF HEADER
- EOT EQU 4 ;END OF TRANSMISSION
- ACK EQU 6 ;ACKNOWLEDGE
- NAK EQU 15H ;NEG ACKNOWLEDGE
- CAN EQU 18H ;CANCEL
- LF EQU 10 ;LINEFEED
- CR EQU 13 ;CARRIAGE RETURN
- ;
- ORG BASE+100H
- ;
- ;INIT PRIVATE STACK
- LXI H,0 ;HL=0
- DAD SP ;HL=STACK FROM CP/M
- SHLD STACK ;..SAVE IT
- LXI SP,STACK ;SP=MY STACK
- CALL START ;GO PRINT ID
- DB 'MODEM PROGRAM as of '
- DB '08/06/79',CR,LF,'$'
- ;
- START POP D ;GET ID MESSAGE
- MVI C,PRINT
- CALL BDOS ;PRINT ID MESSAGE
- ;
- ;INITIALIZE THE JMPS TO CP/M BIOS
- ;
- CALL INITADR
- ;
- ;SAVE PRIMARY OPTION, VALIDATE SECONDARY OPT.
- ;
- CALL PROCOPT
- ;
- ;INIT THE MODEM OR SERIAL PORT
- ;
- CALL INITMOD
- ;
- ;MOVE THE FILENAME FROM FCB 2 TO FCB 1
- ;
- CALL MOVEFCB
- ;
- ;GOBBLE UP GARBAGE CHARS FROM THE LINE
- ;PRIOR TO RECEIVE OR SEND
- ;
- IN MODDATP
- IN MODDATP
- ;
- ;JMP TO APPROPRIATE FUNCTION
- ;
- LDA OPTION ;GET PRIMARY OPTION
- ;
- CPI 'C' ;(COMPAT W/EARLIER
- JZ TRMECHO ;OPTION "COMPUTER")
- ;
- CPI 'E' ;TERMINAL IN ECHO
- JZ TRMECHO ;..MODE?
- ;
- CPI 'T' ;TERMINAL..
- JZ TERM ;..MODE?
- ;
- CPI 'D'
- JZ DISCONN
- ;
- CPI 'X'
- JZ EXAM ;GIVE EXAMPLES
- ;
- CPI 'S' ;SEND..
- JZ SENDFIL ;..A FILE?
- ;
- CPI 'R' ;RECEIVE..
- JZ RCVFIL ;..A FILE?
- ;
- ;INVALID OPTION
- ;
- JMP BADOPT
- * * * * * * * * * * * * * * * * * * * * *
- * *
- * TERM: TERMINAL MODE *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;THIS PROGRAM SIMPLY SENDS KEYED CHARACTERS
- ;DOWN THE LINE, AND DISPLAYS CHARACTERS
- ;RECEIVED FROM THE LINE. THIS MAKES IT
- ;SUITABLE FOR COMMUNICATION WITH TIME SHARING
- ;COMPUTERS, CBBS'S, OR ANOTHER PROGRAM
- ;RUNING "MODEM E" (ECHO MODE)
- ;
- ;TYPE THE "EXITCHR" (ORIGINALLY CTL-E) TO EXIT.
- ;OR THE "DISCCHR" (ORIGINALLY CTL-D) TO DISCONN.
- ;
- ;A FUTURE ENHANCEMENT WILL BE TO WRITE THE
- ;RECEIVED DATA IN MEMORY, AND ALLOW IT TO
- ;BE WRITTEN TO DISK
- ;
- TERM CALL STAT ;LOCAL CHAR KEYED?
- JZ TERML ;..NO, CHECK LINE
- CALL KEYIN ;GET CHAR
- CPI EXITCHR ;TIME TO END?
- JZ CKDIS ;YES, CK DISCONN
- CPI DISCCHR ;DISCONNECT REQUEST?
- JZ DISCONN ;YES, DO IT
- IF TIMESHR
- ORI 80H ;FORCE BIT 7 TO HIGH
- ENDIF ;TIMESHR
- OUT MODDATP ;SEND THE CHAR
- ;
- ;SEE IF CHAR FROM LINE
- ;
- IF NOT DCH
- TERML IN MODCTLP ;READ STATUS
- ENDIF
- IF DCH
- TERML IN MODCTL2 ;READ STATUS
- ENDIF
- ANI MODRCVB ;ISOLATE BIT
- CPI MODRCVR ;READY?
- JNZ TERM ;..NO, LOOP
- IN MODDATP ;READ DATA
- CALL TYPE ;TYPE IT
- JMP TERM ;LOOP
- ;
- * * * * * * * * * * * * * * * * * * * * *
- * *
- * TRMECHO: TERMINAL WITH ECHO *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;TERMINAL PROGRAM WITH ECHO - SEE NOTES
- ;UNDER "TERM" ABOVE
- ;
- ;C A U T I O N DON'T RUN WITH BOTH COMPUTERS
- ;IN "ECHO" MODE - LINE ERRORS (OR ANY CHAR)
- ;WILL BE ECHOED BACK AND FORTH AD INFINITUM.
- ;
- IF NOT DCH
- TRMECHO IN MODCTLP ;GET STATUS
- ENDIF
- IF DCH
- TRMECHO IN MODCTL2 ;GET STATUS
- ENDIF
- ANI MODRCVB ;ISOLATE READY BIT
- CPI MODRCVR ;ARE WE READY?
- JZ LINECHR ;YES, READ THE CHR
- CALL STAT ;CHECK LOCAL KB
- JZ TRMECHO ;..NO CHAR
- CALL KEYIN ;GET LOCAL CHAR
- CPI EXITCHR ;END?
- JZ CKDIS ;YES, CK DISCONN, EXIT
- CPI DISCCHR ;DISCONN?
- JZ DISCONN ;..YES, DO IT.
- OUT MODDATP ;SEND CHAR
- CALL TYPE ;ECHO IT LOCALLY
- JMP TRMECHO ;..AND LOOP
- ;
- ;GOT CHAR FROM LINE
- ;
- LINECHR IN MODDATP ;GET CHAR
- OUT MODDATP ;ECHO IT
- CALL TYPE ;TYPE IT
- JMP TRMECHO ;LOOP
- ;
- * * * * * * * * * * * * * * * * * * * * *
- * *
- * SENDFIL: SENDS A CP/M FILE *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;THE CP/M FILE SPECIFIED IN THE MODEM COMMAND
- ;IS TRANSFERRED OVER THE PHONE TO ANOTHER
- ;COMPUTER RUNNING MODEM WITH THE "R" (RECEIVE)
- ;OPTION. THE DATA IS SENT ONE SECTOR AT A
- ;TIME WITH HEADERS AND CHECKSUMS, AND RE-
- ;TRANSMISSION ON ERRORS.
- ;
- SENDFIL CALL OPENFIL ;OPEN THE FILE
- MVI E,80 ;WAIT 80 SEC..
- CALL WAITNAK ;..FOR INITIAL NAK
- SENDLP CALL RDSECT ;READ A SECTOR
- JC SENDEOF ;SEND EOF IF DONE
- CALL INCRSNO ;BUMP SECTOR #
- XRA A ;ZERO ERROR..
- STA ERRCT ;..COUNT
- SENDRPT CALL SENDHDR ;SEND A HEADER
- CALL SENDSEC ;SEND DATA SECTOR
- CALL SENDCKS ;SEND CKSUM
- CALL GETACK ;GET THE ACK
- JC SENDRPT ;REPEAT IF NO ACK
- JMP SENDLP ;LOOP UNTIL EOF
- ;
- ;FILE SENT, SEND EOT'S
- ;
- SENDEOF MVI A,EOT ;SEND..
- CALL SEND ;..AN EOT
- CALL GETACK ;GET THE ACK
- JC SENDEOF ;LOOP IF NO ACK
- JMP DONE ;ALL DONE
- ;
- * * * * * * * * * * * * * * * * * * * * *
- * *
- * RCVFIL: RECEIVE A FILE *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;RECEIVES A FILE IN BLOCK FORMAT AS SENT
- ;BY ANOTHER PERSON DOING "MODEM S FN.FT".
- ;
- RCVFIL CALL ERASFIL ;ERASE THE FILE
- CALL MAKEFIL ;..THEN MAKE NEW
- LDA QFLG ;SEE IF IN QUIET MODE
- ORA A
- JNZ RCVLP ;NOT IN QUIET MODE, SKIP MSG
- CALL ILPRT ;PRINT:
- DB 'FILE OPEN, READY TO RECEIVE',CR,LF,0
- RCVLP CALL RCVSECT ;GET A SECTOR
- JC RCVEOT ;GOT EOT
- CALL WRSECT ;WRITE THE SECTOR
- CALL INCRSNO ;BUMP SECTOR #
- CALL SENDACK ;ACK THE SECTOR
- JMP RCVLP ;LOOP UNTIL EOF
- ;
- ;GOT EOT ON SECTOR - FLUSH BUFFERS, END
- ;
- RCVEOT CALL WRBLOCK ;WRITE THE LAST BLOCK
- CALL SENDACK ;ACK THE SECTOR
- CALL CLOSFIL ;CLOSE THE FILE
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ CKDIS ;YES, CK DISCONN, END.
- JMP DONE ;DISCONN IF REQ'D
- ;
- * * * * * * * * * * * * * * * * * * * * *
- * *
- * SUBROUTINES *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;
- ;----> RCVSECT: RECEIVE A SECTOR
- ;
- ;RETURNS WITH CARRY SET IF EOT RECEIVED.
- ;
- RCVSECT XRA A ;GET 0
- STA ERRCT ;INIT ERROR COUNT
- RCVRPT LDA QFLG ;QUIET?
- ORA A
- JZ RCVSQ ;YES, NO STAT MSG.
- CALL ILPRT ;PRINT:
- DB 'AWAITING #',0
- LDA SECTNO ;GET SECTOR #
- INR A ;(REAL INR LATER)
- CALL HEXO ;PRINT IN HEX
- CALL CRLF ;..THEN CRLF
- ;
- RCVSQ MVI B,10 ;10 SEC TIMEOUT
- CALL RECV ;GET SOH/EOT
- JC RCVSTOT ;TIMEOUT
- CPI SOH ;GET SOH?
- JZ RCVSOH ;..YES
- ;
- ;EARLIER VERS. OF MODEM PROG SENT SOME NULLS -
- ;IGNORE THEM
- ;
- ORA A ;00 FROM SPEED CHECK?
- JZ RCVSQ ;YES, IGNORE IT
- CPI EOT ;END OF TRANSFER?
- STC ;RETURN WITH CARRY..
- RZ ;..SET IF EOT
- ;
- ;DIDN'T GET SOH OR EOT -
- ;
- MOV B,A ;SAVE CHAR
- LDA VSEEFLG ;VIEWING..
- ORA A ;..MODE?
- JZ RCVSEH ;YES, PRT.MSG
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ RCVSERR ;YES, SKIP MSG
- RCVSEH MOV A,B ;GET CHAR
- CALL HEXO ;SHOW IN HEX
- CALL ILPRT ;PRINT:
- DB 'H RCD, NOT SOH',CR,LF,0
- ;
- ;DIDN'T GET VALID HEADER - PURGE THE LINE,
- ;THEN SEND NAK.
- ;
- RCVSERR MVI B,1 ;WAIT FOR 1 SEC..
- CALL RECV ;..WITH NO CHARS
- JNC RCVSERR ;LOOP UNTIL SENDER DONE
- MVI A,NAK ;SEND..
- CALL SEND ;..THE NAK
- LDA ERRCT ;ABORT IF..
- INR A ;..WE HAVE REACHED..
- STA ERRCT ;..THE ERROR..
- CPI ERRLIM ;..LIMIT?
- JC RCVRPT ;..NO, TRY AGAIN
- ;
- ;10 ERRORS IN A ROW -
- ;
- LDA VSEEFLG ;VIEWING..
- ORA A ;..FILE?
- JZ RCVCKQ ;YES, ASK RETRY/QUIT
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ RCVSABT ;ABORT
- RCVCKQ CALL CKQUIT ;RETRY/QUIT?
- JZ RCVSECT ;TRY AGAIN
- ;
- RCVSABT CALL CLOSFIL ;KEEP WHATEVER WE GOT
- CALL ERXIT
- DB '++UNABLE TO RECEIVE BLOCK'
- DB CR,LF,'++ABORTING++$'
- ;
- ;TIMEDOUT ON RECEIVE
- ;
- RCVSTOT LDA VSEEFLG ;VIEWING..
- ORA A ;..MODE?
- JZ RCVSPT ;YES, PRT MSG
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ RCVSERR ;YES, NO MSG
- RCVSPT CALL ILPRT
- DB '++TIMEOUT++ ',0
- RCVPRN LDA ERRCT ;PRINT ERROR..
- CALL HEXO ;..COUNT
- CALL CRLF
- JMP RCVSERR ;BUMP ERR CT, ETC.
- ;
- ;GOT SOH - GET BLOCK #, BLOCK # COMPLEMENTED
- ;
- RCVSOH MVI B,1 ;TIMEOUT = 1 SEC
- CALL RECV ;GET SECTOR
- JC RCVSTOT ;GOT TIMEOUT
- MOV D,A ;D=BLK #
- MVI B,1 ;TIMEOUT = 1 SEC
- CALL RECV ;GET CMA'D SECT #
- JC RCVSTOT ;TIMEOUT
- CMA ;CALC COMPLEMENT
- CMP D ;GOOD SECTOR #?
- JZ RCVDATA ;YES, GET DATA
- ;
- ;GOT BAD SECTOR #
- ;
- LDA VSEEFLG ;VIEWING..
- ORA A ;..MODE?
- JZ RCVBSE ;..YES, PRT MSG
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ RCVSERR ;..YES, NO MSG
- ;
- RCVBSE CALL ILPRT ;PRINT:
- DB '++BAD SECTOR # IN HDR',CR,LF,0
- JMP RCVSERR ;BUMP ERROR CT.
- ;
- RCVDATA MOV A,D ;GET SECTOR #
- STA RCVSNO ;SAVE IT
- MVI A,1 ;SHOW..
- STA DATAFLG ;GETTING DATA
- MVI C,0 ;INIT CKSUM
- LXI H,BASE+80H ;POINT TO BUFFER
- RCVCHR MVI B,1 ;1 SEC TIMEOUT
- CALL RECV ;GET CHAR
- JC RCVSTOT ;TIMEOUT
- MOV M,A ;STORE CHAR
- INR L ;DONE?
- JNZ RCVCHR ;NO, LOOP
- ;
- ;VERIFY CHECKSUM
- ;
- MOV D,C ;SAVE CHECKSUM
- XRA A ;SHOW..
- STA DATAFLG ;..END OF DATA
- MVI B,1 ;TIMEOUT LEN.
- CALL RECV ;GET CHECKSUM
- JC RCVSTOT ;TIMEOUT
- CMP D ;CHECKSUM OK?
- JNZ RCVCERR ;NO, ERROR
- ;
- ;GOT A SECTOR, IT'S A DUP IF = PREV,
- ; OR OK IF = 1 + PREV SECTOR
- ;
- LDA RCVSNO ;GET RECEIVED
- MOV B,A ;SAVE IT
- LDA SECTNO ;GET PREV
- CMP B ;PREV REPEATED?
- JZ RECVACK ;ACK TO CATCH UP
- INR A ;CALC NEXT SECTOR #
- CMP B ;MATCH?
- JNZ ABORT ;NO MATCH - STOP SENDER, EXIT
- RET ;CARRY OFF - NO ERRORS
- ;
- ;GOT CKSUM
- ;
- RCVCERR LDA VSEEFLG ;VIEWING..
- ORA A ;..MODE?
- JZ RCVCPR ;..YES, PRT MSG
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ RCVSERR ;YES, NO MSG
- RCVCPR CALL ILPRT
- DB '++CKSUM++ ',0
- JMP RCVPRN ;PRINT ERROR #
- ;
- ;PREV SECT REPEATED, DUE TO THE LAST ACK
- ;BEING GARBAGED. ACK IT SO SENDER WILL CATCH UP
- ;
- RECVACK CALL SENDACK ;SEND THE ACK,
- JMP RCVSECT ;GET NEXT BLOCK
- ;
- ;SEND AN ACK FOR THE SECTOR
- ;
- SENDACK MVI A,ACK ;GET ACK
- CALL SEND ;..AND SEND IT
- RET
- ;
- ;----> SENDHDR: SEND THE SECTOR HEADER
- ;
- ;SEND: (SOH) (BLOCK #) (COMPLEMENTED BLOCK #)
- ;
- SENDHDR LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ SENDHNM ;YES, SKIP STATUS MSG.
- CALL ILPRT ;PRINT:
- DB 'SEND # ',0
- LDA SECTNO ;PRINT..
- CALL HEXO ;..SECT #
- CALL CRLF ;..THEN CR/LF
- ;
- SENDHNM MVI A,SOH ;SEND..
- CALL SEND ;..SOH,
- LDA SECTNO ;THEN SEND..
- CALL SEND ;..SECTOR #
- LDA SECTNO ;THEN SECTOR #
- CMA ;..COMPLEMENTED..
- CALL SEND ;..SECTOR #
- RET ;FROM SENDHDR
- ;
- ;----> SENDSEC: SEND THE DATA SECTOR
- ;
- ;WHILE SENDING THE SECTOR, THE "DATAFLG" IS SET
- ;SUCH THAT IF "V" (VIEW THE FILE) WAS REQUESTED,
- ;THE "SHOW" ROUTINE WILL PRINT THE DATA, BUT NOT
- ;THE HDR OR CKSUM, OR ANY NON-FATAL MSGS.
- ;
- SENDSEC MVI A,1 ;SHOW NOW AT DATA..
- STA DATAFLG ;..FOR VIEW COMMAND
- MVI C,0 ;INIT CKSUM
- LXI H,BASE+80H ;POINT TO BUFFER
- SENDC MOV A,M ;GET A CHAR
- CALL SEND ;SEND IT
- INR L ;POINT TO NEXT CHAR
- JNZ SENDC ;LOOP IF <100H
- XRA A ;SHOW NOT INTO DATA..
- STA DATAFLG ;..FOR VIEW COMMAND
- RET ;FROM SENDSEC
- ;
- ;----> SENDCKS: SEND THE CHECKSUM
- ;
- SENDCKS MOV A,C ;SEND THE..
- CALL SEND ;..CHECKSUM
- RET ;FROM SENDCKS
- ;
- ;----> GETACK: GET THE ACK ON THE SECTOR
- ;
- ;RETURNS WITH CARRY CLEAR IF ACK RECEIVED.
- ;IF AN ACK IS NOT RECEIVED, THE ERROR COUNT
- ;IS INCREMENTED, AND IF LESS THAN "ERRLIM",
- ;CARRY IS SET AND CONTROL RETURNS. IF THE
- ;ERROR COUNT IS AT "ERRLIM", THE PROGRAM
- ;ABORTS IF IN "QUIET" MODE, OR ASKS THE
- ;USER FOR QUIT/RETRY IF NOT.
- ;
- GETACK MVI B,10 ;WAIT 10 SECONDS MAX
- CALL RECVDG ;RECV W/GARBAGE COLLECT
- JC GETATOT ;TIMED OUT
- CPI ACK ;OK? (CARRY OFF IF =)
- RZ ;YES, RET FROM GETACK
- MOV B,A ;SAVE CHAR
- ANI 7FH ;STRIP PARITY BIT
- CPI CAN ;CANCEL TRANSMISSION?
- JZ ABORT ;..YES
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ ACKERR ;..YES, NO MSG
- MOV A,B ;GET CHAR
- CALL HEXO ;PRINT IN HEX
- CALL ILPRT ;PRINT:
- DB 'H RCD, NOT ACK',CR,LF,0
- ;
- ;TIMEOUT OR ERROR ON ACK - BUMP ERROR COUNT
- ;
- ACKERR LDA ERRCT ;GET COUNT
- INR A ;BUMP IT
- STA ERRCT ;SAVE BACK
- CPI ERRLIM ;AT LIMIT?
- RC ;NOT AT LIMIT
- ;
- ;REACHED ERROR LIMIT
- ;
- LDA VSEEFLG ;VIEWING..
- ORA A ;..FILE?
- JZ GACKV ;YES, ASK QUIT/RETRY
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ CSABORT ;..YES, NO MSG
- GACKV CALL CKQUIT ;SEE IF WANT TO QUIT
- STC ;TO SHOW NO ACK
- RZ ;KEEP ON TRYIN'
- CSABORT CALL ERXIT
- DB 'CAN''T SEND SECTOR '
- DB '- ABORTING',CR,LF,'$'
- ;
- ;TIMEOUT GETTING ACK
- ;
- GETATOT LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ ACKERR ;YES, NO MSG
- CALL ILPRT ;PRINT:
- DB 'TIMEOUT ON ACK',CR,LF,0
- JMP ACKERR
- ;
- ;----> CKABORT: CHECK FOR LOCAL ABORT
- ;
- ;IF THE USER WANTS TO CANCEL THE TRANSMISSION,
- ;TYPING CTL-X WILL ABORT IT. NOTE THIS TEST
- ;IS NOT MADE IF IN QUIET (NO CONSOLE I/O) MODE.
- ;
- CKABORT LDA VSEEFLG ;VIEWING?
- ORA A
- JZ CKABGO ;YES, CHECK
- LDA QFLG ;SUPPRESSED..
- ORA A ;..CONSOLE I/O?
- RZ ;YES, NO TEST
- CKABGO CALL STAT ;KEY PRESSED?
- RZ ;NOTHING FROM KEYBOARD
- CALL KEYIN ;GET DATA
- CPI CAN ;TIME TO END?
- RNZ ;NO, CONTINUE
- ;
- ABORT LXI SP,STACK
- ABORTL MVI B,1 ;1 SEC. W/O CHARS.
- CALL RECV
- JNC ABORTL ;LOOP UNTIL SENDER DONE
- MVI A,CAN ;CONTROL X
- CALL SEND ;STOP SENDING END
- ABORTW MVI B,1 ;1 SEC W/O CHARS.
- CALL RECV
- JNC ABORTW ;LOOP UNTIL SENDER DONE
- MVI A,' ' ;GET A SPACE...
- CALL SEND ;TO CLEAR OUT CONTROL X
- CALL ILPRT ;EXIT WITH ABORT MSG
- DB 'MODEM PROGRAM CANCELLED',CR,LF,0
- JMP CKDIS ;CHECK FOR DISCONN.
- ;
- ;----> INCRSNO: INCREMENT SECTOR #
- ;
- INCRSNO LDA SECTNO ;INCR..
- INR A ;..SECT..
- STA SECTNO ;..NUMBER
- RET
- ;
- ;----> ERASFIL: ERASE THE INCOMING FILE.
- ;
- ;IF IT EXISTS, ASK IF IT MAY BE ERASED.
- ;
- ERASFIL LXI D,FCB ;POINT TO CTL BLOCK
- MVI C,SRCHF ;SEE IF IT..
- CALL BDOS ;..EXISTS
- INR A ;FOUND?
- RZ ;..NO, RETURN
- CALL ILPRT ;PRINT:
- DB '++FILE EXISTS, TYPE Y TO ERASE: ',0
- CALL KEYIN ;GET CHAR
- PUSH PSW
- CALL TYPE ;ECHO
- CALL CRLF ;BACK TO START OF LINE
- POP PSW
- ANI 5FH ;MAKE UPPER CASE
- CPI 'Y' ;WANT ERASED?
- JNZ CKDIS ;QUIT IF NOT ERASE
- ;
- ;ERASE OLD FILE
- ;
- LXI D,FCB ;POINT TO FCB
- MVI C,ERASE ;GET BDOS FNC
- CALL BDOS ;DO THE ERASE
- RET ;FROM "ERASFIL"
- ;
- ;----> MAKEFIL: MAKES THE FILE TO BE RECEIVED
- ;
- MAKEFIL LXI D,FCB ;POINT TO FCB
- MVI C,MAKE ;GET BDOS FNC
- CALL BDOS ;TO THE MAKE
- INR A ;FF=BAD?
- RNZ ;OPEN OK
- ;DIRECTORY FULL - CAN'T MAKE FILE
- CALL ERXIT
- DB '++ERROR - CAN''T MAKE FILE',CR,LF
- DB '++DIRECTORY MUST BE FULL',CR,LF,'$'
- ;
- ;----> OPENFIL: OPENS THE FILE TO BE SENT
- ;
- OPENFIL LXI D,FCB ;POINT TO FILE
- MVI C,OPEN ;GET FUNCTION
- CALL BDOS ;OPEN IT
- INR A ;OPEN OK?
- JNZ OPENOK ;..YES
- CALL ERXIT ;..NO, ABORT
- DB 'CAN''T OPEN FILE$'
- ;
- OPENOK CALL ILPRT ;PRINT:
- DB 'FILE OPEN, EXTENT LENGTH: ',0
- LDA FCB+15 ;GET # SECTORS
- CALL HEXO ;PRINT IN HEX
- MVI A,'H'
- CALL TYPE ;PRINT 'H' AFTER NUMBER
- CALL CRLF ;..THEN CRLF
- RET
- ;
- ;----> CLOSFIL: CLOSES THE RECEIVED FILE
- ;
- CLOSFIL LXI D,FCB ;POINT TO FILE
- MVI C,CLOSE ;GET FUNCTION
- CALL BDOS ;CLOSE IT
- INR A ;CLOSE OK?
- RNZ ;..YES, RETURN
- CALL ERXIT ;..NO, ABORT
- DB 'CAN''T CLOSE FILE$'
- ;
- ;----> RDSECT: READS A SECTOR
- ;
- ;FOR SPEED, THIS ROUTINE BUFFERS UP 16
- ;SECTORS AT A TIME.
- ;
- RDSECT LDA SECINBF ;GET # SECT IN BUFF.
- DCR A ;DECREMENT..
- STA SECINBF ;..IT
- JM RDBLOCK ;EXHAUSTED? NEED MORE.
- LHLD SECPTR ;GET POINTER
- LXI D,BASE+80H ;TO DATA
- CALL MOVE128 ;MOVE TO BUFFER
- SHLD SECPTR ;SAVE BUFFER POINTER
- RET ;FROM "READSEC"
- ;
- ;BUFFER IS EMPTY - READ IN ANOTHER BLOCK OF 16
- ;
- RDBLOCK LDA EOFLG ;GET EOF FLAG
- CPI 1 ;IS IT SET/
- STC ;TO SHOW EOF
- RZ ;GOT EOF
- MVI C,0 ;SECTORS IN BLOCK
- LXI D,DBUF ;TO DISK BUFFER
- RDSECLP PUSH B
- PUSH D
- MVI C,STDMA ;SET DMA..
- CALL BDOS ;..ADDR
- LXI D,FCB
- MVI C,READ
- CALL BDOS
- POP D
- POP B
- ORA A ;READ OK?
- JZ RDSECOK ;YES
- DCR A ;EOF?
- JZ REOF ;GOT EOF
- ;
- ;READ ERROR
- ;
- CALL ERXIT
- DB '++FILE READ ERROR$'
- ;
- RDSECOK LXI H,80H ;ADD LENGTH OF ONE SECTOR...
- DAD D ;...TO NEXT BUFF
- XCHG ;BUFF TO DE
- INR C ;MORE SECTORS?
- MOV A,C ;GET COUNT
- CPI 16 ;DONE?
- JZ RDBFULL ;..YES, BUFF IS FULL
- JMP RDSECLP ;READ MORE
- ;
- REOF MVI A,1
- STA EOFLG ;SET EOF FLAG
- MOV A,C
- ;
- ;BUFFER IS FULL, OR GOT EOF
- ;
- RDBFULL STA SECINBF ;STORE SECTOR COUNT
- LXI H,DBUF ;INIT BUFFER..
- SHLD SECPTR ;..POINTER
- LXI D,BASE+80H ;RESET..
- MVI C,STDMA ;..DMA..
- CALL BDOS ;..ADDR
- JMP RDSECT ;PASS SECT TO CALLER
- ;
- ;----> WRSECT: WRITE A SECTOR
- ;
- ;WRITES THE SECTOR INTO A BUFFER. WHEN 16
- ;HAVE BEEN WRITTEN, WRITES THE BLOCK TO DISK.
- ;
- ;ENTRY POINT "WRBLOCK" FLUSHES THE BUFFER AT EOF.
- ;
- WRSECT LHLD SECPTR ;GET BUFF ADDR
- XCHG ;TO DE FOR MOVE
- LXI H,BASE+80H ;FROM HERE
- CALL MOVE128 ;MOVE TO BUFFER
- XCHG ;SAVE NEXT..
- SHLD SECPTR ;..BLOCK POINTER
- LDA SECINBF ;BUMP THE..
- INR A ;..SECTOR #..
- STA SECINBF ;..IN THE BUFF
- CPI 16 ;HAVE WE 16?
- RNZ ;NO, RETURN
- ;
- ;----> WRBLOCK: WRITES A BLOCK TO DISK
- ;
- WRBLOCK LDA SECINBF ;# SECT IN BUFFER
- ORA A ;0 MEANS END OF FILE
- RZ ;NONE TO WRITE
- MOV C,A ;SAVE COUNT
- LXI D,DBUF ;POINT TO DISK BUFF
- DKWRLP PUSH H
- PUSH D
- PUSH B
- MVI C,STDMA ;SET DMA
- CALL BDOS ;TO BUFFER
- LXI D,FCB ;THEN WRITE
- MVI C,WRITE ;..THE..
- CALL BDOS ;..BLOCK
- POP B
- POP D
- POP H
- ORA A
- JNZ WRERR ;OOPS, ERROR
- LXI H,80H ;LENGTH OF 1 SECT
- DAD D ;HL= NEXT BUFF
- XCHG ;TO DE FOR SETDMA
- DCR C ;MORE SECTORS?
- JNZ DKWRLP ;..YES, LOOP
- XRA A ;GET A ZERO
- STA SECINBF ;RESET # OF SECTORS
- LXI H,DBUF ;RESET BUFFER..
- SHLD SECPTR ;..POINTER
- RSDMA LXI D,BASE+80H ;RESET..
- MVI C,STDMA ;..DMA..
- CALL BDOS ;..ADDR
- RET
- ;
- WRERR CALL RSDMA ;RESET DMA TO NORM.
- MVI C,CAN ;CANCEL..
- CALL SEND ;..SENDER
- CALL ERXIT ;EXIT W/MSG:
- DB '++ERROR WRITING FILE',CR,LF,'$'
- ;
- ;----> RECV: RECEIVE A CHARACTER
- ;
- ;TIMEOUT TIME IS IN B, IN SECONDS. ENTRY VIA
- ;"RECVDG" DELETES GARBAGE CHARACTERS ON THE
- ;LINE. FOR EXAMPLE, HAVING JUST SENT A SECTOR,
- ;CALLING RECVDG WILL DELETE ANY LINE-NOISE-INDUCED
- ;CHARACTERS "LONG" BEFORE THE ACK/NAK WOULD
- ;BE RECEIVED.
- ;
- RECVDG EQU $ ;RECEIVE W/GARBAGE DELETE
- IN MODDATP ;GET A CHAR
- IN MODDATP ;..TOTALLY PURGE UART
- ;
- RECV PUSH D ;SAVE
- ;
- IF FASTCLK ;4MHZ?
- MOV A,B ;GET TIME REQUEST
- ADD A ;DOUBLE IT
- MOV B,A ;NEW TIME IN B
- ENDIF
- ;
- MSEC LXI D,50000 ;1 SEC DCR COUNT
- CALL CKABORT ;CHECK FOR EXIT REQUEST
- IF NOT DCH
- MWTI IN MODCTLP ;CHECK STATUS
- ENDIF
- IF DCH
- MWTI IN MODCTL2 ;CHECK STATUS
- ENDIF
- ANI MODRCVB ;ISOLATE BIT
- CPI MODRCVR ;READY?
- JZ MCHAR ;GOT CHAR
- DCR E ;COUNT..
- JNZ MWTI ;..DOWN..
- DCR D ;..FOR..
- JNZ MWTI ;..TIMEOUT
- DCR B ;MORE SECONDS?
- JNZ MSEC ;YES, WAIT
- ;
- ;MODEM TIMED OUT RECEIVING
- ;
- POP D ;RESTORE D,E
- STC ;CARRY SHOWS TIMEOUT
- RET
- ;
- ;GOT CHAR FROM MODEM
- ;
- MCHAR IN MODDATP ;READ THE CHAR
- POP D ;RESTORE DE
- ;
- ;CALC CHECKSUM
- ;
- PUSH PSW ;SAVE THE CHAR
- ADD C ;ADD TO CHECKSUM
- MOV C,A ;SAVE CHECKSUM
- ;
- ;CHECK IF MONITORING REC'D DATA
- ;
- LDA RSEEFLG ;SEE RECEIVED..
- ORA A ;..DATA?
- JZ MONIN ;..YES
- ;
- ;CHECK IF "VIEWING" AND THIS IS A DATA CHAR
- ;
- LDA VSEEFLG ;VIEWING..
- ORA A ;..DATA?
- JNZ NOMONIN ;..NO
- ;
- ;"VIEW" REQUESTED. SHOW THE CHAR IT IS DATA
- ;
- LDA DATAFLG ;GET DATA FLAG
- ORA A ;TEST IT
- JZ NOMONIN ;..OFF, NOT DATA
- MONIN POP PSW ;..IS DATA,
- PUSH PSW ;GET IT,
- CALL SHOW ;..AND SHOW IT
- NOMONIN POP PSW ;RESTORE CHAR
- ORA A ;CARRY OFF: NO ERROR
- RET ;FROM "RECV"
- ;
- ;----> SEND: SEND A CHARACTER TO THE MODEM
- ;
- SEND PUSH PSW ;SAVE THE CHAR
- ;
- ;CHECK IF MONITORING SENT DATA
- ;
- LDA SSEEFLG ;CHECK IF MONITORING..
- ORA A ;..SENT DATA
- JZ MONOUT ;..YES
- ;
- ;CHECK IF "VIEWING" THE FILE
- ;
- LDA VSEEFLG ;GET VIEW FLAG
- ORA A ;TEST IT
- JNZ NOMONOT ;NO
- LDA DATAFLG ;IS THIS
- ORA A ;..DATA?
- JZ NOMONOT ;..NO.
- MONOUT POP PSW ;GET THE CHAR
- PUSH PSW ;SAVE IT
- CALL SHOW ;SHOW IT
- NOMONOT POP PSW ;RESTORE CHAR
- PUSH PSW ;SAVE IT
- ADD C ;CALC CKSUM
- MOV C,A ;SAVE CKSUM
- IF NOT DCH
- SENDW IN MODCTLP ;GET STATUS
- ENDIF
- IF DCH
- SENDW IN MODCTL2 ;GET STATUS
- ENDIF
- ANI MODSNDB ;ISOLATE READY BIT
- CPI MODSNDR ;READY?
- JNZ SENDW ;..NO, WAIT
- POP PSW ;GET CHAR
- OUT MODDATP ;OUTPUT IT
- RET ;FROM "SEND"
- ;
- ;----> WAITNAK: WAITS FOR INITIAL NAK
- ;
- ;TO ENSURE NO DATA IS SENT UNTIL THE RECEIVING
- ;PROGRAM IS READY, THIS ROUTINE WAITS FOR THE
- ;THE FIRST TIMEOUT-NAK FROM THE RECEIVER.
- ;(E) CONTAINS THE # OF SECONDS TO WAIT.
- ;
- WAITNAK LDA VSEEFLG ;VIEWING?
- ORA A
- JZ WAITNPR ;PRINT MSG
- LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ WAITNLP ;YES, SKIP MSG
- WAITNPR CALL ILPRT ;PRINT:
- DB 'AWAITING INITIAL NAK',CR,LF,0
- WAITNLP CALL CKABORT ;ABORT IF LOCAL CTL-X
- MVI B,1 ;TIMEOUT DELAY
- CALL RECV ;DID WE GET..
- CPI NAK ;..A NAK?
- RZ ;YES, SEND BLOCK
- ANI 7FH ;STRIP PARITY BIT
- CPI CAN ;CTL-X FROM REMOTE?
- JZ ABORT ;..YES, ABORT
- DCR E ;80 TRIES?
- JZ ABORT ;YES, ABORT
- JMP WAITNLP ;NO, LOOP
- ;
- ;----> INITADR: INIT'S CP/M BDOS ADDRESSES
- ;
- ;THIS ROUTINE FILLS IN THE ADDRESSES OF VARIOUS
- ;JMP AND CALL INSTRUCTIONS, SO THAT CP/M BDOS
- ;IS BYPASSED WHILE ACCESSING THE CONSOLE. THIS
- ;IS DONE TO ALLOW CHARACTERS SUCH AS CONTROL-C
- ;AND CONTROL-S TO BE KEYED WHILE IN TERMINAL
- ;MODE, WITHOUT CP/M INTERPRETING THEM.
- ;
- INITADR LHLD BASE+1 ;GET WARM BOOT ADDR
- LXI D,3 ;LENGTH OF A 'JMP'
- DAD D ;TO CONSOLE STAT
- SHLD VSTAT+1 ;MODIFY CALL
- DAD D ;TO CONSOLE IN
- SHLD VKEYIN+1 ;MODIFY CALL
- DAD D ;TO CONSOLE OUT
- SHLD VTYPE+1 ;MODIFY CALL
- RET
- ;
- ;----> PROCOPT: PROCESS COMMAND OPTIONS
- ;
- ;1) SAVES THE PRIMARY OPTION IN 'OPTION';
- ;2) IF OPTION 'H' (HELP) IS ASKED FOR,
- ;TRANSFERS DIRECTLY TO THE HELP PRINT;
- ;3) SCANS THE SUB-OPTION CHARACTERS, AND FOR
- ;EACH FOUND, ZEROS THE APPROPRIATE ENTRY IN
- ;THE OPTION TABLE. FOR EXAMPLE, IF 'D' IS
- ;CODED (DISCONNECT) THEN THE 'D' STORED AT
- ;'DISCFLG' IS SET TO 0 SO IT CAN BE TESTED
- ;LATER.
- ;
- PROCOPT LXI D,FCB+1 ;TO PRIMARY OPT.
- LDAX D ;GET PRIMARY
- STA OPTION ;SAVE IT
- CPI 'H' ;MODEM H(ELP)?
- JZ HELP ;..YES, GIVE HELP
- ;
- OPTLP INX D ;TO SECONDARY OPTION
- LDAX D ;GET CHAR
- ;
- ;IF YOU MOD THIS PROGRAM FOR >7 OPTIONS,
- ;YOU MUST CHANGE THE FOLLOWING, SINCE
- ;THERE WON'T BE A ' ' AFTER THE OPTION
- ;IF A BAUD RATE WAS SPECIFIED.
- ;
- CPI ' ' ;NO MORE OPT'NS?
- JZ ENDOPT ;..YES
- ;SET THE APPROP. OPT: STORE 0 IN IT
- LXI H,OPTBL ;HL = ADDR OF 'OAQDSRV'
- MVI B,OPTBE-OPTBL ;OPT TABLE LEN
- OPTCK CMP M ;FOUND THE OPTION?
- JNZ OPTNO ;NO, DON'T SET IT
- MVI M,0 ;SET THE OPTION
- JMP OPTLP ;GET NEXT OPTION
- OPTNO INX H ;TO NEXT
- DCR B ;MORE?
- JNZ OPTCK
- ;OPTION NOT IN TABLE
- JMP BADOPT ;SHOW BAD SUB OPTION
- ;
- ;IF "VIEW" WAS ASKED FOR, SET QUIET FLAG
- ;
- ENDOPT LDA VSEEFLG ;VIEW..
- ORA A ;..ASKED FOR?
- RNZ ;..NO, RET FROM 'PROCOPT'
- STA QFLG ;YES, NO HDR/CKSUM PRT
- RET ;FROM 'PROCOPT'
- ;
- ;DONE - CLOSE UP SHOP
- ;
- DONE LDA VSEEFLG ;VIEWING?
- ORA A
- JZ DONETC ;SHOW MSG
- LDA QFLG ;QUIET
- ORA A ;..MODE?
- JZ DONECTE ;YES, CK TERM/ECHO
- DONETC CALL ILPRT
- DB CR,LF,'TRANSFER COMPLETE'
- DB CR,LF,0
- ;
- ;CHECK IF TERMINAL OR ECHO SUB COMMAND
- ;WAS SPECIFIED
- ;
- DONECTE LDA TERMFLG ;TERM?
- ORA A
- JZ TERM ;..YES
- LDA ECHOFLG ;ECHO?
- ORA A
- JZ TRMECHO ;..YES
- ;
- ;FALL INTO 'CKDIS'
- ;
- ;----> CKDIS: CHECK IF DISCONNECT REQUESTED
- ;
- ;THIS ROUTINE IS JUMPED TO AT THE END OF
- ;PROCESSING, AND DISCONNECTS THE PHONE IF
- ;'D' WAS SPECIFIED AS A SUB-OPTION.
- ;
- CKDIS LDA DISCFLG ;CHECK 'D' FLAG
- ORA A ;REQUESTED?
- ;
- IF PMMI OR DCH
- JNZ NDIS ;..NO, JUST EXIT
- ENDIF
- ;
- IF NOT PMMI AND NOT DCH
- JNZ EXIT
- ENDIF
- ;
- ;AWAIT C/R TO DISC. SO WE DON'T LOSE THE PHONE
- ;
- CALL ILPRT
- DB CR,LF,'PRESS RETURN TO DISCONNECT:',0
- CALL KEYIN
- PUSH PSW
- CALL CRLF
- POP PSW
- CPI CR
- JNZ CKDIS ;ASK AGAIN
- ;
- ;----> DISCONN: DISCONNECT THE PHONE
- ;
- DISCONN EQU $
- ;
- IF PMMI
- XRA A ;GET DISCONN VALUE
- OUT MODCTLP ;RESET ORIG/ANSW
- OUT MODCTL2 ;TURN OFF DTR, DO BREAK
- ENDIF
- ;
- IF DCH
- XRA A ;GET DISCONNECT VALUE
- OUT MODCTLP ;DISCONNECT
- ENDIF
- ;
- CALL ILPRT ;PRINT:
- DB '++DISCONNECTED++',0
- JMP EXIT
- ;
- ;NO DISCONNECT, TYPE MSG AS REMINDER THAT PHONE'S
- ;OFF HOOK
- ;
- IF PMMI OR DCH
- NDIS LDA QFLG ;QUIET..
- ORA A ;..MODE?
- JZ EXIT ;..YES, NO MSG
- CALL ILPRT
- DB CR,LF,'++DON''T FORGET - THE MODEM IS '
- DB 'NOT DISCONNECTED++',CR,LF
- DB 'USE "MODEM D" TO DISCONNECT',CR,LF,0
- JMP EXIT
- ;
- ENDIF
- ;
- ;----> INITMOD: INITIALIZES THE MODEM
- ;
- ;THIS ROUTINE IS USED TO INITIALIZE SERIAL
- ;BOARDS, OR SETUP S-100 MODEM BOARDS.
- ;JUST RETURNS IF NO INITIALIZATION REQUIRED.
- ;
- INITMOD:
- ;
- IF INITREQ ;REQUIRE INIT?
- MVI A,INITC1 ;GET 1ST INIT CHAR
- OUT MODCTLP ;OUTPUT IT
- MVI A,INITC2 ;GET 2ND INIT CHAR
- OUT MODCTLP ;OUTPUT IT
- ENDIF
- ;
- IF PMMI
- CALL GETBAUD ;GET THE BAUD RATE
- OUT BAUDRP ;OUT BAUD RATE PORT
- ENDIF
- ;
- IF DCH
- CALL GETBAUD ;GET BAUD RATE
- ENDIF
- IF PMMI
- ;SET THE MOTOROLA MODEM CHIP BIT FOR >300 IF REQ'D
- ;
- CPI 52 ;>300?
- MVI A,5FH ;VALUE FOR >300
- JC GT300
- MVI A,7FH ;VALUE FOR <= 300
- GT300 OUT MODCTL2 ;SET IT
- ;
- ;SET ORIG/ANSW IF REQUESTED
- ;
- LDA ORIGFLG ;ORIGINATE..
- ORA A ;..MODE?
- MVI A,ORIGMOD
- JZ OFFHOOK ;..YES, DO IT
- LDA ANSWFLG ;ANSWER..
- ORA A ;..MODE?
- MVI A,ANSWMOD
- RNZ ;NEITHER ORIG NOR ANSW.
- ENDIF
- ;
- IF DCH
- LDA ANSWFLG ;ANSWER..
- ORA A
- MVI B,ANSWMOD ;SET ANSWER MODE
- JZ INITM1
- LDA ORIGFLG ;GET ORIGINATE FLAG
- ORA A
- MVI B,ORIGMOD ;SET ORIGINATE MODE
- JZ INITM1
- LDA HOLDD ;NEITHER - GET LAST VALUE
- MOV B,A ;STORE IN B
- INITM1: MOV A,B ;GET MODE
- STA HOLDD ;SAVE VALUE
- MOV A,C ;GET BAUD RATE INDICATOR
- ORA A ;ZEBO IF 110 BAUD
- MOV A,B ;GET MODE
- JZ OFFHOOK ;DO OFFHOOK
- ORI 1 ;SET 300 BAUD
- ENDIF
- ;
- IF PMMI OR DCH
- ;
- ;GO OFFHOOK IN REQUESTED (ORIG/ANSW) MODE
- ;
- OFFHOOK LXI H,4000 ;DELAY AMT
- OFFDLY DCR L
- JNZ OFFDLY
- DCR H
- JNZ OFFDLY
- OUT MODCTLP ;GO OFF HOOK
- RET
- ENDIF
- ;
- IF PMMI
- ;----> GETBAUD: GETS BAUD RATE FROM COMMAND
- ;
- ;THIS ROUTINE CHECKS IF A BAUD RATE HAS
- ;BEEN ASKED FOR, (SUCH AS MODEM T.450),
- ;AND IF SO, CALCULATES THE PMMI BAUD RATE
- ;VALUE TO BE OUTPUT. DEFAULTS TO 300.
- ;
- GETBAUD LDA FCB+9 ;GET 'FILETYPE'
- CPI ' ' ;DEFAULT?
- MVI A,52 ;300 BAUD VALUE
- RZ ;NO BAUD RATE, USE 300
- ;
- ;GOT BAUD RATE - CONVERT TO PROPER TIMER VALUE
- ;
- ;FIRST, CONVERT THE NUMBER TO BINARY
- ;
- CALL CVBIN
- ;
- ;CALCULATE THE VALUE TO OUTPUT:
- ;
- ; RATE = 250000/16/BAUD RATE
- ;
- ; DIVIDE BY REPETITIVE SUBTRACTION
- ; ------
- ;COMPLEMENT THE BAUD RATE
- ;
- MOV A,H ;GET HI
- CMA ;COMPLEMENT
- MOV D,A ;SAVE
- MOV A,L ;GET LO
- CMA ;COMPLEMENT
- MOV E,A ;SAVE
- INX D ;DE=2'S COMPLEMENT
- ;DIVIDE
- LXI H,15625 ;250000/16
- LXI B,-1 ;INIT QUOTIENT
- DIVLP INX B ;BUMP QUOTIENT
- DAD D ;'SUBTRACT'
- JC DIVLP ;LOOP 'TILL DONE
- ;VALIDATE THE RESULT
- MOV A,B ;CAN'T HAVE >255
- ORA A
- MOV A,C ;GET ACTUAL
- RZ ;RET IF <256
- JMP BADRATE ;INVALID
- ENDIF ;PMMI
- ;
- IF DCH
- GETBAUD LDA FCB+9 ;GET FILETYPE
- CPI ' ' ;DEFAULT?
- JNZ GETBAU1 ;NO - DO BAUD RATE STUFF
- MVI C,1 ;SET 300 BAUD
- MVI B,17H ;SET 1 STOP BIT
- JMP GETBAU2
- ; CONVERT BAUD RATE TO BINARY
- GETBAU1 CALL CVBIN ;CONVERT TO BINARY
- PUSH H ;SAVE BAUD RATE
- MVI C,0 ;ANTICIPATE 110 BAUD
- MVI B,1FH ;SET 2 STOP BITS
- LXI D,-110 ;GET CONSTANT
- DAD D ;SUBTRACT
- MOV A,H
- ORA L
- POP H
- JZ GETBAU2 ;110 BAUD
- MVI B,17H ;SET 1 STOP BIT
- INR C
- LXI D,-300 ;GET CONSTANT
- DAD D
- MOV A,H
- ORA L
- JNZ BADRATE ;INVALID
- GETBAU2 MOV A,B ;GET SET UP
- OUT MODCTL2 ;INITIALIZE MODEM FOR STOP BITS..
- RET ;..DATA BITS, ETC.
- ENDIF ;DCHAYES
- ;
- IF PMMI OR DCH
- ; ROUTINE TO CONVERT BAUD RATE TO BINARY
- CVBIN: LXI D,FCB+9 ;TO ASCII VALUE
- LXI H,0 ;INIT BINARY RESULT
- DECLP LDAX D ;GET ASCII DIGIT
- INX D ;TO NEXT DIGIT
- CPI ' ' ;BLANK ONE?
- JZ DECLP ;..YES, SKIP IT
- CPI '0' ;VALIDATE IT
- JC BADRATE ;ERROR
- CPI '9'+1 ;VALIDATE
- JNC BADRATE ;ERROR
- SUI '0' ;MAKE DIGIT BINARY
- ;
- ;MULTIPLY PREV VALUE BY 10
- ;
- MOV B,H ;SET UP FOR
- MOV C,L ;MULTIPLY BY 10
- DAD H ;MULTIPLY BY 2
- DAD H ;X 2 = 4
- DAD B ;+ 1 = 5
- DAD H ;X 2 = 10
- ADD L ;ADD IN DIGIT
- MOV L,A ;SAVE BACK
- JNZ DIGNC ;NO CARRY?
- INR H ;ADD IN CARRY
- ;CHECK IF DONE?
- DIGNC MOV A,E ;SEE IF PAST
- CPI FCB+12 ;..LAST DIGIT
- JNZ DECLP ;NO, LOOP
- RET
- ;INVALID BAUD RATE
- ;
- BADRATE CALL ERXIT
- DB '++INVALID BAUD RATE++$'
- ENDIF ;PMMI OR DCHAYES
- ;
- RET ;**THIS MUST BE HERE**
- ;
- ;- T) RATHER
- ;THAT MODEM FILENAME SEND (MODEM FN.FT S) SO THIS
- ;ROUTINE MOVES THE FILENAME FROM THE SECOND FCB
- ;TO THE FIRST
- ;
- MOVEFCB LXI H,FCB+16 ;FROM
- LXI D,FCB ;TO
- MVI B,16 ;LEN
- CALL MOVE ;DO THE MOVE
- XRA A ;GET 0
- STA FCBSNO ;ZERO SECTOR #
- STA FCBEXT ;..AND EXTENT
- RET
- ;
- ;----> SHOW: SHOWS CHAR SENT/RECEIVED
- ;
- ;CR, LF, AND TAB ARE SHOWN. ALL OTHER
- ;NON-PRINTABLE CHARACTERS ARE SHOWN IN
- ;HEX AS (XX)
- ;
- SHOW CPI LF ;LF?
- JZ CTYPE ;..YES, TYPE IT
- CPI CR ;CR?
- JZ CTYPE ;..YES, TYPE IT
- CPI 09 ;TAB
- JZ CTYPE ;..YES, TYPE IT
- CPI ' ' ;CTL-CHR?
- JC SHOWHEX ;YES, SHOW IN HEX
- CPI 7FH ;DEL?
- JC CTYPE ;NO, TYPE THE CHAR
- SHOWHEX PUSH PSW ;SAVE THE CHAR
- MVI A,'(' ;TYPE..
- CALL CTYPE ;..'('
- POP PSW ;THEN..
- CALL HEXO ;..THE CHAR
- MVI A,')' ;THEN..
- JMP CTYPE ;..')' AND RETURN.
- ;
- ;----> CTYPE: TYPES VIA CP/M SO TABS ARE EXPANDED
- ;
- CTYPE PUSH B ;SAVE..
- PUSH D ;..ALL..
- PUSH H ;..REGS
- MOV E,A ;CHAR TO E
- MVI C,WRCON ;GET BDOS FNC
- CALL BDOS ;PRIN THE CHR
- POP H ;RESTORE..
- POP D ;..ALL..
- POP B ;..REGS
- RET ;FROM "CTYPE"
- ;
- CRLF MVI A,CR
- CALL TYPE
- MVI A,LF
- ;
- ;----> TYPE: TYPE VIA DIRECT CBIOS ACCESS
- ;WE ASSUME CBIOS MAY DESTROY SOME REGISTERS,
- ;SO SAVE THEM ALL.
- ;
- ;THIS ROUTINE BYPASSES CP/M'S CTL-S, CTL-C
- ;TESTS.
- ;
- TYPE PUSH PSW ;SAVE CHAR
- PUSH B ;AND OTHER REGISTERS
- PUSH D
- PUSH H
- MOV C,A ;FOR BIOS
- VTYPE CALL $-$ ;MODIFIED AT INIT
- POP H ;RESTORE REGISTERS
- POP D
- POP B
- POP PSW ;..AND CHAR
- RET ;FROM "TYPE"
- ;
- ;----> STAT: KEYBOARD STATUS
- ;
- ;SAVE ALL REGISTERS, EXCEPT A, IN CASE
- ;CBIOS CLOBBERS THEM.
- ;
- STAT PUSH B
- PUSH D
- PUSH H
- VSTAT CALL $-$ ;ADDR SET AT INIT
- POP H
- POP D
- POP B
- ORA A ;0 => NOT READY
- RET
- ;
- ;----> KEYIN: KEYBOARD INPUT
- ;
- ;SAVE ALL REGISTERS, EXCEPT A, IN CASE
- ;CBIOS CLOBBERS THEM.
- ;
- KEYIN PUSH B
- PUSH D
- PUSH H
- VKEYIN CALL $-$ ;ADDR SET AT INIT
- POP H
- POP D
- POP B
- ANI 7FH ;STRIP PARITY IF THERE
- RET ;FROM KEYIN
- ;
- ;----> HEXO: HEX OUTPUT
- ;
- HEXO PUSH PSW ;SAVE FOR RIGHT DIGIT
- RAR ;RIGHT..
- RAR ;..JUSTIFY..
- RAR ;..LEFT..
- RAR ;..DIGIT..
- CALL NIBBL ;PRINT LEFT DIGIT
- POP PSW ;RESTORE RIGHT
- NIBBL ANI 0FH ;ISOLATE DIGIT
- CPI 10 ;IS IS <10?
- JC ISNUM ;YES, NOT ALPHA
- ADI 7 ;ADD ALPHA BIAS
- ISNUM ADI '0' ;MAKE PRINTABLE
- JMP TYPE ;..THEN TYPE IT
- ;
- ;----> CKQUIT: QUIT/RETRY AFTER MULTIPLE ERRS.
- ;
- ;RETURNS W/ ZERO SET IF "RETRY" ASKED FOR
- ;
- CKQUIT XRA A ;ZERO..
- STA ERRCT ;..ERROR COUNT
- CALL ILPRT ;PRINT:
- DB 'MULTIPLE ERRORS ENCOUNTERED. '
- DB 'TYPE Q TO QUIT, R TO RETRY: ',0
- CALL KEYIN ;QUIT/RETRY
- PUSH PSW
- CALL TYPE
- CALL CRLF
- POP PSW
- ANI 5FH ;MAKE UPPER CASE
- CPI 'R' ;RETRY?
- RZ ;'KEEP ON TRUCKIN'
- CPI 'Q' ;QUIT?
- JNZ CKQUIT ;NO, ASK AGAIN
- ORA A ;SET NON-ZERO
- RET
- ;
- ;----> ILPRT: INLINE PRINT OF MSG
- ;
- ;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE,
- ;BINARY 0 AS THE END. BINARY 1 MAY BE USED TO
- ;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE')
- ;
- ILPRT XTHL ;SAVE HL, GET HL=MSG
- ILPLP MOV A,M ;GET CHAR
- ORA A ;END OF MSG?
- JZ ILPRET ;..YES, RETURN
- CPI 1 ;PAUSE?
- JZ ILPAUSE ;..YES
- CALL CTYPE ;TYPE THE MSG
- ILPNEXT INX H ;TO NEXT CHAR
- JMP ILPLP ;LOOP
- ;
- ;PAUSE WHILE TYPING HELP SO INFO DOESN'T
- ; SCROLL OFF OF VIDEO SCREENS
- ;
- ILPAUSE CALL ILPRT ;PRINT:
- DB CR,LF,'PRESS RETURN TO CONTINUE'
- DB CR,LF,0
- CALL KEYIN ;GET ANY CHAR
- CPI 'C'-40H ;REBOOT?
- JZ EXIT ;YES.
- JMP ILPNEXT ;LOOP
- ;
- ILPRET XTHL ;RESTORE HL
- RET ;PAST MSG
- ;
- ;----> PRTMSG: PRINTS MSG POINTED TO BY (DE)
- ;
- ;A '$' IS THE ENDING DELIMITER FOR THE PRINT.
- ;NO REGISTERS SAVED.
- ;
- PRTMSG MVI C,PRINT ;GET BDOS FNC
- JMP BDOS ;PRINT MESSAGE, RETURN
- ;
- ;----> ERXIT: EXIT PRINTING MSG FOLLOWING CALL
- ;
- ERXIT POP D ;GET MESSAGE
- CALL PRTMSG ;PRINT IT
- CALL CKDIS ;DISCONNECT?
- ;
- EXIT LHLD STACK ;GET ORIGINAL STACK
- SPHL ;RESTORE IT
- RET ;--EXIT-- TO CP/M
- ;
- ;MOVE 128 CHARACTERS
- ;
- MOVE128 MVI B,128 ;SET MOVE COUNT
- ;
- ;MOVE FROM (HL) TO (DE) LENGTH IN (B)
- ;
- MOVE MOV A,M ;GET A CHAR
- STAX D ;STORE IT
- INX H ;TO NEXT "FROM"
- INX D ;TO NEXT "TO"
- DCR B ;MORE?
- JNZ MOVE ;..YES, LOOP
- RET ;..NO, RETURN
- ; ----------------
- OPTION DB 0 ;PRIMARY OPTION
- ;
- ;DATAFLG IS USED BY THE "V" SUBCOMMAND -
- ;IT IS 0 WHEN A HEADER OR CKSUM IS BEING
- ;SENT/RCD, AND 1 IF "VIEWABLE" DATA (THE
- ;SECTOR ITSELF) IS
- ;
- DATAFLG DB 0 ;AT HEADER, FIRST
- ;
- ;
- ;SUB-OPTION TABLE. IF AN OPTION IS IN EFFECT,
- ; THE CHARACTER IS SET TO BINARY 0
- ;
- OPTBL EQU $
- ANSWFLG DB 'A' ;ANSWER MODE
- DISCFLG DB 'D' ;DISCONNECT WHEN DONE
- ECHOFLG DB 'E' ;TO ECHO AFTER XFER
- ORIGFLG DB 'O' ;ORIGINATE MODE
- QFLG DB 'Q' ;QUIET TRANSFER (NO MSGS)
- RSEEFLG DB 'R' ;SEE WHAT'S RECEIVED
- SSEEFLG DB 'S' ;SEE WHAT'S SENT
- TERMFLG DB 'T' ;TO TERM AFTER XFER
- VSEEFLG DB 'V' ;VIEW MESSAGES (NO HDR, ETC)
- OPTBE EQU $ ;END OF OPTIONS
- ;
- RCVSNO DB 0 ;SECT # RECEIVED
- SECTNO DB 0 ;CURRENT SECTOR NUMBER
- ERRCT DB 0 ;ERROR COUNT
- HOLDD DB 86H ;HOLD AREA - LAST DC HAYES CONT CHAR.
- ;FOLLOWING 3 USED BY DISK BUFFERING ROUTINES
- EOFLG DB 0 ;EOF FLAG (1=TRUE)
- SECPTR DW DBUF
- SECINBF DB 0 ;# OF SECTORS IN BUFFER
- DS 60 ;STACK AREA
- STACK DS 2 ;STACK POINTER
- ;
- ;16 SECTOR DISK BUFFER (OVERLAYS HELP MSGS)
- ;
- DBUF EQU $ ;16 SECTOR DISK BUFFER
- ;
- ;INVALID COMMAND
- ;
- BADOPT CALL TYPE
- CALL ILPRT ;EXIT W/ERROR
- DB ': INVALID OPTION ON MODEM '
- DB 'COMMAND - ',CR,LF
- DB 'PRESS RETURN FOR HELP, CTL-C IF NOT',CR,LF,1,0
- ;
- HELP CALL ILPRT
- DB 'Format for command is:',cr,lf,cr,lf
- DB 'MODEM # FILENAME',CR,LF,CR,LF
- DB 'Where # is a 1 character primary option,',cr,lf
- DB ' which may be followed by sub-options,',cr,lf
- DB ' and by ".xxx" to set baud rate to xxx'
- DB cr,lf,cr,lf,1
- DB 'Primary Options:',cr,lf
- DB ' S to send a file',cr,lf
- DB ' R to receive a file',cr,lf
- DB ' T to act as a terminal',cr,lf
- DB ' E to act as a computer (echo data)',cr,lf
- DB ' D to disconnect the phone'
- DB ' (S100 modems only)',cr,lf
- DB ' H to print this help file'
- DB cr,lf,cr,lf,1
- DB 'Secondary options:',cr,lf
- DB ' A answer mode',cr,lf
- DB ' O originate mode',cr,lf
- DB ' D disconnect after execution',cr,lf
- DB ' T go to terminal mode after file xfer',cr,lf
- DB ' E go to echo mode after file xfer',cr,lf
- DB ' Q quiet mode - no status msgs',cr,lf
- DB ' R show chars received',cr,lf
- DB ' S show chars sent',cr,lf
- DB ' V view file sent/received (no status)',cr,lf
- DB CR,LF,'FOR EXAMPLES, TYPE: MODEM X',cr,lf,0
- JMP EXIT
- ;
- EXAM CALL ILPRT
- DB 'Send file, originate mode, 300 baud:',CR,LF
- DB ' MODEM SO fn.ft',cr,lf
- DB 'Send another file:',CR,LF
- DB ' MODEM S fn.ft',cr,lf
- DB 'Then send a third file at 450 baud and disconnect'
- DB CR,LF,' MODEM SD.450 fn.ft',cr,lf
- DB 'Act as a terminal at 110 baud',cr,lf
- DB ' MODEM T.110',CR,LF
- DB ' Use ctl-D to disconnect)',cr,lf
- DB 'Receive file, answ mode, view it, 600 baud:',cr,lf
- DB ' MODEM RAV.600 fn.ft',cr,lf,0
- JMP EXIT
- ;
- ; BDOS EQUATES (VERSION 2)
- ;
- RDCON EQU 1
- WRCON EQU 2
- PRINT EQU 9
- CONST EQU 11 ;CONSOLE STAT
- OPEN EQU 15 ;0FFH=NOT FOUND
- CLOSE EQU 16 ; " "
- SRCHF EQU 17 ; " "
- SRCHN EQU 18 ; " "
- ERASE EQU 19 ;NO RET CODE
- READ EQU 20 ;0=OK, 1=EOF
- WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC
- MAKE EQU 22 ;0FFH=BAD
- REN EQU 23 ;0FFH=BAD
- STDMA EQU 26 ;SET DMA
- BDOS EQU BASE+5
- REIPL EQU BASE
- FCB EQU BASE+5CH ;SYSTEM FCB
- FCBEXT EQU FCB+12 ;FILE EXTENT
- FCBSNO EQU FCB+32 ;SECTOR #
- FCB2 EQU BASE+6CH ;SECOND FCB
- END
-