home *** CD-ROM | disk | FTP | other *** search
- ;
- ; XMODEM.ASM V5.0, by Keith Petersen, W8SDZ
- ; (revised 6/8/82)
- ;
- ; REMOTE CP/M - CP/M FILE TRANSFER PROGRAM
- ;
- ;Based on MODEM.ASM V2.0, by Ward Christensen.
- ;This program is intended 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 PMMIBYE program. The baud rate and number of bits
- ;remains the same as whatever was set previously.
- ;There is no disconnect, terminal or echo option.
- ;
- ;Updates/fixes (in reverse order to minimize reading time):
- ;
- ;6/8/82 Added file transfer logging feature. Enabled with
- ; the equate variable LOGCAL, it uses caller
- ; info provided by the RCPM file LASTCALR
- ; together with transferred file name, size and
- ; direction of transfer to append each successful
- ; transfer to new special file LOG.SYS. The user
- ; area designation for LASTCALR must be specified
- ; by the variable LASTUSR and file is expected to
- ; reside on the DEFDRV drive. The support library
- ; SEQIO.LIB(vrs >=2.2) and the MAC assembler are
- ; needed ONLY if LOGCAL is true. If logging is
- ; not desired, or you don't have MAC then LOGCAL
- ; may be set false and the ASM assembler will
- ; work. See SEQIO.LIB for documentation on the
- ; support code. Also made mods to file length
- ; printout to give times for 600 baud (PMMI
- ; only). This is optional with the LSPEED equate.
- ; If used, the baud rate of caller must be made
- ; available thru location MSPEED(by the BYE
- ; program). Jack Riley
- ;04/18/82 Corrected transfer time calculations. Added optional
- ; equate, VOUT for sector count display to
- ; console output. (Must be CRT type device)
- ; Changed modem data port equates into 2 distinct
- ; booleans to accomodate a wider variety of customized
- ; EXTMOD equated modems.
- ; Changed NOCOMR option on receive to automatic
- ; renaming of .COM extents to .OBJ. (Howard Booker)
- ;
- ;04/01/82 Added routine to ERASE any file not properly received
- ; (gets rid of all those damn 0K files) - thanks
- ; to Skip Hansen for this one. - BHK
- ;
- ;03/28/82 Added cancel facility - if first char received
- ; when waiting for initial nak is control-X it will
- ; cancel sending (useful for when the time estimate
- ; is longer than you want to wait). - BHK
- ;
- ;03/22/82 Added calculation of estimated transmission time
- ; when sending a file - divide # sectors by ~ 8 sectors
- ; per minute transmission speed (at 300 baud) - BHK
- ;
- ;03/08/82 Added Bruce Wood's designated user and drive area
- ; routines to the original ver. 46 which contained
- ; the DCH modem updates which were first included
- ; on 10/19/81. Then renamed to ver. 48A to distinguish
- ; from the first ver. 48. (Bill Aten)
- ;
- ;01/06/82 Added code to implement designated user and drive
- ; area to receive files on. This was put in to
- ; make it easier to locate new programs and for drives
- ; that are write protected. This change will put the file
- ; being sent into the designated area and when done return
- ; to the orginal area.
- ; SEE SETAREA LABEL IN THE CONDITIONAL SECTION (Bruce Wood)
- ;
- ;10/19/81 Corrected numerous 'IN MODCTL2' errors for the DC
- ; Hayes modem. Added DC Hayes detection of framing
- ; errors, overrun errors, and parity errors (if
- ; parity is used) for the receive file routine.
- ; (Bill Aten)
- ;
- ;10/12/81 Added code to implement Cyclic Redundancy
- ; Checking for both receiving and sending files.
- ; The CRC can only be specified by the operator
- ; on the receive file option as a secondary
- ; option of 'C' (XMODEM RC FN.FT). When CRC is
- ; in effect, an initial 'C' instead of a NAK will
- ; be sent to the sender to start things off.
- ; The 'C' will be the signal to the sender
- ; (hopefully a version of MODEM that implements
- ; this CRC convention) that CRC is in effect.
- ; CRC will then take the place of the checksum
- ; checking for data validity. The CRC should
- ; make file transfers as far as data integrity is
- ; concerned better than 99.99% error free. The
- ; crc macro, CRC120, was used to implement CRC
- ; in this program and its equivalent version of
- ; MODEM. Acknowledgements and thanks to Paul
- ; Hansknecht who designed and wrote CRC120.
- ;
- ;07/01/81 REDID H8/H89 EQUATES TESTED PROGRAM USING BOTH
- ; SYSTEMS AND CHANGED VER TO 4.4 (AL OLANDER)
- ;
- ;06/28/81 INSTALL H8/H89 EQUATES AND CHANGE EXTERNAL
- ; MODEM EQUATES TO "EXTMOD". (L. SHIPINSKI)
- ;
- ;05/30/81 Added IF PMMI/ENDIF to RCVERR routine to eliminate
- ; 'undefined symbol' error when set for DCH modem.
- ; (Dave Hardy)
- ;
- ;05/07/81 Changed signon revision number.
- ; Cleaned up file. (KBP)
- ;
- ;05/01/81 Added detection of framing errors, overrun
- ; errors, and parity errors (if parity is used)
- ; for the receive file routine. This feature
- ; is only active for the PMMI modem, since I
- ; do not know what the modem status bits are
- ; for IDS and D.C. Hayes modems. If there
- ; is one of the above errors, the line will
- ; be purged for that block and a NAK will be
- ; sent to the sender for that block. This was
- ; added to help catch those transmission errors
- ; that are not always caught by the checksum.
- ; This error checking is in addition to the
- ; checksum routine. (John Mahr)
- ;
- ;02/17/81 Added test for "f2" tagged files in OPENOK
- ; for MP/M version 1.1 compatiblity, which
- ; doesn't allow Ctl-C or Ctl-S in "f1" tagged
- ; files. (Tim Nicholas)
- ;
- ;02/16/81 Added hex to file size display. Now reports
- ; size in both decimal and (xxxxH) hex. Thanks
- ; to Ben Bronson for the idea. (Tim Nicholas)
- ;
- ;02/15/81 Added a software timer to the carrier test
- ; added in SEND and RECV routines. This will
- ; now abort only if carrier is lost for a
- ; period of 15 seconds. This is only essential
- ; for those using external modems with certain
- ; SIO's, but will provide the PMMI/DCH user
- ; faster recovery in a lost carrier situation
- ; as well. Approx 15 seconds plus 15 seconds
- ; in BYE.COM, compared to 3 minutes at 300
- ; baud with earlier revisions. Thanks to Ben
- ; Bronson for his aid in developing this
- ; revision. (Tim Nicholas)
- ;
- ;02/14/81 Corrected error in last update which read
- ; the incorrect port for PMMI in the added
- ; carrier test. (Tim Nicholas)
- ;
- ;01/31/81 Added equates and code for a carrier test.
- ; Test performed in modem I/O routines. This
- ; is required since loss of carrier will go
- ; undetected by BYE.COM, if the loss occurs
- ; after a sucessful XMODEM signon, when using
- ; an external modem and SIO. (Tim Nicholas)
- ;
- ;01/17/81 Re-wrote routine to calculate file size so
- ; that it works correctly on v2.X systems with
- ; extent folding (non-zero extent mask). (BRR)
- ;
- ;12/06/80 Re-wrote routine to calculate file size,
- ; added decimal print of file size. (KBP)
- ;
- ;12/05/80 Corrected error in use of ext byte that pre-
- ; vented files greater than one extent from
- ; being sent. Ron Fowler
- ;
- ;12/03/80 Corrected file extent length display. Now
- ; reports correct number of records for files
- ; longer than one extent. Display is now
- ; double precision (xxxxH). Also made some
- ; cosmetic changes by re-arranging the equates.
- ; By Tim Nicholas
- ;
- ;10/28/80 Cleaned up file. (KBP)
- ;
- ;10/23/80 Expanded conditional assembly of NOCOM routines
- ; into NOCOMS, NOLBS, and NOCOMR equates, to allow
- ; separate conditional assembly of tests for sending
- ; .COM files, sending .??# files, and receiving .COM
- ; files, respectively. (Dave Hardy)
- ;
- ;10/15/80 Added traps for ambiguous file name or
- ; none at all. (KBP)
- ;
- ;09/09/80 Added conditional assembly to prevent filetypes
- ; '.COM' or '.??#' from being sent to distant end
- ; and added conditional assembly of test for '.COM'
- ; filetype on receive as well. See 'NOCOM' below.
- ; Any filetype ending in '#' will not be sent by
- ; this program if 'NOCOM' is set to TRUE. J.SEYMOUR
- ;
- ;NOTE: If you add improvements or otherwise update
- ;this program, please modem a copy of the new file
- ;to "TECHNICAL CBBS" in Dearborn, Michigan - phone
- ;313-846-6127 (110, 300, 450 or 600 baud). Use the
- ;filename XMODEM.NEW. (KBP)
- ;
- FALSE EQU 0
- TRUE EQU NOT FALSE
- ;
- ;-----------------------------------------------------
- ; --- Conditional Assembly Options --- ;
- ;------------------------------------------------------
- ;
- STDCPM EQU TRUE ;TRUE, IS STANDARD CP/M
- ALTCPM EQU FALSE ;TRUE, IS TRS-80 OR H8 W/O 0-ORG
- ;
- PMMI EQU TRUE ;TRUE, IS PMMI
- DCH EQU FALSE ;TRUE, IS D.C. HAYES
- H8 EQU FALSE ;TRUE, IS H8/H89 W/INS8250 MODEM CHIP
- EXTMOD EQU FALSE ;TRUE, IS NONE OF THE ABOVE!
- ;
- NOCOMS EQU TRUE ;TRUE, NO .COM FILES SENT
- NOLBS EQU TRUE ;TRUE, NO .??# FILES SENT
- NOCOMR EQU TRUE ;TRUE, CHANGE.COM TO.OBJ ON RECEIVE
- ;
- 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
- ;
- SETAREA EQU TRUE ;TRUE, IF USING DESIGNATED AREA TO RECEIVE
- RECU EQU 0 ;USER AREA TO REC IN (NOT GREATER THAN 9)
- DEFDRV EQU 'A' ;DRIVE TO REC TO
- ;
- ; FILE TRANSFER LOGGING OPTIONS (J. Riley)
- LOGCAL EQU true ;IF USING LOGGING OF XMODEM TRANSFERS
- LASTUSR EQU 15 ;USER AREA OF 'LASTCALR' FILE (IF 'LOGCAL' ONLY)
- ;
- LSPEED EQU true ;REPORT DIFFERENCES IN BAUD RATES IN PRINTOUT
- MSPEED EQU 3EH ;LOCATION OF CURRENT BAUD RATE FACTOR(set by BYE)
- ;
- VOUT EQU 00000H ;ADR OF VIDEO DRIVER IF OPTIONAL SECTOR
- ;COUNT TO CONSOLE, ELSE LEAVE AS 0000H
- ;
- ;
- ;------------------------------------------------------
- ; --- Modem Port Equates --- ;
- ;------------------------------------------------------
- ;
- IF PMMI
- MODCTLP EQU 0C0H ;PMMI VALUES(base port addr)
- 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
- B600 EQU 1AH ;FACTOR FOR B600 BAUD
- MODCTL2 EQU MODCTLP+3;SECOND CTL PORT
- ENDIF
- ;
- IF H8
- MODCTLP EQU 0DDH ;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 20H ;CARRIER DETECT BIT (MSR-CTS)
- MODDCDA EQU 20H ;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 0D8H ;DATA PORT, RECIEVE
- MODDATO EQU 0D8H ;DATA PORT, SEND
- BAUDRP EQU 0DDH ;BAUD RATE PORT (DALB IN LCR MUST=1)
- MODCTL2 EQU 0DEH ;MODEM STATUS REGISTER (MSR)
- MODCTL1 EQU 0DBH ;LINE CONTROL REGISTER (LCR)
- ENDIF
- ;
- IF 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
- 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 80H ;DATA PORT IN PORT
- MODDATO EQU 80H ;DATA OUT PORT
- MODCTL2 EQU 81H ;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
- ;
- ;
- ;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
- ;
- if setarea
- mvi e,0ffh ;get the current user area a 01/06/82
- mvi c,user ;a 01/06/82
- call bdos ;a 01/06/82
- sta olduser ;save user number here a 01/06/82
- mvi c,curdrv ;get the current drive a 01/06/82
- call bdos ;a 01/06/82
- sta olddrv ;save drive here a 01/06/82
- endif
- ;
- CALL ILPRT ;PRINT:
- DB CR,LF
- DB 'XMODEM ver 5.0V [CRC capable]',CR,LF,0
- ;
- ;GET OPTION
- ;
- LDA FCB+2 ;SECONDARY OPTION?
- CPI 'C' ;CRC CHECKING REQUESTED?
- JNZ CHKOPTN ;NO, GO CHECK PRIMARY
- LDA FCB+1 ;GET PRIMARY OPTION
- CPI 'R' ;CRC VALID ONLY FOR RECEIVE
- JNZ OPTNERR ;PRT MSG, ABORT
- XRA A ;ZERO ACCUM
- STA CRCFLG ;TURN ON CRC FLAG
- ;
- CHKOPTN LDA FCB+1 ;GET OPTION (S or R)
- PUSH PSW ;SAVE OPTION
- ;
- ;Move the filename from FCB2 to FCB1
- ;
- CALL MOVEFCB
- ;
- ;Gobble up garbage chars from the line
- ;prior to receive or send
- ;
- IN MODDATP
- IN MODDATP
- ;
- ;Jump to appropriate function
- ;
- POP PSW ;GET OPTION
- IF LOGCAL
- PUSH PSW ;BUT SAVE IT
- ENDIF
- ;
- CPI 'S' ;SEND..
- JZ SENDFIL ;..A FILE?
- ;
- CPI 'R' ;RECEIVE..
- JZ RCVFIL ;..A FILE?
- ;
- ;Invalid option
- ;
- OPTNERR CALL ERXIT ;EXIT W/ERROR
- DB '++INVALID OPTION ON XMODEM '
- DB 'COMMAND++',CR,LF
- DB 'Must be S for SEND; R or RC '
- DB 'for RECEIVE',CR,LF,'$'
-
- 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
- CMA
- ADI 7EH ; MAGIC NUMBER FOR PMMI MODEM SO WE CAN
- PUT LOG ; PUT OUT A SINGLE LETTER CODE
- LDA PGSIZE ; NOW THE PROGRAM SIZE(IN MINUTES 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 CP/M FILE *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;The CP/M file specified in the XMODEM 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 TRAP ;CHECK FOR NO NAME OR AMBIG. NAME
- CALL CNREC ;COMPUTE # OF RECORDS.
- 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
- 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
- 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 EXITLG ;ALL DONE
- ;
- * * * * * * * * * * * * * * * * * * * * *
- * *
- * RCVFIL: RECEIVE A FILE *
- * *
- * * * * * * * * * * * * * * * * * * * * *
- ;
- ;Receives a file in block format as sent
- ;by another person doing "MODEM S FN.FT".
- ;Can be invoked by 'XMODEM R FN.FT' or
- ;by 'XMODEM RC FN.FT' if CRC is to be used.
- ;
- RCVFIL CALL TRAP ;CHECK FOR NO NAME OR AMBIG. NAME
- ;
- IF NOCOMR
- LXI H,FCB+9 ;POINT TO FILETYPE
- MVI A,'C' ;1ST LETTER
- CMP M ;IS IT C ?
- JNZ CONTINU ;IF NOT, CONTINUE NORMALLY
- INX H ;GET 2ND LETTER
- MVI A,'O' ;2ND LETTER
- CMP M ;IS IT O ?
- JNZ CONTINU ;IF NOT, CONTINUE NORMALLY
- INX H ;GET 3RD LETTER
- MVI A,'M' ;3RD LETTER
- CMP M ;IS IT M ?
- JNZ CONTINU ;IF NOT, CONTINUE NORMALLY
-
- CALL ILPRT ; PRINT RENAMING MESSAGE
- DB 'Auto Renaming Filetype To ".OBJ" '
- DB CR,LF,CR,LF,0
- ;
- LXI H,OBJEXT
- LXI D,FCB+9
- MVI B,3
- ALTEXT MOV A,M
- STAX D
- INX H
- INX D
- DCR B
- JNZ ALTEXT
- JMP CONTINU
-
- OBJEXT DB 'OBJ'
- ENDIF
- ;
- CONTINU CALL CHEKFIL ;SEE IF FILE EXISTS
- CALL MAKEFIL ;..THEN MAKE NEW
- CALL ILPRT ;PRINT:
- ;
- if setarea
- db 'NOTE: File Will Be Received On',cr,lf ; a 01/06/81
- db 'Drive ',defdrv,' User ',recu+30H,cr,lf ; tell this .a 01/06/81
- endif
- ;
- 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
- 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 '++NO FILE NAME SPECIFIED++',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
- RET ;NO AMBIGUOUS NAME, RETURN
- ;
- TRERR CALL ERXIT ;PRINT MSG, EXIT
- DB '++CAN''T USE WILD CARD OPTIONS++',CR,LF,'$'
- ;
- ;----> RCVSECT: Receive a sector
- ;
- ;Returns with carry set if EOT received.
- ;
- RCVSECT XRA A ;GET 0
- STA ERRCT ;INIT ERROR COUNT
- ;
- RCVRPT:
- IF PMMI OR H8 OR DCH
- XRA A ;GET 0
- STA ERRCDE ;CLEAR RECEIVE ERROR CODE
- ENDIF
- ;
- MVI B,10 ;10 SEC TIMEOUT
- CALL RECV ;GET SOH/EOT
- JC RCVSTOT ;TIMEOUT
- ;
- IF PMMI OR H8 OR DCH
- CALL RCVERR ;TRANS ERROR?
- JC RCVSERR ;CARRY SET IF ERROR
- ENDIF
- ;
- CPI SOH ;GET SOH?
- JZ RCVSOH ;..YES
- ;
- ;Earlier versions of MODEM program send some nulls -
- ;ignore them
- ;
- ORA A ;00 FROM SPEED CHECK?
- JZ RCVRPT ;YES, IGNORE IT
- CPI EOT ;END OF TRANSFER?
- STC ;RETURN WITH CARRY..
- RZ ;..SET IF EOT
- ;
- ;Didn't get SOH or EOT -
- ; -or-
- ;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
- LDA CRCFLG ;GET CRC FLAG
- ORA A ;CRC IN EFFECT?
- MVI A,NAK ;PUT NAK IN ACCUM
- JNZ RCVSER2 ;NO, SEND THE NAK
- LDA FIRSTIME;GET FIRST TIME SWITCH
- ORA A ;HAS FIRST SOH BEEN RECEIVED?
- MVI A,NAK ;PUT NAK IN ACCUM
- JZ RCVSER2 ;YES, THEN SEND NAK
- MVI A,CRC ;TELL SENDER CRC IS IN EFFECT
- ;
- RCVSER2 CALL SEND ;..THE NAK or CRC request
- 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 -
- ;
- RCVSABT CALL CLOSFIL ;KEEP WHATEVER WE GOT
- CALL ILPRT
- DB '++UNABLE TO RECEIVE BLOCK '
- DB '- ABORTING++',CR,LF,0
- CALL DELFILE ;DELETE RECEIVED FILE ; v48c smh
- CALL ILPRT ;PRINT SECOND HALF OF MESSAGE
- DB '++INCOMPLETELY RECEIVED FILE '
- DB 'DELETED++',CR,LF,0
- JMP EXIT ;GIVE UP
- ;
- ;----> DELFILE: Deletes the received file (used if receive aborts)
- ; ; v48c smh
- DELFILE LXI D,FCB ;POINT TO FILE ; (whole routine)
- MVI C,ERASEF ;GET FUNCTION
- CALL BDOS ;DELETE IT
- INR A ;DELETE OK?
- RNZ ;..YES, RETURN
- CALL ERXIT ;..NO, ABORT
- DB '++CAN''T DELETE RECEIVED FILE++',CR,LF,'$',0
- ;
- ;Timed out on receive
- ;
- RCVSTOT JMP RCVSERR ;BUMP ERR CT, ETC.
- ;
- ;---->RCVERR: Checks to see if framing error, overrun, or
- ; parity error occurred.
- ; 1. Error code (ERRCDE) was set in recv routine
- ; 2. ERRCDE=0 for no errors, ERRCDE<>0 for errors
- ; 3. If there has been an error, this routine sets
- ; the carry bit on.
- ;
- IF PMMI OR H8 OR DCH
- RCVERR PUSH PSW ;SAVE CHAR TRANSMITTED
- LDA ERRCDE ;GET RECEIVE ERR CODE
- ANA A ;IS IT ZERO?
- JZ RCVERR2 ;YES, NO ERROR
- POP PSW ;RESTORE CHAR TRANSMITTED
- STC ;SET CARRY ON FOR ERROR
- RET
- ;
- RCVERR2 POP PSW ;RESTORE CHAR TRANSMITTED
- ORA A ;CLEAR CARRY BIT
- RET
- ENDIF
- ;
- ;Got SOH - get block #, block # complemented
- ;
- RCVSOH XRA A ;ZERO ACCUM
- STA FIRSTIME;INDICATE FIRST SOH RECV'D
- MVI B,1 ;TIMEOUT = 1 SEC
- CALL RECV ;GET SECTOR
- JC RCVSTOT ;GOT TIMEOUT
- ;
- IF PMMI OR H8 OR DCH
- CALL RCVERR ;TRANS ERROR?
- JC RCVSERR ;CARRY SET IF ERROR
- ENDIF
- ;
- MOV D,A ;D=BLK #
- MVI B,1 ;TIMEOUT = 1 SEC
- CALL RECV ;GET CMA'D SECT #
- JC RCVSTOT ;TIMEOUT
- ;
- IF PMMI OR H8 OR DCH
- CALL RCVERR ;TRANS ERROR?
- JC RCVSERR ;CARRY SET IF ERROR
- ENDIF
- ;
- CMA ;CALC COMPLEMENT
- CMP D ;GOOD SECTOR #?
- JZ RCVDATA ;YES, GET DATA
- ;
- ;Got bad sector #
- ;
- JMP RCVSERR ;BUMP ERROR CT.
- ;
- RCVDATA MOV A,D ;GET SECTOR #
- STA RCVSNO ;SAVE IT
- MVI C,0 ;INIT CKSUM
- CALL CLRCRC ;CLEAR CRC COUNTER
- LXI H,BASE+80H ;POINT TO BUFFER
- ;
- RCVCHR MVI B,1 ;1 SEC TIMEOUT
- CALL RECV ;GET CHAR
- JC RCVSTOT ;TIMEOUT
- ;
- IF PMMI OR H8 OR DCH
- CALL RCVERR ;TRANS ERROR?
- JC RCVSERR ;CARRY SET IF ERROR
- ENDIF
- ;
- MOV M,A ;STORE CHAR
- INR L ;DONE?
- JNZ RCVCHR ;NO, LOOP
- LDA CRCFLG ;GET CRC FLAG
- ORA A ;CRC IN EFFECT?
- JZ RCVCRC ;YES, TO RECEIVE CRC
- ;
- ;Verify checksum
- ;
- MOV D,C ;SAVE CHECKSUM
- MVI B,1 ;TIMEOUT LEN.
- CALL RECV ;GET CHECKSUM
- JC RCVSTOT ;TIMEOUT
- ;
- IF PMMI OR H8 OR DCH
- CALL RCVERR ;TRANS ERROR?
- JC RCVSERR ;CARRY SET IF ERROR
- ENDIF
- ;
- CMP D ;CHECKSUM OK?
- JNZ RCVSERR ;NO, ERROR
- ;
- ;Got a sector, it's a duplicate if = previous,
- ; or OK if = 1 + previous sector
- ;
- CHKSNUM 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
- ;
- ;----> RCVCRC: Receive the cyclic redundancy check
- ; characters (2 bytes), and see if the crc
- ; received matches the one calculated.
- ; If they match, get next sector, else
- ; send a NAK requesting the sector be
- ; resent.
- ;
- RCVCRC MVI E,2 ;NUMBER OF BYTES TO RECEIVE
- ;
- RCVCRC2 MVI B,1 ;1 SEC TIMEOUT
- CALL RECV ;GET CRC BYTE
- JC RCVSTOT ;TIMEOUT
- ;
- IF PMMI OR H8 OR DCH
- CALL RCVERR ;TRANSMISSION ERROR?
- JC RCVSERR ;YES, IF CARRY IS ON
- ENDIF
- ;
- DCR E ;DECREMENT NUM OF BYTES
- JNZ RCVCRC2 ;GET BOTH BYTES
- CALL CHKCRC ;CHECK RCVD CRC AGAINST CALC'D CRC
- ORA A ;IS CRC OKAY?
- JZ CHKSNUM ;YES, GO CHECK SECTOR NUMBERS
- JMP RCVSERR ;GO CHECK ERROR LIMIT AND SEND NAK
- ;
- ;Previous sector 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 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
- ;
- 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..
- CALL SEND ;..CHECKSUM
- RET ;FROM SENDCKS
- ;
- ;----> SENDCRC: Send the two Cyclic Redundancy
- ; Check characters. Call FINCRC
- ; to calc the CRC which will be in
- ; d,e regs 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 program
- ;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
- ;
- ;Reached error limit
- ;
- CSABORT CALL ERXIT
- DB '++CAN''T SEND SECTOR '
- DB '- ABORTING++',CR,LF,'$'
- ;
- ;Timeout getting ACK
- ;
- GETATOT JMP ACKERR ;NO MSG
- ;
- 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 ERXIT ;EXIT WITH ABORT MSG
- DB 'XMODEM PROGRAM CANCELLED',CR,LF,'$'
- ;
- ;----> INCRSNO: Increment sector #
- ;
- INCRSNO LDA SECTNO ;INCR..
- INR A ;..SECT..
- STA SECTNO ;..NUMBER
- PUSH H
- LXI H,VOUT ;CK FOR OPTIONAL COUNT TO CONSOLE
- MOV A,H
- ORA L
- JNZ CONSEC
- POP H
- RET
- ;
- CONSEC: MVI A,CR
- CALL VOUT
- LHLD SECCNT ;UPDATE TOTAL SECTOR COUNT
- INX H
- SHLD SECCNT
- CALL DECOUTX ;DISPLAY COUNT
- POP H
- RET
- ;
- DECOUTX PUSH B
- PUSH D
- PUSH H
- LXI B,-10
- LXI D,-1
- ;
- DECOU2X DAD B
- INX D
- JC DECOU2X
- LXI B,10
- DAD B
- XCHG
- MOV A,H
- ORA L
- CNZ DECOUTX
- MOV A,E
- ADI '0'
- CALL VOUT
- POP H
- POP D
- POP B
- RET
- ;
- ;----> CHEKFIL: See if file exists
- ;
- ;If it exists, say use a different name.
- ;
- CHEKFIL
- if setarea
- call recarea ;set the designated area up a 01/06/81
- endif
- ;
- LXI D,FCB ;POINT TO CTL BLOCK
- MVI C,SRCHF ;SEE IF IT..
- CALL BDOS ;..EXISTS
- INR A ;FOUND?
- RZ ;..NO, RETURN
- CALL ERXIT ;EXIT, PRINT ERROR MESSAGE
- DB '++FILE EXISTS - USE A DIFFERENT NAME++'
- DB CR,LF,'$'
- ;
- ;----> MAKEFIL: Makes the file to be received
- ;
- MAKEFIL XRA A ;SET EXT & REC # TO 0
- STA FCBEXT
- STA FCBSNO
- 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,'$'
- ;
- ;----> CNREC: Computes record count, and saves it
- ; until successful file OPEN.
- ;
- ;LOOK UP THE FCB IN THE DIRECTORY
- CNREC MVI A,'?' ;MATCH ALL EXTENTS
- STA FCBEXT
- MVI A,0FFH
- STA MAXEXT ;INIT MAX EXT NO.
- MVI C,SRCHF ;GET 'SEARCH FIRST' FNC
- LXI D,FCB
- CALL BDOS ;READ FIRST
- INR A ;WERE THERE ANY?
- JNZ SOME ;GOT SOME
- CALL ERXIT
- DB '++FILE NOT FOUND++$'
- ;
- ;READ MORE DIRECTORY ENTRIES
- MOREDIR MVI C,SRCHN ;SEARCH NEXT
- LXI D,FCB
- CALL BDOS ;READ DIR ENTRY
- INR A ;CHECK FOR END (0FFH)
- JNZ SOME ;NOT END OF DIR...PROCESS EXTENT
- LDA MAXEXT ;HIT END...GET HIGHEST EXTENT NO. SEEN
- MOV L,A ;WHICH GIVES EXTENT COUNT - 1
- MVI H,0
- MOV D,H
- LDA RCNT ;GET RECORD COUNT OF MAX EXTENT SEEN
- MOV E,A ;SAVE IT IN DE
- DAD H
- DAD H ;MULTIPLY # OF EXTENTS - 1
- DAD H ; TIMES 128
- DAD H
- DAD H
- DAD H
- DAD H
- DAD D ;ADD IN SIZE OF LAST EXTENT
- SHLD RCNT ;SAVE TOTAL RECORD COUNT
- RET ;AND EXIT
- ;
- ;POINT TO DIRECTORY ENTRY
- SOME DCR A ;UNDO PREV 'INR A'
- ANI 3 ;MAKE MODULUS 4
- ADD A ;MULTIPLY...
- ADD A ;..BY 32 BECAUSE
- ADD A ;..EACH DIRECTORY
- ADD A ;..ENTRY IS 32
- ADD A ;..BYTES LONG
- LXI H,BASE+80H ;POINT TO BUFFER
- ADD L ;POINT TO ENTRY
- ADI 15 ;OFFSET TO RECORD COUNT
- MOV L,A ;HL NOW POINTS TO REC COUNT
- MOV B,M ;GET RECORD COUNT
- DCX H
- DCX H ;BACK DOWN TO EXTENT NUMBER
- DCX H
- LDA MAXEXT ;COMPARE WITH CURRENT MAX.
- ORA A ;IF NO MAX YET
- JM BIGGER ;THEN SAVE RECORD COUNT ANYWAY
- CMP M
- JNC MOREDIR
- ;
- BIGGER: MOV A,B ;SAVE NEW RECORD COUNT
- STA RCNT
- MOV A,M ;SAVE NEW MAX. EXTENT NO.
- STA MAXEXT
- JMP MOREDIR ;GO FIND MORE EXTENTS
- ;
- ;----> 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 '++OPEN ERROR++',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 tag.
- ANI 80H ;Is it set?
- JZ OPENOK2 ;If not, ok to send file.
- ;
- OPENOT CALL ERXIT ;EXIT W/MESSAGE
- DB '++THIS FILE IS NOT FOR DISTRIBUTION, SORRY++'
- DB CR,LF,'$'
- ;
- OPENOK2 EQU $
- ;
- IF NOLBS OR NOCOMS ;CHECK FOR SEND RESTRICTIONS
- LXI H,FCB+11
- MOV A,M ;CHECK FOR PROTECT ATTR
- ANI 7FH ;REMOVE CP/M 2.x ATTRS
- ENDIF ;NOLBS OR NOCOMS
- ;
- IF NOLBS ;DON'T ALLOW '#' TO BE SENT.
- CPI '#' ;CHK FOR '#' AS LAST FIRST
- JZ OPENOT ;IF '#', CAN'T SEND, SHOW WHY
- ENDIF ;NOLBS
- ;
- IF NOCOMS ;DON'T ALLOW .COM TO BE SENT
- CPI 'M' ;IF NOT, CHK FOR '.COM'
- JNZ OPENOK3 ;IF NOT, OK TO SEND
- DCX H
- MOV A,M ;CHK NEXT CHAR
- ANI 7FH ;STRIP ATTRIBUTES
- CPI 'O' ; 'O'?
- JNZ OPENOK3 ;IF NOT, OK TO SEND
- DCX H
- MOV A,M ;NOW CHK FIRST CHAR
- ANI 7FH ;STRIP ATTRIBUTES
- CPI 'C' ; 'C' AS IN '.COM'?
- JNZ OPENOK3 ;IF NOT, CONTINUE
- CALL ERXIT ;EXIT W/MESSAGE
- DB '++CAN''T SEND A .COM FILE++'
- DB CR,LF,'$'
- ENDIF ;NOCOMS
- ;
- OPENOK3 CALL ILPRT ;PRINT:
- DB 'File Open - ',0 ; v48b bhk
- LHLD RCNT ; Get record count.
- CALL DECOUT ;PRINT DECIMAL NUMBER OF SECTORS
- CALL ILPRT
- DB ' (',0
- CALL DHXOUT ;Now print size in hex.
- CALL ILPRT
- DB ' Hex) Sectors',CR,LF ; v48b bhk
- db '(approximately ',0 ; v48b bhk
- lhld rcnt ; get # of sectors ; v48b bhk
- IF LSPEED
- LDA MSPEED ; V50 JPR
- CPI B600 ; "
- PUSH PSW ; "
- JNZ S300 ; "
- XRA A ; DIVIDE HL BY 2 "
- MOV A,H ; "
- RAR ; "
- MOV H,A ; "
- MOV A,L ; "
- RAR ; "
- MOV L,A ; "
-
- S300
- ENDIF
- call divhl14 ; divide HL by 14 (sectors/min) ; v48b bhk
- PUSH H
- IF LOGCAL
- SHLD PGSIZE ; V50 JPR
- ENDIF
- MVI H,0
- call decout ; print decimal # of minutes ; v48b bhk
- call ilprt ; v48b bhk
- db ' mins, ',0
-
- POP H
- MOV A,H ;REMAINDER X 4 = SECONDS
- RLC
- RLC
- MOV L,A
- MVI H,0
- CALL DECOUT
- IF LSPEED
- POP PSW ; V50 JPR
- JNZ MS300
- CALL ILPRT
- DB ' secs to send at 600 baud).',cr,lf ; v48b bhk
- db '[Control-X to cancel.]',cr,lf,0 ; v48c bhk
- RET
- MS300
- ENDIF
- CALL ILPRT
- DB ' secs to send at 300 baud).',cr,lf ; v48b bhk
- db '[Control-X to cancel.]',cr,lf,0 ; v48c bhk
- RET
- ;
- ;----> DIVHL14: Divides HL by 14,
- ; UPON EXIT: L=QUOTIENT,H=REMAINDER
- ;
- divhl14 push b
- MVI B,8 ;SHIFT FACTOR TO B
- MVI C,14 ;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
- ;
- ;----> 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++',CR,LF,'$'
- ;
- ;
- ;----> 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 hi order byte.
- MOV A,L ;Get LS byte.
- CALL HEXO ;Output lo 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 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 ;GED 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++',CR,LF,'$'
- ;
- 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
- ;
- 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
- ;
- MCHAR:
- ;Check to see if there was a framing error,
- ;overrun, or parity error.
- ;
- 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
- ;
- ;Calc 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 D,E
- ;
- 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 # of seconds to wait.
- ;
- ; If the first character received is a CAN (control-X)
- ; then the send will be aborted as though it had timed out.
- ; 04/01/82 BHK
- ;
- 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 (CONTROL-X)? ; v48c bhk
- JZ ABORT ;YES, ABORT ; v48c bhk
- 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 FCB
- ;
- ;In order to make the XMODEM command 'natural',
- ;i.e. XMODEM SEND FILENAME (MODEM S FN.FT) rather
- ;than XMODEM FILENAME SEND (MODEM FN.FT S), 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
- ;
- 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"
- ;
- 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 as the 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
- ;
- if setarea
- call restu ; restore old area user & drive ..a 01/06/81
- endif
- ;
- RET ;--EXIT-- TO CP/M
- ;
- if setarea
- ;
- ;------> RESTORE THE OLD USER AREA AND DRIVE FROM A RECEIVED FILE
- ;
- RESTU lda olddrv ;RESTORE THE OLD DRIVE ;a 01/06/81
- mov e,a ;a 01/06/81
- call recdrx ;a 01/06/81
- lda olduser ;RESTORE THE OLD USER NUMBER ;a 01/06/81
- mov e,a ;a 01/06/81
- jmp recare ;a 01/06/81
- ;
- ;--------> SET USER AREA TO RECEIVE FILE
- RECAREA call recdrv ;ok set the drive to its place ;a 01/06/81
- mvi e,recu ;ok now set the user area ;a 01/06/81
- RECARE mvi c,user ;tell bdos what we want to do ;a 01/06/81
- call bdos ;do it ;a 01/06/81
- RET
- ;
- RECDRV mvi e,defdrv-41h ;make drive cp/m number ;a 01/06/81
- RECDRX mvi c,seldrv ;tell bdos ;a 01/06/81
- call bdos ;do it ;a 01/06/81
- ret ;back ;a 01/06/81
- endif
- ;
- ;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
- ;
- ;************************************************************************
- ;* CRCSUBS (Cyclic Redundancy Code Subroutines) version 1.20 *
- ;* 8080 Mnemonics *
- ;* *
- ;* These subroutines will compute and check a true 16-bit *
- ;* Cyclic Redundancy Code for a message of arbitrary length. *
- ;* *
- ;* The use of this scheme will guarantee detection of all *
- ;* single and double bit errors, all errors with an odd *
- ;* number of error bits, all burst errors of length 16 or *
- ;* less, 99.9969% of all 17-bit error bursts, and 99.9984% *
- ;* of all possible longer error bursts. (Ref: Computer *
- ;* Networks, Andrew S. Tanenbaum, Prentiss-Hall, 1981) *
- ;* *
- ;* *
- ;* There are four entry points, which are used as follows: *
- ;* *
- ;* CLRCRC - A call to this entry resets the CRC accumulator. *
- ;* It must be called at the start of each message. *
- ;* *
- ;* Entry Parameters: None. *
- ;* *
- ;* Exit Conditions: CRC accumulator cleared. *
- ;* All registers preserved. *
- ;* *
- ;* *
- ;* UPDCRC - A call to this entry updates the CRC accumulator. *
- ;* It must be called once for each byte in the *
- ;* message for which the CRC is being calculated. *
- ;* *
- ;* Entry Parameters: (A) = a byte to be included *
- ;* in the CRC calculation. *
- ;* *
- ;* Exit Conditions: CRC accumulator updated. *
- ;* All registers preserved. *
- ;* *
- ;* *
- ;* FINCRC - A call to this entry finishes the CRC calculation *
- ;* for a message which is to be TRANSMITTED. It must *
- ;* be called after the last byte of the message has *
- ;* been passed thru UPDCRC. It returns the calculated *
- ;* CRC bytes, which must be transmitted as the final *
- ;* two bytes of the message (first D, then E). *
- ;* *
- ;* Entry Parameters: None. *
- ;* *
- ;* Exit Conditions: (DE) = calculated CRC bytes. *
- ;* All other registers preserved. *
- ;* *
- ;* *
- ;* CHKCRC - A call to this routine checks the CRC bytes of *
- ;* a RECEIVED message and returns a code to indicate *
- ;* whether the message was received correctly. It must *
- ;* be called after the message AND the two CRC bytes *
- ;* have been received AND passed thru UPDCRC. *
- ;* *
- ;* Entry Parameters: None. *
- ;* *
- ;* Exit Conditions: (A) = 0 if message ok. *
- ;* (A) = -1 if message garbled. *
- ;* All other registers preserved. *
- ;* *
- ;************************************************************************
- ;* *
- ;* Designed & coded by Paul Hansknecht, June 13, 1981 *
- ;* *
- ;* *
- ;* Copyright (c) 1981, Carpenter Associates *
- ;* Box 451 *
- ;* Bloomfield Hills, MI 48013 *
- ;* 313/855-3074 *
- ;* *
- ;* This program may be freely reproduced for non-profit use. *
- ;* *
- ;************************************************************************
- ;
- ; ENTRY CLRCRC,UPDCRC,FINCRC,CHKCRC
- ;
- CLRCRC: EQU $ ; Reset CRC Accumulator for a new message.
- PUSH H
- LXI H,0
- SHLD CRCVAL
- POP H
- RET
- ;
- UPDCRC: EQU $ ; Update CRC Accumulator using byte in (A).
- PUSH PSW
- 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.
- MOV H,A ; An alternate generator which is often
- MOV A,L ; used in synchronous transmission protocols
- XRI 21H ; is X^16 + X^15 + X^2 + 1. This may be
- MOV L,A ; used by substituting XOR 80H for XOR 10H
- SKIPIT: DCR B ; and XOR 05H for XOR 21H in the adjacent code.
- JNZ UPDLOOP
- SHLD CRCVAL
- POP H
- POP B
- POP PSW
- RET
- ;
- FINCRC: EQU $ ; Finish CRC calc for outbound message.
- PUSH PSW
- XRA A
- CALL UPDCRC
- CALL UPDCRC
- PUSH H
- LHLD CRCVAL
- MOV D,H
- MOV E,L
- POP H
- POP PSW
- RET
- ;
- CHKCRC: EQU $ ; Check CRC bytes of received message.
- PUSH H
- LHLD CRCVAL
- MOV A,H
- ORA L
- POP H
- RZ
- MVI A,0FFh
- RET
- ;
- ;
- CRCVAL DW 0
- ;
- ;
- ;
- ;Temporary storage area
- ;
- MAXEXT DB 0 ;HIGHEST EXTENT NO. SEEN IN FILE SIZE CALC.
- RCNT DW 0 ;RECORD COUNT
- RCVSNO DB 0 ;SECT # RECEIVED
- SECTNO DB 0 ;CURRENT SECTOR NUMBER
- SECCNT DW 0 ;TOTAL SECTOR COUNT
- ERRCT DB 0 ;ERROR COUNT
- olduser db 0 ;save the org user number
- olddrv db 0 ;save the org drive number
- ;
- IF PMMI OR H8 OR DCH
- ERRCDE DB 0 ;RECEIVE ERROR CODE
- ENDIF
- ;
- CRCFLG DB 'C' ;SET TO NULL IF CRC USED
- FIRSTIME DB 1 ;TURNED OFF AFTER FIRST SOH RECEIVED
- ;
- ;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
- ;
- DBUF EQU $ ;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 #
- FCB2 EQU BASE+6CH ;SECOND FCB
- ;
- END
-