home *** CD-ROM | disk | FTP | other *** search
- ; LMODEM.ASM by S. Kluger, N5NX
- ;
- ; Developed from XMODEM56.ASM by Keith Petersen, W8SDZ
- ; The basic idea on how to access the LBR file was taken from
- ; LRUN.ASM by G. Novosielski, but no code was copied therefrom.
- ; Error checking is not done as extensively as in LRUN.
- ; Note that this is an EXPERIMENTAL version and could most
- ; definitely be improved by a more experienced programmer.
- ; (This doesn't mean I'm incompetent. I made it work, didn't I???)
- ;
- ;-----------------------------------------------------------------
- ; Modifications/updates: (in reverse order to minimize reading time)
- ; 1.6 12/26/82 Finally fixed send bug. Changed end-of-member detect
- ; routine and placement of RCNT. (SFK)
- ; 1.5 12/25/82 Fixed bug which kept LMODEM from sending files larger
- ; than 255 sectors (bug made file size modulo 255) (SFK)
- ; 1.4 12/22/82 Incorporated directory check to make sure LBR directory
- ; is not corrupt. Changed program to accept either a file name
- ; defaulting to .LBR or any full file name, in case the library
- ; file has a different type. (SFK)
- ; 1.3 12/03/82 Added EQU to version no.,and changed sign-on message.
- ; (Tim Hancock Walled Lake, Mich)
- ; 1.2 11/29/82 Fixed RECU and DEFDRV labels (for LOGCAL only) (SFK)
- ; 1.1 11/27/82 Fixed bug where sometimes the end-of-member would not
- ; be detected; LMODEM kept going until EOF on the LBR (SFK)
- ; 1.0 11/27/82 Original distribution version
- ;
- ;
- ; REMOTE LBR - CP/M FILE TRANSFER PROGRAM
- ;
- ; Based on MODEM.ASM V2.0, by Ward Christensen. This program is in-
- ; tended for use on remote CP/M systems where it is important that the
- ; initialization of the modem not be changed, such as when using the
- ; BYE program. The baud rate and number of bits remains the same as
- ; whatever was set previously. There is no disconnect, terminal or echo
- ; option.
- ;
- ; NOTE: REQUIRES SEQIO22.LIB if "LOGCAL" is set TRUE
- ;
- ;* * * * * * * * * * * * * * * * * *
- ;
- ;
- ; NOTE: If you add improvements or otherwise update
- ; this program, please modem a copy of the
- ; new file to "El Paso RCPM" in El Paso, TX
- ; (915)-598-1668.
- ;
- ;
- ;* * * * * * * * * * * * * * * * * *
- ;
- ;
- FALSE EQU 0
- TRUE EQU NOT FALSE
- ;
- ;
- ;-----------------------------------------------------------------------
- ;
- ; --- Conditional Assembly Options ---
- ;
- ;-----------------------------------------------------------------------
- ;
- ;
- VERSION EQU 1
- MODLEV EQU 6
- ;
- STDCPM EQU TRUE ;TRUE, IS STANDARD CP/M
- ALTCPM EQU FALSE ;TRUE, IS TRS-80 OR H8 W/O 0-ORG
- ;
- DCH EQU FALSE ;TRUE, IS D.C. HAYES
- PMMI EQU TRUE ;TRUE, IS PMMI
- H8 EQU FALSE ;TRUE, IS H8/H89 W/INS8250 MODEM CHIP
- EXTMOD EQU FALSE ;TRUE, IS NONE OF THE ABOVE!
- ;
- FASTCLK EQU TRUE ;PUT TRUE HERE FOR 4 MHZ CLOCK
- ;
- FRNTPNL EQU FALSE ;TO DISPLAY STATUS ON FRONT PANEL
- PANEL EQU 0FFH ;DEFAULT ADDRESS OF FRONT PANEL
- ;
- ;
- ; FILE TRANSFER LOGGING OPTIONS
- ;
- LOGCAL EQU false ;IF USING LOGGING OF LMODEM TRANSFERS
- LASTUSR EQU 14 ;USER AREA OF 'LASTCALR' FILE(IF 'LOGCAL' ONLY)
- RECU EQU 0 ;user area for .LOG file
- DEFDRV EQU 'A' ;LOG file drive
- ;
- LSPEED EQU true ;TRUE IF USING BYE WITH SPEED SELECTION
- MSPEED EQU 3DH ;LOCATION OF BAUD RATE FACTOR (SET BY BYE)
- CONOUT EQU 0000H ;ADDRESS OF BIOS 'C' REGISTER OUTPUT. THIS WILL
- ; ;BE THE 5TH ENTRY IN THE CP/M JUMP TABLE. ENTER
- ; ;YOUR OWN BIOS ADDRESS HERE IF YOU WISH TO HAVE
- ; ;THE RECORD COUNT ON YOUR LOCAL CRT CONSOLE.
- ;
- ;-----------------------------------------------------------------------
- ;
- ; --- Modem Port Equates ---
- ;
- ;-----------------------------------------------------------------------
- ;
- IF PMMI
- MODCTLP EQU 0E0H ;PMMI VALUES (BASE PORT ADDRESS)
- 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
- MODDCDB EQU 4 ;CARRIER DETECT BIT
- MODDCDA EQU 0 ;VALUE WHEN ACTIVE
- MODPARE EQU 08H ;VALUE FOR PARITY ERROR
- MODOVRE EQU 10H ;VALUE FOR OVERRUN ERROR
- MODFRME EQU 20H ;VALUE FOR FRAMING ERROR
- MODDATP EQU MODCTLP+1 ;DATA PORT, RECEIVE
- MODDATO EQU MODCTLP+1 ;DATA PORT, SEND
- BAUDRP EQU MODCTLP+2 ;BAUD RATE OUTPUT/MODEM STATUS
- MODCTL2 EQU MODCTLP+3 ;SECOND CTL PORT
- ENDIF
- ;
- IF H8
- MODCTLP EQU 0E5H ;H8/H89 VALUES (LSR-LINE STATUS REG.)
- MODSNDB EQU 20H ;TEST FOR SEND (LSR-THRE)
- MODSNDR EQU 20H ;VALUE WHEN READY
- MODRCVB EQU 01H ;TEST FOR RECIEVE (LSR-DR)
- MODRCVR EQU 01H ;VALUE WHEN READY
- MODDCDB EQU 80H ;CARRIER DETECT BIT (MSR-CTS)
- MODDCDA EQU 80H ;VALUE WHEN ACTIVE
- MODPARE EQU 04H ;VALUE FOR PARITY ERROR (LSR-PE)
- MODOVRE EQU 02H ;VALUE FOR OVERRUN ERROR (LSR-OR)
- MODFRME EQU 08H ;VALUE FOR FRAMING ERROE (LSR-FE)
- MODDATP EQU 0E0H ;DATA PORT, RECIEVE
- MODDATO EQU 0E0H ;DATA PORT, SEND
- BAUDRP EQU 0E6H ;BAUD RATE PORT (DALB IN LCR MUST=1)
- MODCTL2 EQU 0E6H ;MODEM STATUS REGISTER (MSR)
- MODCTL1 EQU 0E3H ;LINE CONTROL REGISTER (LCR)
- ENDIF
- ;
- IF DCH
- MODCTLP EQU 92H ;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
- MODDCDB EQU 40H ;CARRIER DETECT BIT
- MODDCDA EQU 40H ;VALUE WHEN ACTIVE
- MODPARE EQU 04H ;VALUE FOR PARITY ERROR
- MODOVRE EQU 10H ;VALUE FOR OVERRUN ERROR
- MODFRME EQU 08H ;VALUE FOR FRAMING ERROR
- MODDATP EQU 90H ;DATA PORT IN PORT
- MODDATO EQU 90H ;DATA OUT PORT
- MODCTL2 EQU 91H ;SECOND CTL PORT
- ENDIF
- ;
- ; If you are using an external modem (not S-100 plug-in) change these
- ; equates for your modem port requirements
- ;
- IF EXTMOD
- MODCTLP EQU 0C3H ;PUT YOUR MODEM STATUS PORT HERE
- MODSNDB EQU 10H ;YOUR BIT TO TEST FOR SEND
- MODSNDR EQU 10H ;YOUR VALUE WHEN READY
- MODRCVB EQU 01H ;YOUR BIT TO TEST FOR RECEIVE
- MODRCVR EQU 01H ;YOUR VALUE WHEN READY
- MODDCDB EQU 02H ;CARRIER DETECT BIT
- MODDCDA EQU 02H ;VALUE WHEN ACTIVE
- MODDATP EQU 0C0H ;YOUR MODEM DATA IN PORT
- MODDATO EQU 0C2H ;YOUR MODEM DATA OUT PORT
- MODCTL2 EQU 0C1H ;SECOND CONTROL/STATUS PORT.
- ENDIF ;END OF EXTERNAL MODEM EQUATES
- ;
- ;
- ;-----------------------------------------------------------------------
- ;
- ; --- End of Options ---
- ;
- ;-----------------------------------------------------------------------
- ;
- ;
- ERRLIM EQU 10 ;MAX ALLOWABLE ERRORS (10 STANDARD)
- ;
- ;
- ; 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
- CRC EQU 'C' ;CRC REQUEST CHARACTER
- CAN EQU 18H ;CONTROL-X FOR CANCEL
- LF EQU 10 ;LINEFEED
- CR EQU 13 ;CARRIAGE RETURN
- ;
- IF STDCPM
- BASE EQU 0 ;CP/M BASE ADDRESS
- ENDIF
- ;
- IF ALTCPM
- BASE EQU 4200H ;ALTERNATE CP/M BASE ADDRESS
- ENDIF
- ;
- ORG BASE+100H
- ;
- ;
- JMP BEGIN
-
- SPEED DB 1 ;SPEED FOR FILE TIME TRANSFER WITHOUT AUTO-SET
- ; ;0=110, 1=300, 2=450, 3=600, 4=710, 5=1200
- ;
- ; INIT PRIVATE STACK
- ;
-
- BEGIN:
- LXI H,0 ;HL=0
- DAD SP ;HL=STACK FROM CP/M
- SHLD STACK ; SAVE IT
- LXI SP,STACK ;SP=MY STACK
- CALL ILPRT ;PRINT:
- DB CR,LF
- DB 'LMODEM V'
- DB VERSION+'0' ;VERSION #
- DB '.',MODLEV+'0' ;MODIFICATION LEVEL
- DB '[CRC capable]',CR,LF,0
- MVI A,'S'
- PUSH PSW ;SAVE OPTION
- ;
- ;
- ; MOVE THE FILENAME FROM FCB2 TO MEMFCB
- ;
- CALL MOVEFCB
- ;
- ;
- ; GOBBLE UP GARBAGE CHARACTERS FROM THE LINE PRIOR TO RECEIVER OR SEND
- ;
- IN MODDATP
- IN MODDATP
- ;
- POP PSW ;GET OPTION
- IF LOGCAL
- PUSH PSW ;BUT SAVE IT
- ENDIF
- ;
- STA OPTSAV ;SAVE OPTION IN CASE WE LOSE CARRIER
- JMP SENDFIL
- ;
- IF LOGCAL
- ;
- MACLIB SEQIO22
- ;
- BSIZE EQU 80H
- FILERR SET EXIT
- BUFFERS SET DBUF
- ;
- ;
- ; THE FOLLOWING ALLOCATIONS ARE USED BY THE 'FILE' MACROS
- ;
- DEFAULT$USER:
- DB LASTUSR
- CUR$USER:
- DB 0FFH
- DEFAULT$DISK:
- DB DEFDRV-'A'
- CUR$DISK:
- DB 0FFH
- PGSIZE:
- DW 0
- LOGCALL:
- FILE INFILE,CALLER,,LASTCALR,,BSIZE,,PUBLIC,TRUE
- ;
- MVI A,RECU
- STA DEFAULT$USER
- ;
- FILE APPEND,LOG,,LOG,SYS,BSIZE,,PUBLIC,TRUE
- ;
- POP PSW ;GET OPTION
- PUT LOG ;PUT IT OUT TO LOG
- LDA MSPEED ;GET SPEED FACTOR
- ADI 30H
- PUT LOG ;PUT OUT A SINGLE LETTER CODE
- LDA PGSIZE ;NOW THE PRGM SIZE IN MINS TRANSFER TIME
- CALL PNDEC
- MVI A,' ' ;BLANK
- PUT LOG
- ;
- ;
- ; LOG THE DRIVE AND USER AREA AS A PROMPT
- ;
- LDA FCB
- ORA A
- JNZ WDRV
- MVI C,25
- CALL @BDOS
- INR A
- WDRV:
- ADI 'A'-1
- PUT LOG
- MVI C,32 ;NOW THE USER AREA (AS DECIMAL NUMBER)
- MVI E,0FFH
- CALL @BDOS
- CALL PNDEC
- MVI A,'>' ;MAKE IT LOOK LIKE A PROMPT
- PUT LOG
- LXI H,FCB+1 ;NOW THE NAME OF THE FILE
- MVI B,11
- CALL PUTSTR
- MVI A,' ' ;BLANK
- PUT LOG
- CLOOP:
- GET CALLER ;AND THE CALLER
- CPI EOF
- JZ QUIT
- PUT LOG
- JMP CLOOP
- ;.....
- ;
- ;
- PNDEC:
- CPI 10 ;TWO COLUMN DECIMAL FORMAT ROUTINE
- JC ONE ;ONE OR TWO DIGITS TO AREA #?
- JMP TWO
- ;...
- ;
- ;
- ONE:
- PUSH PSW
- MVI A,'0'
- PUT LOG
- POP PSW
- TWO:
- MVI H,0
- MOV L,A
- CALL DECOT
- RET
- ;.....
- ;
- ;
- DECOT:
- PUSH B
- PUSH D
- PUSH H
- LXI B,-10
- LXI D,-1
- ;
- DECOT2: DAD B
- INX D
- JC DECOT2
- LXI B,10
- DAD B
- XCHG
- MOV A,H
- ORA L
- CNZ DECOT
- MOV A,E
- ADI '0'
- PUT LOG
- POP H
- POP D
- POP B
- RET
- ;.....
- ;
- ;
- PUTSTR:
- MOV A,M
- PUSH H
- PUSH B
- PUT LOG
- POP B
- POP H
- INX H
- DCR B
- JNZ PUTSTR
- RET
- ;.....
- ;
- ;
- QUIT: FINIS LOG
- JMP EXIT
- ;.....
- ;
- ENDIF ;LOGCAL
- ;
- ;
- ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- ; SENDFIL: SENDS A MEMBER OF A LBR FILE
- ;
- ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- ; The LBR member specified in the LMODEM command is transferred over the
- ; phone to another computer running MODEM with the "R" (receive) option.
- ; The data is sent one record at a time with headers and checksums, and
- ; re transmission on errors.
- ;
- SENDFIL:
- CALL TRAP ;CHECK FOR NO NAME OR AMBIG. NAME
- CALL OPENFIL ;OPEN THE FILE
- MVI E,80 ;WAIT 80 SEC FOR INITIAL NAK
- CALL WAITNAK
- ;
- SENDLP:
- CALL RDSECT ;READ A SECTOR
- JC SENDEOF ;SEND 'EOF' IF DONE
- CALL INCRSNO ;BUMP SECTOR #
- XRA A ;ZERO ERROR COUNT
- STA ERRCT
- ;
- SENDRPT:
- CALL SENDHDR ;SEND A HEADER
- CALL SENDSEC ;SEND DATA SECTOR
- LDA CRCFLG ;GET CRC FLAG
- ORA A ;CRC IN EFFECT?
- CZ SENDCRC ;YES, SEND CRC
- CNZ SENDCKS ;NO, SEND CKSUM
- CALL GETACK ;GET THE ACK
- JC SENDRPT ;REPEAT IF NO ACK
- lhld rcnt
- mov a,h
- ora l
- jz sendeof
- dcx h
- shld rcnt
- JMP SENDLP ;LOOP UNTIL EOF
- ;.....
- ;
- ;
- ; FILE SENT, SEND EOT's
- ;
- SENDEOF:
- MVI A,EOT ;SEND AN 'EOT'
- CALL SEND
- CALL GETACK ;GET THE ACK
- JC SENDEOF ;LOOP IF NO ACK
- JMP EXITLG ;ALL DONE
- ;.....
- ;
- ;
- ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- ; SUBROUTINES
- ;
- ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- ;
- ; ---> TRAP: Check for no file name or ambiguous name
- ;
- TRAP LXI H,FCB+1 ;POINT TO FILE NAME
- MOV A,M ;GET FIRST CHAR OF FILE NAME
- CPI ' ' ;ANY THERE?
- JNZ ATRAP ;YES, CHECK FOR AMBIGOUS FILE NAME
- CALL ERXIT ;PRINT MSG, EXIT
- DB CR,LF,'++No File Name Specified++',CR,LF
- DB 'SYNTAX:',CR,LF
- DB 'LMODEM <library> <member>',CR,LF
- DB 'Where <library> is the file name for a '
- DB '.LBR file, i.e. "TEST.LBR" or "TEST"',CR,LF
- DB 'and <member> is the FULL file name for a '
- DB 'member of that LBR file.',CR,LF
- DB '(Find <member> with LDIR <library>).',CR,LF,'$'
- ;
- ATRAP:
- MVI B,11 ;11 CHARS TO CHECK
- TRLOOP:
- MOV A,M ;GET CHAR FROM FCB
- CPI '?' ;AMBIGUOUS?
- JZ TRERR ;YES, EXIT WITH ERROR MSG
- INX H ;POINT TO NEXT CHAR
- DCR B ;ONE LESS TO GO
- JNZ TRLOOP ;NOT DONE, CHECK SOME MORE
- ;
- ; Now see if he specified a LBR file.
- ; If not and if the type is empty, make it LBR.
- ;
- LXI H,FCB+9
- MOV A,M
- CPI ' '
- JZ NOXT ;no extension in file name, make one.
- RET ;NO AMBIGUOUS NAME, RETURN
- ;
- ; NOXT: The file he specified didn't have an extension. Make it LBR.
- ;
- NOXT: LXI D,LBRTYP
- MVI B,3
- NXLP: LDAX D
- MOV M,A
- INX D
- INX H
- DCR B
- JNZ NXLP
- RET
- ;
- LBRTYP: DB 'LBR'
- ;
- TRERR:
- CALL ERXIT ;PRINT MSG, EXIT
- DB CR,LF,'++Wild Card Options not allowed++',CR,LF,'$'
- ;
- ;
- ; ---> SENDHDR: Send the sector header
- ;
- ; SEND: (SOH) (block #) (complemented block #)
- ;
- SENDHDR:
- MVI A,SOH ;SEND
- CALL SEND ; SOH,
- LDA SECTNO ;THEN SEND
- CALL SEND ; SECTOR #
- LDA SECTNO ;THEN SECTOR #
- CMA ; COMPLEMENTED
- JMP SEND ; SECTOR #
- ;.....
- ;
- ;
- ; ---> SENDSEC: Send the data sector
- ;
- SENDSEC:
- MVI C,0 ;INIT CKSUM
- CALL CLRCRC ;CLEAR THE CRC COUNTER
- 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
- RET ;FROM SENDSEC
- ;.....
- ;
- ;
- ; ---> SENDCKS: Send the checksum
- ;
- SENDCKS:
- MOV A,C ;SEND THE
- JMP SEND ; CHECKSUM
- ;.....
- ;
- ;
- ; ---> SENDCRC: Send the two Cyclic Redundancy Check characters. Call
- ; FINCRC to calculate the CRC which will be in 'DE' upon
- ; return.
- ;
- SENDCRC:
- CALL FINCRC ;CALC THE CRC FOR THIS SECTOR
- MOV A,D ;PUT FIRST CRC BYTE IN ACCUM
- CALL SEND ;SEND IT
- MOV A,E ;PUT SECOND CRC BYTE IN ACCUM
- CALL SEND ;SEND IT
- XRA A ;SET ZERO RETURN CODE
- RET
- ;.....
- ;
- ;
- ; ---> 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 pro-
- ; gram aborts.
- ;
- 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
- ;
- ;
- ; 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
- CALL ERXIT
- DB CR,LF,'++Can''t send sector - Aborting++',CR,LF,'$'
- ;
- ;
- ; Timeout getting ACK
- ;
- GETATOT:
- JMP ACKERR ;NO MSG
- ABORT:
- LXI SP,STACK
- ABORTL:
- MVI B,1 ;1 SECOND WITHOUT CHARACTERS
- CALL RECV
- JNC ABORTL ;LOOP UNTIL SENDER DONE
- MVI A,CAN ;CTL- X
- CALL SEND ;STOP SENDING END
- ABORTW:
- MVI B,1 ;1 SECOND WITHOUT CHRACTERS
- CALL RECV
- JNC ABORTW ;LOOP UNTIL SENDER DONE
- MVI A,' ' ;GET A SPACE...
- CALL SEND ;TO CLEAR OUT CONTROL X
- CALL ERXIT ;EXIT WITH ABORT MSG
- DB CR,LF,'++LMODEM Program Cancelled++',CR,LF,'$'
- ;
- ;
- ; ---> INCRSNO: Increment sector #
- ;
- INCRSNO:
- PUSH H ;INCREMENT RECORD NUMBER
- LHLD SECTNO
- INX H
- SHLD SECTNO
- LXI H,CONOUT ;CHECK FOR OPTIONAL COUNT TO CONSOLE
- MOV A,H
- ORA L ;IF 0, THEN NOPE, SO
- POP H
- RZ ;RETURN
- ;...
- ;
- ;
- DSPLY:
- MVI A,1
- STA CONONL ;SET LOCAL ONLY
- CALL ILPRT
- DB CR,'Record #',0
- LHLD SECTNO
- CALL DECOUT
- CALL ILPRT
- DB ' (',0
- CALL DHXOUT
- CALL ILPRT
- DB 'H)',0
- ORA A
- STA CONONL ;RESET LOCAL ONLY
- RET
- ;.....
- ;
- ; ---> OPENFIL: Opens the file to be sent
- ;
- OPENFIL:
- XRA A ;SET EXT & REC # TO 0 FOR PROPER OPEN
- STA FCBEXT
- STA FCBSNO
- 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 CR,LF,'++Unable to open the file++',CR,LF,'$'
- ;
- ;
- ; Check for distribution-protected file
- ;
- OPENOK:
- LDA FCB+1 ;FIRST CHAR OF FILE NAME
- ANI 80H ;CHECK BIT 7
- JNZ OPENOT ;IF ON, FILE CAN'T BE SENT
- LDA FCB+2 ;ALSO CHECK "F2" FOR TAB
- ANI 80H ;IS IS SET?
- JZ OPENOK2 ;IF NOT, OK TO SEND FILE
- OPENOT:
- CALL ERXIT ;EXIT W/MESSAGE
- DB CR,LF,'++File is Not for Distribution, Sorry++'
- DB CR,LF,'$'
- OPENOK2:
- LXI D,80H
- MVI C,STDMA
- CALL BDOS
- MVI C,READ
- LXI D,FCB
- CALL BDOS
- LHLD 8EH
- SHLD DIRSZ
- LXI D,MEMFCB
- LDAX D
- CPI ' '
- JNZ MOK
- CALL ERXIT
- DB '++No member name specified!++',CR,LF,'$'
- ;
- MOK: LXI H,80H
- MOV A,M
- ORA A
- JZ CKDIR ;check directory present?
- BADLBR: CALL ERXIT
- DB '++The file specified is not recognized '
- DB 'as LBR file!++',CR,LF,'$'
- ;
- ; CKDIR - check to see if there indeed is a LBR file
- ; directory and barf if not!
- ;
- CKDIR: MVI B,11 ;len of file name
- MVI A,' ' ;space
- INX H
- CKDLP: CMP M
- JNZ BADLBR
- DCR B
- INX H
- JNZ CKDLP
- ;
- ; The first entry in the LBR directory is indeed blank.
- ; Now see if the directory size is >0
- ;
- MOV D,M
- INX H
- MOV A,M
- ORA D
- JNZ BADLBR
- INX H
- MOV A,M
- INX H
- ORA M
- JZ BADLBR
- LXI H,80H
- ;
- ; The next routine checks the LBR directory for the
- ; specified member name 1 sector at a time.
- ;
- CMLP: MOV A,M
- ORA A
- MVI B,11
- INX H
- JNZ NOMTCH
- CKLP: LDAX D
- CMP M
- JNZ NOMTCH
- INX H
- INX D
- DCR B
- JNZ CKLP
- MOV E,M
- INX H
- MOV D,M
- XCHG
- SHLD INDEX
- XCHG
- INX H
- MOV E,M
- INX H
- MOV D,M
- XCHG
- DCX H
- SHLD RCNT
- LHLD INDEX
- DAD H
- MOV A,H
- STA FCBEXT
- MOV A,L
- RRC
- STA FCBSNO
- LXI D,FCB
- MVI C,OPEN
- CALL BDOS
- CPI 0FFH
- JZ WHAT
- JMP OPENOK3
- ;
- WHAT: CALL ERXIT
- DB '++Impossible error - notify SYSOP++',CR,LF,'$'
- ;
- NOMTCH: INX H
- DCR B
- JNZ NOMTCH
- LXI B,20
- DAD B
- LXI D,MEMFCB
- MOV A,H
- ORA A
- JZ CMLP
- LHLD DIRSZ
- MOV A,H
- ORA L
- JZ NFOUND
- DCX H
- SHLD DIRSZ
- MVI C,READ
- LXI D,FCB
- CALL BDOS
- LXI H,80H
- LXI D,MEMFCB
- JMP CMLP
- ;
- NFOUND: CALL ERXIT
- DB '++Member file not in library++',CR,LF
- DB 'Run LDIR on the file and try again.',CR,LF,'$'
- ;
- OPENOK3:
- CALL ILPRT ;PRINT:
- DB 'File Open: ',0
- LHLD RCNT ;GET RECORD COUNT
- INX H
- CALL DECOUT ;PRINT DECIMAL NUMBER OF RECORDS
- CALL ILPRT
- DB ' (',0
- CALL DHXOUT ;NOW PRINT SIZE IN HEX
- CALL ILPRT
- DB ' Hex) Records',CR,LF
- DB 'Send Time: ',0
-
- IF LSPEED
- LDA MSPEED ;GET THE SPEED INDICATOR
- ENDIF
- ;
- IF NOT LSPEED
- LDA SPEED ;DEFAULT TO PRESET SPEED AT 0103H
- ENDIF
- ;
- LXI D,0
- MOV E,A ;SET UP FOR TABLE ACCESS
- LXI H,BTABLE ;POINT TO BAUD FACTOR TABLE
- DAD D ;INDEX TO PROPER FACTOR
- MOV A,M ;FACTOR IN 'A'
- ;
- LHLD RCNT ;GET NUMBER OF RECORDS
- INX H
- CALL DIVHLA ;DIVIDE HL BY VALUE IN A (RECORDS/MIN)
- PUSH H
- ;
- IF LOGCAL
- SHLD PGSIZE
- ENDIF
- ;
- MVI H,0
- CALL DECOUT ;PRINT DECIMAL NUMBER OF MINUTES
- CALL ILPRT
- DB ' mins, ',0
- LXI H,SECTBL ;POINT TO DIVISORS FOR SECONDS CALC.
- LXI D,0
- ;
- IF LSPEED
- LDA MSPEED ;GET INDEX FOR BAUD RATE
- ENDIF
- ;
- IF NOT LSPEED
- LDA SPEED
- ENDIF
- ;
- MOV E,A
- DAD D ;INDEX INTO TABLE
- MOV A,M ;GET MULTIPLIER
- POP H ;GET REMAINDER
- CALL MULHA ;MULTIPLY 'H' BY 'A'
- CALL SHFTHL
- CALL SHFTHL
- CALL SHFTHL
- CALL SHFTHL
- ;
- MVI H,0
- CALL DECOUT
- ;
- IF LSPEED
- LDA MSPEED ;GET BAUD RATE CODE
- ENDIF
- ;
- IF NOT LSPEED
- LDA SPEED ;DEFAULT TO PRESET SPEED AT 0103H
- ENDIF
- ;
- CPI 0 ;110 BAUD?
- JNZ MS300 ;NO-CHECK 300
- MS110:
- CALL ILPRT
- DB ' secs at 110 Baud',CR,LF,0
- JMP MSCTLX
- ;...
- ;
- ;
- MS300:
- CPI 1 ;300 BAUD?
- JNZ MS450 ;NO-CHECK 450
- CALL ILPRT
- DB ' secs at 300 Baud',CR,LF,0
- JMP MSCTLX
- ;...
- ;
- ;
- MS450
- CPI 2 ;450 BAUD?
- JNZ MS600 ;NO-CHECK 600
- CALL ILPRT
- DB ' secs at 450 Baud',CR,LF,0
- JMP MSCTLX
- ;.....
- ;
- ;
- MS600:
- CPI 3 ;600 BAUD?
- JNZ MS710 ;NO-CHECK 710
- CALL ILPRT
- DB ' secs at 600 Baud',CR,LF,0
- JMP MSCTLX
- ;...
- ;
- ;
- MS710:
- CPI 4 ;710 BAUD?
- JNZ MS1200 ;NO-MUST BE 1200
- CALL ILPRT
- DB ' secs at 710 Baud',CR,LF,0
- JMP MSCTLX
- ;...
- ;
- ;
- MS1200:
- CALL ILPRT ;MUST BE 1200 - NO OTHERS SUPPORTED
- DB ' secs at 1200 Baud',CR,LF,0
- ;...
- ;
- ;
- MSCTLX CALL ILPRT
- DB 'Use CTL-X to Cancel',CR,LF,0
- RET
- ;...
- ;
- ;
- BTABLE: DB 5,13,19,25,29,49,0
- SECTBL: DB 192,74,51,38,33,20,0
- ;...
- ;
- ;
- ; ---> DIVHL-A: Divides 'HL' by value in 'A',
- ; UPON EXIT: L=QUOTIENT,H=REMAINDER
- ;
- DIVHLA:
- PUSH B
- MVI B,8 ;SHIFT FACTOR TO 'B'
- MOV C,A ;DIVISOR TO 'C'
- DIV2:
- XRA A ;CLEAR CARRY FLAG AND ACCUMULATOR
- DAD H
- MOV A,H
- SUB C
- JM DIV3 ;DONT BORROW ON NEG RESULTS
- MOV H,A
- MOV A,L
- ORI 1 ;BORROW 1
- MOV L,A
- DIV3:
- DCR B
- JNZ DIV2
- POP B
- RET
- ;...
- ;
- ;
- ; ---> MULHA: Multiply the value in 'H' by the value in 'A'
- ; Return with answer in 'HL'.
- ;
- MULHA:
- MOV B,A ;PUT LOOP COUNT IN 'B'
- MVI D,0
- MOV E,H
- MOV L,H
- MVI H,0
- MULLP:
- DCR B
- RZ
- DAD D
- JMP MULLP
- RET
- ;
- ;
- ; Shift the 'HL' pair one bit to the right
- ;
- SHFTHL:
- MOV A,L
- RAR
- MOV L,A
- ORA A ;CLEAR THE CARRY BIT
- MOV A,H
- RAR
- MOV H,A
- RNC
- MVI A,80h
- ORA L
- MOV L,A
- RET
- ;.....
- ;
- ; ---> DECOUT: Decimal output routine
- ;
- DECOUT:
- PUSH B
- PUSH D
- PUSH H
- LXI B,-10
- LXI D,-1
- DECOU2:
- DAD B
- INX D
- JC DECOU2
- LXI B,10
- DAD B
- XCHG
- MOV A,H
- ORA L
- CNZ DECOUT
- MOV A,E
- ADI '0'
- CALL CTYPE
- POP H
- POP D
- POP B
- RET
- ;.....
- ;
- ;
- ; ---> DHXOUT: Double precision hex output routine.
- ; Call with hex value in 'HL'.
- ;
- DHXOUT:
- PUSH H ;SAVE H,L
- PUSH PSW ;SAVE A
- MOV A,H ;GET MS BYTE
- CALL HEXO ;OUTPUT HIGH ORDER BYTE
- MOV A,L ;GET LS BYTE
- CALL HEXO ;OUTPUT LOW ORDER BYTE
- POP PSW ;RESTORE A
- POP H ;RESTORE H,L
- RET ;RETURN TO CALLER
- ;
- ;
- ; ---> RDSECT: Reads a sector
- ;
- ; For speed, this routine buffers up 16 sectors at a time.
- ;
- RDSECT: LDA SECNBF ;GET # SECT IN BUFF
- DCR A ;DECREMENT
- STA SECNBF ; 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 ADDRESS
- CALL BDOS
- 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 CR,LF,'++File Read Error++',CR,LF,'$'
- ;
- RDSECOK:
- INR C
- LXI H,80H ;ADD LENGTH OF ONE SECTOR
- DAD D ; TO NEXT BUFF
- XCHG ;BUFF TO DE
- 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 SECNBF ;STORE SECTOR COUNT
- LXI H,DBUF ;INIT BUFFER POINTEAR
- SHLD SECPTR
- LXI D,BASE+80H ;RESET DMA ADDRESS
- MVI C,STDMA
- CALL BDOS
- JMP RDSECT ;PASS SECT TO CALLER
- ;
- ;----> 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:
- 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 SECOND DCR COUNT
- ;
- IF NOT DCH
- MWTI:
- IN MODCTLP ;CHECK STATUS
- ENDIF
- ;
- IF DCH
- MWTI:
- IN MODCTL2 ;CHECK STATUS
- ENDIF
- ;
- IF PMMI AND FRNTPNL
- OUT PANEL ;DISPLAY STATUS ON PANEL LIGHTS
- 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
- ;
- ;
- ; Test for the presence of carrier - if none, go to CARCK and continue
- ; testing for 15 seconds. If carrier returns, continue. If is doesn't
- ; return, exit.
- ;
- IF EXTMOD OR H8 OR DCH
- IN MODCTL2 ;READ MODEM STATUS
- ENDIF
- ;
- IF PMMI
- IN BAUDRP ;READ MODEM STATUS
- ENDIF
- ;
- IF PMMI AND FRNTPNL
- OUT PANEL ;DISPLAY STATUS ON PANEL LIGHTS
- ENDIF
- ;
- ANI MODDCDB ;CARRIER DETECT MASK
- CPI MODDCDA ;IS IT STILL ON?
- CNZ CARCK ;IF NOT, TEST FOR 15 SECONDS
- ;
- ; Modem timed out receiving - but carrier still on.
- ;
- POP D ;RESTORE D,E
- STC ;CARRY SHOWS TIMEOUT
- RET
- ;.....
- ;
- ;
- ; Got character from modem. Check to see if there was a framing error,
- ; overrun, or parity error.
- ;
- MCHAR:
- IF PMMI OR H8
- IN MODCTLP ;GET MODEM STATUS
- ENDIF
- ;
- IF DCH
- IN MODCTL2 ;GET MODEM STATUS
- ENDIF
- ;
- IF PMMI OR H8 OR DCH
- MOV D,A ;SAVE STATUS
- ANI MODFRME ;FRAMING ERROR?
- CPI MODFRME
- JNZ MCHAR2 ;NO, CHECK FOR OVERRUN
- LDA ERRCDE ;GET RECV ERR CODE
- ORI MODFRME ;TURN ON RECV ERR CODE
- STA ERRCDE ;PUT IT BACK
- MCHAR2:
- MOV A,D ;RESTORE MODEM STATUS
- ANI MODOVRE ;OVERRUN?
- CPI MODOVRE
- JNZ MCHAR3 ;NO, CHECK FOR PARITY ERROR
- LDA ERRCDE
- ORI MODOVRE ;TURN ON RECV ERR CODE
- STA ERRCDE
- MCHAR3:
- MOV A,D ;RESTORE MODEM STATUS
- ANI MODPARE ;PARITY ERROR?
- CPI MODPARE
- JNZ MCHAR4 ;NO, GET DATA CHAR
- LDA ERRCDE
- ORI MODPARE
- STA ERRCDE
- MCHAR4:
- ENDIF ;PMMI OR H8 OR DCH
- ;
- ;
- ; Get data char
- ;
- IN MODDATP ;READ THE CHAR
- POP D ;RESTORE 'DE'
- ;
- ;
- ; Calculate checksum and CRC
- ;
- PUSH PSW ;SAVE THE CHAR
- CALL UPDCRC ;CALC CRC
- ADD C ;ADD TO CHECKSUM
- MOV C,A ;SAVE CHECKSUM
- POP PSW ;RESTORE CHAR
- ORA A ;CARRY OFF: NO ERROR
- RET ;FROM "RECV"
- ;.....
- ;
- ;
- ; CARCK - common 15 second carrier test for RECV and SEND. If carrier
- ; returns within 15 seconds, normal program execution continues. Else,
- ; it will abort to CP/M via EXIT.
- ;
- CARCK:
- MVI E,150 ;VALUE FOR 15 SECOND DELAY
- CARCK1:
- CALL DELAY ;KILL .1 SECONDS
- ;
- IF EXTMOD OR H8 OR DCH
- IN MODCTL2 ;READ MODEM STATUS
- ENDIF
- ;
- IF PMMI
- IN BAUDRP ;READ MODEM STATUS
- ENDIF
- ;
- IF PMMI AND FRNTPNL
- OUT PANEL ;DISPLAY STATUS
- ENDIF
- ;
- ANI MODDCDB ;CARRIER DETECT MASK
- CPI MODDCDA ;IS IT STILL ON?
- RZ ;RETURN IF CARRIER ON
- DCR E ;HAS 15 SECONDS EXPIRED?
- JNZ CARCK1 ;IF NOT, CONTINUE TESTING
- JMP EXIT ;ELSE, ABORT TO CP/M.
- ;
- ;
- ; DELAY - 100 millisecond delay.
- ;
- DELAY:
- PUSH B ;SAVE B,C
- ;
- IF FASTCLK ;IF 4MHZ CLOCK
- LXI B,16667 ;VALUE FOR 100MS DELAY
- ENDIF
- ;
- IF NOT FASTCLK
- LXI B,8334 ;VALUE FOR 100MS DELAY
- ENDIF
- DELAY2:
- DCX B ;UPDATE COUNT
- MOV A,B ;GET MS BYTE
- ORA C ;COUNT = ZERO?
- JNZ DELAY2 ;IF NOT, CONTINUE
- POP B ;RESTORE B,C
- RET ;RETURN TO CARCK1.
- ;.....
- ;
- ;
- ; ---> SEND: Send a character to the modem
- ;
- SEND:
- PUSH PSW ;SAVE THE CHARACTER
- CALL UPDCRC ;CALC THE CRC
- 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
- ;
- IF PMMI AND FRNTPNL
- OUT PANEL ;DISPLAY STATUS
- ENDIF
- ;
- ANI MODSNDB ;ISOLATE READY BIT
- CPI MODSNDR ;READY?
- JZ SENDR ; YES, GO SEND
- ;
- ;
- ; Xmit status not ready, so test for carrier before looping - if lost,
- ; go to CARCK and give it up to 15 seconds to return. If it doesn't,
- ; return abort via EXIT.
- ;
- PUSH D ;SAVE 'DE'
- ;
- IF EXTMOD OR H8 OR DCH
- IN MODCTL2 ;READ MODEM STATUS
- ENDIF
- ;
- IF PMMI
- IN BAUDRP ;READ MODEM STATUS
- ENDIF
- ;
- IF PMMI AND FRNTPNL
- OUT PANEL ;DISPLAY STATUS
- ENDIF
- ;
- ANI MODDCDB ;CARRIER DETECT MASK
- CPI MODDCDA ;IS IT STILL ON?
- CNZ CARCK ;IF NOT, CONTINUE TESTING IT
- POP D ;RESTORE D,E
- JMP SENDW ;ELSE, WAIT FOR XMIT READY.
- ;.....
- ;
- ;
- ; Xmit status ready, carrier still on - send the data.
- ;
- SENDR:
- 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 first timeout-NAK or the letter 'C' for CRC
- ; from the receiver. If CRC is in effect, then Cyclic Redundancy Checks
- ; are used instead of checksums. 'E' contains the number of seconds to
- ; wait.
- ;
- ; If the first character received is a CAN (CTL-X) then the send will be
- ; aborted as though it had timed out.
- ;
- WAITNAK:
- MVI B,1 ;TIMEOUT DELAY
- CALL RECV ;DID WE GET
- CPI NAK ; A NAK?
- RZ ;YES, SEND BLOCK
- CPI CRC ;CRC INDICATED?
- JZ WAITCRC ;YES, GO PUT CRC IN EFFECT
- CPI CAN ;WAS IT A CANCEL (CTL-X)?
- JZ ABORT ;YES, ABORT
- DCR E ;80 TRIES?
- JZ ABORT ;YES, ABORT
- JMP WAITNAK ;NO, LOOP
- ;.....
- ;
- ;
- ; ---> WAITCRC: Turn on CRC Flag
- ;
- WAITCRC:
- XRA A ;ZERO ACCUM
- STA CRCFLG ;TURN ON CRC OPT
- RET
- ;.....
- ;
- ;
- ; ---> MOVEFCB: Moves FCB(2) to MEMFCB
- ;
- ; Saves the member file name into MEMFCB
- ;
- MOVEFCB:
- LXI H,FCB+16 ;FROM
- LXI D,MEMFCB-1 ;TO
- MVI B,16 ;LEN
- CALL MOVE ;DO THE MOVE
- XRA A ;GET 0
- STA FCBSNO ;ZERO SECTOR #
- STA FCBEXT ; AND EXTENT
- RET
- ;.....
- ;
- ;
- CTYPE:
- PUSH B ;SAVE ALL REGISTERS
- PUSH D
- PUSH H
- PUSH PSW ;SAVE THE CHARACTER TEMPORARILY
- LDA CONONL ;LOCAL ONLY?
- ORA A
- JNZ CLTYP ;YES, TO TO BIOS OUT
- POP PSW ;ELSE GET THE CHARACTER BACK
- MOV E,A ;CHARACTER TO 'E'
- MVI C,WRCON ;WRITE TO CONSOLE
- CALL BDOS ;PRINT THE CHARACTER
- POP H ;RESTORE
- POP D ; ALL
- POP B ; REGS
- RET ;FROM "CTYPE"
- ;...
- ;
- ;
- CLTYP:
- POP PSW ;GET THE CHARACTER BACK
- MOV C,A ;BIOS NEEDS IT IN 'C'
- CALL CONOUT ;DO BIOS CALL
- POP H ;ALL THIS
- POP D ; IS FROM
- POP B ; CTYPE ROUTINE
- RET
- ;.....
- ;
- ;
- 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 IT <10?
- JC ISNUM ;YES, NOT ALPHA
- ADI 7 ;ADD ALPHA BIAS
- ISNUM:
- ADI '0' ;MAKE PRINTABLE
- JMP CTYPE ; THEN TYPE IT
- ;.....
- ;
- ;
- ; ---> ILPRT: Inline print of message
- ;
- ; The call to ILPRT is followed by a message, binary 0 for its end.
- ;
- ILPRT:
- XTHL ;SAVE HL, GET HL=MSG
- ;
- ILPLP:
- MOV A,M ;GET CHAR
- ORA A ;END OF MSG?
- JZ ILPRET ; YES, RETURN
- CALL CTYPE ;TYPE THE MSG
- INX H ;TO NEXT CHAR
- JMP ILPLP ;LOOP
- ;...
- ;
- ILPRET:
- XTHL ;RESTORE HL
- RET ;PAST MSG
- ;.....
- ;
- ;
- EXITLG: ; SPECIAL LOG CALLER EXIT
- IF LOGCAL
- JMP LOGCALL
- ENDIF
- ;
- JMP EXIT
- ;.....
- ;
- ;
- ; ---> ERXIT: Exit printing message following call
- ;
- ERXIT:
- POP D ;GET MESSAGE
- MVI C,PRINT ;GET BDOS FNC
- CALL BDOS ;PRINT MESSAGE
- EXIT:
- LHLD STACK ;GET ORIGINAL STACK
- SPHL ;RESTORE IT
- ;
- RET ;--EXIT-- TO CP/M
- ;
- ;
- ; Move 128 characters from 'HL' to 'DE' length in 'B'
- ;
- MOVE128:
- MVI B,128 ;SET MOVE COUNT
- 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
- ;.....
- ;
- ;
- ;***********************************************************************
- ;
- ; CRCSUBS (Cyclic Redundancy Code Subroutines) version 1.20
- ; 8080 Mnemonics
- ;
- ; These subroutines will compute and check a true 16-bit Cyclic Redun-
- ; dancy Code for a message of arbitrary length.
- ;
- ; (Theory and appliction are discussed extensively in the LMODEMxx.HIS
- ; file. See that for additional information.)
- ;
- ;***********************************************************************
- ;
- ;
- ; ENTRY CLRCRC,UPDCRC,FINCRC,CHKCRC
- ;
- CLRCRC:
- PUSH H ;RESET CRC ACCUMULATOR FOR A NEW MSG.
- LXI H,0
- SHLD CRCVAL
- POP H
- RET
- ;
- UPDCRC:
- PUSH PSW ;UPDATE CRC ACCUMULATOR WITH BYTE IN 'A'
- PUSH B
- PUSH H
- MVI B,8
- MOV C,A
- LHLD CRCVAL
- UPDLOOP:
- MOV A,C
- RLC
- MOV C,A
- MOV A,L
- RAL
- MOV L,A
- MOV A,H
- RAL
- MOV H,A
- JNC SKIPIT
- ;
- MOV A,H ;The generator is X^16 + X^12 + X^5 + 1
- XRI 10H ;as recommended by CCITT. An alternate
- MOV H,A ;generator which is often used in
- MOV A,L ;synchronous transmission protocols is
- XRI 21H ;X^16 + X^15 + X^2 + 1. This may be used
- MOV L,A ;by substituting XOR 80H for XOR 10H and
- SKIPIT:
- DCR B ;XOR 05H for XOR 21H in the adj. code.
- JNZ UPDLOOP
- SHLD CRCVAL
- POP H
- POP B
- POP PSW
- RET
- ;
- FINCRC:
- PUSH PSW ;FINISH CRC CALC FOR OUTBOUND MSG.
- XRA A
- CALL UPDCRC
- CALL UPDCRC
- PUSH H
- LHLD CRCVAL
- MOV D,H
- MOV E,L
- POP H
- POP PSW
- RET
- ;.....
- ;
- CRCVAL: DW 0
- ;
- ;
- ;
- ; Temporary storage area
- ;
- DB 0
- MEMFCB: DS 16
- ;
- DIRSZ: DW 0
- MAXEXT: DB 0 ;HIGHEST EXT. # SEEN IN FILE SIZE CALC.
- SECTNO: DW 0 ;CURRENT SECTOR NUMBER
- ERRCT: DB 0 ;ERROR COUNT
- OPTSAV: DB 0 ;SAVE OPTION HERE FOR CARRIER LOSS
- CONONL: DB 0 ;CTYPE CONSOLE-ONLY FLAG
- INDEX: DW 0
- ;
- IF PMMI OR H8 OR DCH
- ERRCDE: DB 0 ;RECEIVE ERROR CODE
- ENDIF
- ;
- CRCFLG: DB 'C' ;SET TO NULL IF CRC USED
- RCNT: DW 0 ;RECORD COUNT
- ;
- ;
- ; Following 3 used by disk buffering routines
- ;
- EOFLG: DB 0 ;'EOF' FLAG (1=TRUE)
- SECPTR: DW DBUF
- SECNBF: DB 0 ;# OF SECTORS IN BUFFER
- DS 60 ;STACK AREA
- ;
- STACK: DS 2 ;STACK POINTER
- ;
- ;
- ; 16 sector disk buffer
- ;
- DBUF: DS 0 ;16 SECTOR DISK BUFFER
- ;
- ; BDOS equates
- ;
- RDCON EQU 1
- WRCON EQU 2
- PRINT EQU 9
- CONST EQU 11 ;CONSOLE STAT
- SELDRV EQU 14 ;SELECT DRIVE
- OPEN EQU 15 ;0FFH = NOT FOUND
- CLOSE EQU 16 ; " "
- SRCHF EQU 17 ; " "
- SRCHN EQU 18 ; " "
- ERASEF 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
- CURDRV EQU 25 ;GET CURRENT DRIVE
- STDMA EQU 26 ;SET DMA
- USER EQU 32 ;SET USER AREA TO RECEIVE FILE
- BDOS EQU BASE+5
- FCB EQU BASE+5CH ;SYSTEM FCB
- FCBEXT EQU FCB+12 ;FILE EXTENT
- FCBSNO EQU FCB+32 ;SECTOR #
- ;.....
- ;
- ;
- END
-