CP/M MACRO ASSEM 2.0 #001 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ TITLE '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 CP/M MACRO ASSEM 2.0 #002 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; 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) CP/M MACRO ASSEM 2.0 #003 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; 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 ; CP/M MACRO ASSEM 2.0 #004 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ;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) ; 0000 = FALSE EQU 0 FFFF = TRUE EQU NOT FALSE ; ;----------------------------------------------------- ; --- CONDITIONAL ASSEMBLY OPTIONS --- ; ;------------------------------------------------------ ; FFFF = STDCPM EQU TRUE ;TRUE, IS STANDARD CP/M 0000 = ALTCPM EQU FALSE ;TRUE, IS TRS-80 OR H8 W/O 0-ORG ; 0000 = PMMI EQU FALSE ;TRUE, IS PMMI FFFF = DCH EQU TRUE ;TRUE, IS D.C. HAYES 0000 = H8 EQU FALSE ;TRUE, IS H8/H89 W/INS8250 MODEM CHIP 0000 = EXTMOD EQU FALSE ;TRUE, IS NONE OF THE ABOVE! ; 0000 = NOCOMS EQU FALSE ;TRUE, NO .COM FILES SENT FFFF = NOLBS EQU TRUE ;TRUE, NO .??# FILES SENT FFFF = NOCOMR EQU TRUE ;TRUE, CHANGE.COM TO.OBJ ON RECEIVE ; FFFF = FASTCLK EQU TRUE ;PUT TRUE HERE FOR 4 MHZ CLOCK ; 0000 = FRNTPNL EQU FALSE ;TO DISPLAY STATUS ON FRONT PANEL 00FF = PANEL EQU 0FFH ;DEFAULT ADDRESS OF FRONT PANEL ; FFFF = SETAREA EQU TRUE ;TRUE, IF USING DESIGNATED AREA TO RECEIVE CP/M MACRO ASSEM 2.0 #005 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0000 = RECU EQU 0 ;USER AREA TO REC IN (NOT GREATER THAN 9) 0041 = DEFDRV EQU 'A' ;DRIVE TO REC TO ; ; FILE TRANSFER LOGGING OPTIONS (J. RILEY) 0000 = LOGCAL EQU FALSE ;IF USING LOGGING OF XMODEM TRANSFERS 000F = LASTUSR EQU 15 ;USER AREA OF 'LASTCALR' FILE (IF 'LOGCAL' ONLY) ; 0000 = LSPEED EQU FALSE ;REPORT DIFFERENCES IN BAUD RATES IN PRINTOUT 003E = MSPEED EQU 3EH ;LOCATION OF CURRENT BAUD RATE FACTOR(SET BY BYE) ; 0000 = 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 0082 = MODCTLP EQU 82H ;D. C. HAYES VALUES CP/M MACRO ASSEM 2.0 #006 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0002 = MODSNDB EQU 2 ;BIT TO TEST FOR SEND 0002 = MODSNDR EQU 2 ;VALUE WHEN READY 0001 = MODRCVB EQU 1 ;BIT TO TEST FOR RECEIVE 0001 = MODRCVR EQU 1 ;VALUE WHEN READY 0040 = MODDCDB EQU 40H ;CARRIER DETECT BIT 0040 = MODDCDA EQU 40H ;VALUE WHEN ACTIVE 0004 = MODPARE EQU 04H ;VALUE FOR PARITY ERROR 0010 = MODOVRE EQU 10H ;VALUE FOR OVERRUN ERROR 0008 = MODFRME EQU 08H ;VALUE FOR FRAMING ERROR 0080 = MODDATP EQU 80H ;DATA PORT IN PORT 0080 = MODDATO EQU 80H ;DATA OUT PORT 0081 = 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 --- ;------------------------------------------------------ ; 000A = ERRLIM EQU 10 ;MAX ALLOWABLE ERRORS (10 STANDARD) ; ;DEFINE ASCII CHARACTERS USED ; 0001 = SOH EQU 1 ;START OF HEADER 0004 = EOT EQU 4 ;END OF TRANSMISSION 0006 = ACK EQU 6 ;ACKNOWLEDGE 0015 = NAK EQU 15H ;NEG ACKNOWLEDGE 0043 = CRC EQU 'C' ;CRC REQUEST CHARACTER 0018 = CAN EQU 18H ;CONTROL-X FOR CANCEL 000A = LF EQU 10 ;LINEFEED 000D = CR EQU 13 ;CARRIAGE RETURN ; IF STDCPM 0000 = BASE EQU 0 ;CP/M BASE ADDRESS ENDIF ; IF ALTCPM BASE EQU 4200H ;ALTERNATE CP/M BASE ADDRESS ENDIF ; 0100 ORG BASE+100H ; CP/M MACRO ASSEM 2.0 #007 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; ;INIT PRIVATE STACK 0100 210000 BEGIN LXI H,0 ;HL=0 0103 39 DAD SP ;HL=STACK FROM CP/M 0104 22030B SHLD STACK ;..SAVE IT 0107 31030B LXI SP,STACK ;SP=MY STACK ; IF SETAREA 010A 1EFF MVI E,0FFH ;GET THE CURRENT USER AREA A 01/06/82 010C 0E20 MVI C,USER ;A 01/06/82 010E CD0500 CALL BDOS ;A 01/06/82 0111 32BE0A STA OLDUSER ;SAVE USER NUMBER HERE A 01/06/82 0114 0E19 MVI C,CURDRV ;GET THE CURRENT DRIVE A 01/06/82 0116 CD0500 CALL BDOS ;A 01/06/82 0119 32BF0A STA OLDDRV ;SAVE DRIVE HERE A 01/06/82 ENDIF ; 011C CD1B0A CALL ILPRT ;PRINT: 011F 0D0A DB CR,LF 0121 584D4F4445 DB 'XMODEM ver 5.0V [CRC capable]',CR,LF,0 ; ;GET OPTION ; 0141 3A5E00 LDA FCB+2 ;SECONDARY OPTION? 0144 FE43 CPI 'C' ;CRC CHECKING REQUESTED? 0146 C25501 JNZ CHKOPTN ;NO, GO CHECK PRIMARY 0149 3A5D00 LDA FCB+1 ;GET PRIMARY OPTION 014C FE52 CPI 'R' ;CRC VALID ONLY FOR RECEIVE 014E C26B01 JNZ OPTNERR ;PRT MSG, ABORT 0151 AF XRA A ;ZERO ACCUM 0152 32C10A STA CRCFLG ;TURN ON CRC FLAG ; 0155 3A5D00 CHKOPTN LDA FCB+1 ;GET OPTION (S OR R) 0158 F5 PUSH PSW ;SAVE OPTION ; ;MOVE THE FILENAME FROM FCB2 TO FCB1 ; 0159 CDE409 CALL MOVEFCB ; ;GOBBLE UP GARBAGE CHARS FROM THE LINE ;PRIOR TO RECEIVE OR SEND ; 015C DB80 IN MODDATP 015E DB80 IN MODDATP ; ;JUMP TO APPROPRIATE FUNCTION ; 0160 F1 POP PSW ;GET OPTION IF LOGCAL PUSH PSW ;BUT SAVE IT ENDIF ; 0161 FE53 CPI 'S' ;SEND.. 0163 CABE01 JZ SENDFIL ;..A FILE? ; 0166 FE52 CPI 'R' ;RECEIVE.. CP/M MACRO ASSEM 2.0 #008 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0168 CA0002 JZ RCVFIL ;..A FILE? ; ;INVALID OPTION ; 016B CD2D0A OPTNERR CALL ERXIT ;EXIT W/ERROR 016E 2B2B494E56 DB '++INVALID OPTION ON XMODEM ' 0189 434F4D4D41 DB 'COMMAND++',CR,LF 0194 4D75737420 DB 'Must be S for SEND; R or RC ' 01B0 666F722052 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) CP/M MACRO ASSEM 2.0 #009 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 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 CP/M MACRO ASSEM 2.0 #010 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 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. ; 01BE CDD402 SENDFIL CALL TRAP ;CHECK FOR NO NAME OR AMBIG. NAME 01C1 CD3306 CALL CNREC ;COMPUTE # OF RECORDS. 01C4 CDAB06 CALL OPENFIL ;OPEN THE FILE 01C7 1E50 MVI E,80 ;WAIT 80 SEC.. 01C9 CDC609 CALL WAITNAK ;..FOR INITIAL NAK ; 01CC CD2608 SENDLP CALL RDSECT ;READ A SECTOR 01CF DAF201 JC SENDEOF ;SEND EOF IF DONE 01D2 CD6B05 CALL INCRSNO ;BUMP SECTOR # 01D5 AF XRA A ;ZERO ERROR.. 01D6 32BD0A STA ERRCT ;..COUNT ; 01D9 CDBC04 SENDRPT CALL SENDHDR ;SEND A HEADER 01DC CDCF04 CALL SENDSEC ;SEND DATA SECTOR 01DF 3AC10A LDA CRCFLG ;GET CRC FLAG 01E2 B7 ORA A ;CRC IN EFFECT? 01E3 CCE504 CZ SENDCRC ;YES, SEND CRC 01E6 C4E004 CNZ SENDCKS ;NO, SEND CKSUM 01E9 CDF204 CALL GETACK ;GET THE ACK 01EC DAD901 JC SENDRPT ;REPEAT IF NO ACK 01EF C3CC01 JMP SENDLP ;LOOP UNTIL EOF ; ;FILE SENT, SEND EOT'S ; 01F2 3E04 SENDEOF MVI A,EOT ;SEND.. 01F4 CDA509 CALL SEND ;..AN EOT 01F7 CDF204 CALL GETACK ;GET THE ACK 01FA DAF201 JC SENDEOF ;LOOP IF NO ACK 01FD C32A0A JMP EXITLG ;ALL DONE ; CP/M MACRO ASSEM 2.0 #011 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ * * * * * * * * * * * * * * * * * * * * * * * * 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. ; 0200 CDD402 RCVFIL CALL TRAP ;CHECK FOR NO NAME OR AMBIG. NAME ; IF SETAREA 0203 3E01 MVI A,DEFDRV-40H 0205 325C00 STA FCB ENDIF ; IF NOCOMR 0208 216500 LXI H,FCB+9 ;POINT TO FILETYPE 020B 3E43 MVI A,'C' ;1ST LETTER 020D BE CMP M ;IS IT C ? 020E C25E02 JNZ CONTINU ;IF NOT, CONTINUE NORMALLY 0211 23 INX H ;GET 2ND LETTER 0212 3E4F MVI A,'O' ;2ND LETTER 0214 BE CMP M ;IS IT O ? 0215 C25E02 JNZ CONTINU ;IF NOT, CONTINUE NORMALLY 0218 23 INX H ;GET 3RD LETTER 0219 3E4D MVI A,'M' ;3RD LETTER 021B BE CMP M ;IS IT M ? 021C C25E02 JNZ CONTINU ;IF NOT, CONTINUE NORMALLY 021F CD1B0A CALL ILPRT ; PRINT RENAMING MESSAGE 0222 4175746F20 DB 'Auto Renaming Filetype To ".OBJ" ' 0243 0D0A0D0A00 DB CR,LF,CR,LF,0 ; 0248 215B02 LXI H,OBJEXT 024B 116500 LXI D,FCB+9 024E 0603 MVI B,3 0250 7E ALTEXT MOV A,M 0251 12 STAX D 0252 23 INX H 0253 13 INX D 0254 05 DCR B 0255 C25002 JNZ ALTEXT 0258 C35E02 JMP CONTINU 025B 4F424A OBJEXT DB 'OBJ' ENDIF ; 025E CDB005 CONTINU CALL CHEKFIL ;SEE IF FILE EXISTS 0261 CDE905 CALL MAKEFIL ;..THEN MAKE NEW 0264 CD1B0A CALL ILPRT ;PRINT: ; IF SETAREA 0267 4E4F54453A DB 'NOTE: File Will Be Received On',CR,LF ; A 01/06/81 CP/M MACRO ASSEM 2.0 #012 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0287 4472697665 DB 'Drive ',DEFDRV,' User ',RECU+30H,CR,LF ; TELL THIS .A 01/06/81 ENDIF ; 0297 46494C4520 DB 'FILE OPEN - READY TO RECEIVE',CR,LF,0 ; 02B6 CD3003 RCVLP CALL RCVSECT ;GET A SECTOR 02B9 DAC802 JC RCVEOT ;GOT EOT 02BC CDA408 CALL WRSECT ;WRITE THE SECTOR 02BF CD6B05 CALL INCRSNO ;BUMP SECTOR # 02C2 CDB604 CALL SENDACK ;ACK THE SECTOR 02C5 C3B602 JMP RCVLP ;LOOP UNTIL EOF ; ;GOT EOT ON SECTOR - FLUSH BUFFERS, END ; 02C8 CDBC08 RCVEOT CALL WRBLOCK ;WRITE THE LAST BLOCK 02CB CDB604 CALL SENDACK ;ACK THE SECTOR 02CE CDD307 CALL CLOSFIL ;CLOSE THE FILE 02D1 C32A0A JMP EXITLG ;ALL DONE ; * * * * * * * * * * * * * * * * * * * * * * * * SUBROUTINES * * * * * * * * * * * * * * * * * * * * * * * * ; ;----> TRAP: CHECK FOR NO FILE NAME OR AMBIGUOUS NAME ; 02D4 215D00 TRAP LXI H,FCB+1 ;POINT TO FILE NAME 02D7 7E MOV A,M ;GET FIRST CHAR OF FILE NAME 02D8 FE20 CPI ' ' ;ANY THERE? 02DA C2FD02 JNZ ATRAP ;YES, CHECK FOR AMBIGOUS FILE NAME 02DD CD2D0A CALL ERXIT ;PRINT MSG, EXIT 02E0 2B2B4E4F20 DB '++NO FILE NAME SPECIFIED++',CR,LF,'$' ; 02FD 060B ATRAP MVI B,11 ;11 CHARS TO CHECK ; 02FF 7E TRLOOP MOV A,M ;GET CHAR FROM FCB 0300 FE3F CPI '?' ;AMBIGUOUS? 0302 CA0B03 JZ TRERR ;YES, EXIT WITH ERROR MSG 0305 23 INX H ;POINT TO NEXT CHAR 0306 05 DCR B ;ONE LESS TO GO 0307 C2FF02 JNZ TRLOOP ;NOT DONE, CHECK SOME MORE 030A C9 RET ;NO AMBIGUOUS NAME, RETURN ; 030B CD2D0A TRERR CALL ERXIT ;PRINT MSG, EXIT 030E 2B2B43414E DB '++CAN''T USE WILD CARD OPTIONS++',CR,LF,'$' ; ;----> RCVSECT: RECEIVE A SECTOR ; ;RETURNS WITH CARRY SET IF EOT RECEIVED. ; 0330 AF RCVSECT XRA A ;GET 0 0331 32BD0A STA ERRCT ;INIT ERROR COUNT ; RCVRPT: IF PMMI OR H8 OR DCH CP/M MACRO ASSEM 2.0 #013 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0334 AF XRA A ;GET 0 0335 32C00A STA ERRCDE ;CLEAR RECEIVE ERROR CODE ENDIF ; 0338 060A MVI B,10 ;10 SEC TIMEOUT 033A CD2009 CALL RECV ;GET SOH/EOT 033D DA0E04 JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH 0340 CD1104 CALL RCVERR ;TRANS ERROR? 0343 DA5303 JC RCVSERR ;CARRY SET IF ERROR ENDIF ; 0346 FE01 CPI SOH ;GET SOH? 0348 CA1F04 JZ RCVSOH ;..YES ; ;EARLIER VERSIONS OF MODEM PROGRAM SEND SOME NULLS - ;IGNORE THEM ; 034B B7 ORA A ;00 FROM SPEED CHECK? 034C CA3403 JZ RCVRPT ;YES, IGNORE IT 034F FE04 CPI EOT ;END OF TRANSFER? 0351 37 STC ;RETURN WITH CARRY.. 0352 C8 RZ ;..SET IF EOT ; ;DIDN'T GET SOH OR EOT - ; -OR- ;DIDN'T GET VALID HEADER - PURGE THE LINE, ;THEN SEND NAK. ; 0353 0601 RCVSERR MVI B,1 ;WAIT FOR 1 SEC.. 0355 CD2009 CALL RECV ;..WITH NO CHARS 0358 D25303 JNC RCVSERR ;LOOP UNTIL SENDER DONE 035B 3AC10A LDA CRCFLG ;GET CRC FLAG 035E B7 ORA A ;CRC IN EFFECT? 035F 3E15 MVI A,NAK ;PUT NAK IN ACCUM 0361 C26F03 JNZ RCVSER2 ;NO, SEND THE NAK 0364 3AC20A LDA FIRSTIME;GET FIRST TIME SWITCH 0367 B7 ORA A ;HAS FIRST SOH BEEN RECEIVED? 0368 3E15 MVI A,NAK ;PUT NAK IN ACCUM 036A CA6F03 JZ RCVSER2 ;YES, THEN SEND NAK 036D 3E43 MVI A,CRC ;TELL SENDER CRC IS IN EFFECT ; 036F CDA509 RCVSER2 CALL SEND ;..THE NAK OR CRC REQUEST 0372 3ABD0A LDA ERRCT ;ABORT IF.. 0375 3C INR A ;..WE HAVE REACHED.. 0376 32BD0A STA ERRCT ;..THE ERROR.. 0379 FE0A CPI ERRLIM ;..LIMIT? 037B DA3403 JC RCVRPT ;..NO, TRY AGAIN ; ;10 ERRORS IN A ROW - ; 037E CDD307 RCVSABT CALL CLOSFIL ;KEEP WHATEVER WE GOT 0381 CD1B0A CALL ILPRT 0384 2B2B554E41 DB '++UNABLE TO RECEIVE BLOCK ' 039E 2D2041424F DB '- ABORTING++',CR,LF,0 CP/M MACRO ASSEM 2.0 #014 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 03AD CDDF03 CALL DELFILE ;DELETE RECEIVED FILE ; V48C SMH 03B0 CD1B0A CALL ILPRT ;PRINT SECOND HALF OF MESSAGE 03B3 2B2B494E43 DB '++INCOMPLETELY RECEIVED FILE ' 03D0 44454C4554 DB 'DELETED++',CR,LF,0 03DC C3330A JMP EXIT ;GIVE UP ; ;----> DELFILE: DELETES THE RECEIVED FILE (USED IF RECEIVE ABORTS) ; ; V48C SMH 03DF 115C00 DELFILE LXI D,FCB ;POINT TO FILE ; (WHOLE ROUTINE) 03E2 0E13 MVI C,ERASEF ;GET FUNCTION 03E4 CD0500 CALL BDOS ;DELETE IT 03E7 3C INR A ;DELETE OK? 03E8 C0 RNZ ;..YES, RETURN 03E9 CD2D0A CALL ERXIT ;..NO, ABORT 03EC 2B2B43414E DB '++CAN''T DELETE RECEIVED FILE++',CR,LF,'$',0 ; ;TIMED OUT ON RECEIVE ; 040E C35303 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 0411 F5 RCVERR PUSH PSW ;SAVE CHAR TRANSMITTED 0412 3AC00A LDA ERRCDE ;GET RECEIVE ERR CODE 0415 A7 ANA A ;IS IT ZERO? 0416 CA1C04 JZ RCVERR2 ;YES, NO ERROR 0419 F1 POP PSW ;RESTORE CHAR TRANSMITTED 041A 37 STC ;SET CARRY ON FOR ERROR 041B C9 RET ; 041C F1 RCVERR2 POP PSW ;RESTORE CHAR TRANSMITTED 041D B7 ORA A ;CLEAR CARRY BIT 041E C9 RET ENDIF ; ;GOT SOH - GET BLOCK #, BLOCK # COMPLEMENTED ; 041F AF RCVSOH XRA A ;ZERO ACCUM 0420 32C20A STA FIRSTIME;INDICATE FIRST SOH RECV'D 0423 0601 MVI B,1 ;TIMEOUT = 1 SEC 0425 CD2009 CALL RECV ;GET SECTOR 0428 DA0E04 JC RCVSTOT ;GOT TIMEOUT ; IF PMMI OR H8 OR DCH 042B CD1104 CALL RCVERR ;TRANS ERROR? 042E DA5303 JC RCVSERR ;CARRY SET IF ERROR ENDIF ; 0431 57 MOV D,A ;D=BLK # 0432 0601 MVI B,1 ;TIMEOUT = 1 SEC CP/M MACRO ASSEM 2.0 #015 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0434 CD2009 CALL RECV ;GET CMA'D SECT # 0437 DA0E04 JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH 043A CD1104 CALL RCVERR ;TRANS ERROR? 043D DA5303 JC RCVSERR ;CARRY SET IF ERROR ENDIF ; 0440 2F CMA ;CALC COMPLEMENT 0441 BA CMP D ;GOOD SECTOR #? 0442 CA4804 JZ RCVDATA ;YES, GET DATA ; ;GOT BAD SECTOR # ; 0445 C35303 JMP RCVSERR ;BUMP ERROR CT. ; 0448 7A RCVDATA MOV A,D ;GET SECTOR # 0449 32B90A STA RCVSNO ;SAVE IT 044C 0E00 MVI C,0 ;INIT CKSUM 044E CD670A CALL CLRCRC ;CLEAR CRC COUNTER 0451 218000 LXI H,BASE+80H ;POINT TO BUFFER ; 0454 0601 RCVCHR MVI B,1 ;1 SEC TIMEOUT 0456 CD2009 CALL RECV ;GET CHAR 0459 DA0E04 JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH 045C CD1104 CALL RCVERR ;TRANS ERROR? 045F DA5303 JC RCVSERR ;CARRY SET IF ERROR ENDIF ; 0462 77 MOV M,A ;STORE CHAR 0463 2C INR L ;DONE? 0464 C25404 JNZ RCVCHR ;NO, LOOP 0467 3AC10A LDA CRCFLG ;GET CRC FLAG 046A B7 ORA A ;CRC IN EFFECT? 046B CA9204 JZ RCVCRC ;YES, TO RECEIVE CRC ; ;VERIFY CHECKSUM ; 046E 51 MOV D,C ;SAVE CHECKSUM 046F 0601 MVI B,1 ;TIMEOUT LEN. 0471 CD2009 CALL RECV ;GET CHECKSUM 0474 DA0E04 JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH 0477 CD1104 CALL RCVERR ;TRANS ERROR? 047A DA5303 JC RCVSERR ;CARRY SET IF ERROR ENDIF ; 047D BA CMP D ;CHECKSUM OK? 047E C25303 JNZ RCVSERR ;NO, ERROR ; ;GOT A SECTOR, IT'S A DUPLICATE IF = PREVIOUS, ; OR OK IF = 1 + PREVIOUS SECTOR ; CP/M MACRO ASSEM 2.0 #016 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0481 3AB90A CHKSNUM LDA RCVSNO ;GET RECEIVED 0484 47 MOV B,A ;SAVE IT 0485 3ABA0A LDA SECTNO ;GET PREV 0488 B8 CMP B ;PREV REPEATED? 0489 CAB004 JZ RECVACK ;ACK TO CATCH UP 048C 3C INR A ;CALC NEXT SECTOR # 048D B8 CMP B ;MATCH? 048E C23005 JNZ ABORT ;NO MATCH - STOP SENDER, EXIT 0491 C9 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. ; 0492 1E02 RCVCRC MVI E,2 ;NUMBER OF BYTES TO RECEIVE ; 0494 0601 RCVCRC2 MVI B,1 ;1 SEC TIMEOUT 0496 CD2009 CALL RECV ;GET CRC BYTE 0499 DA0E04 JC RCVSTOT ;TIMEOUT ; IF PMMI OR H8 OR DCH 049C CD1104 CALL RCVERR ;TRANSMISSION ERROR? 049F DA5303 JC RCVSERR ;YES, IF CARRY IS ON ENDIF ; 04A2 1D DCR E ;DECREMENT NUM OF BYTES 04A3 C29404 JNZ RCVCRC2 ;GET BOTH BYTES 04A6 CDA90A CALL CHKCRC ;CHECK RCVD CRC AGAINST CALC'D CRC 04A9 B7 ORA A ;IS CRC OKAY? 04AA CA8104 JZ CHKSNUM ;YES, GO CHECK SECTOR NUMBERS 04AD C35303 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 ; 04B0 CDB604 RECVACK CALL SENDACK ;SEND THE ACK, 04B3 C33003 JMP RCVSECT ;GET NEXT BLOCK ; ;SEND AN ACK FOR THE SECTOR ; 04B6 3E06 SENDACK MVI A,ACK ;GET ACK 04B8 CDA509 CALL SEND ;..AND SEND IT 04BB C9 RET ; ;----> SENDHDR: SEND THE SECTOR HEADER ; ;SEND: (SOH) (BLOCK #) (COMPLEMENTED BLOCK #) ; 04BC 3E01 SENDHDR MVI A,SOH ;SEND.. 04BE CDA509 CALL SEND ;..SOH, 04C1 3ABA0A LDA SECTNO ;THEN SEND.. 04C4 CDA509 CALL SEND ;..SECTOR # 04C7 3ABA0A LDA SECTNO ;THEN SECTOR # CP/M MACRO ASSEM 2.0 #017 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 04CA 2F CMA ;..COMPLEMENTED.. 04CB CDA509 CALL SEND ;..SECTOR # 04CE C9 RET ;FROM SENDHDR ; ;----> SENDSEC: SEND THE DATA SECTOR ; 04CF 0E00 SENDSEC MVI C,0 ;INIT CKSUM 04D1 CD670A CALL CLRCRC ;CLEAR THE CRC COUNTER 04D4 218000 LXI H,BASE+80H ;POINT TO BUFFER ; 04D7 7E SENDC MOV A,M ;GET A CHAR 04D8 CDA509 CALL SEND ;SEND IT 04DB 2C INR L ;POINT TO NEXT CHAR 04DC C2D704 JNZ SENDC ;LOOP IF <100H 04DF C9 RET ;FROM SENDSEC ; ;----> SENDCKS: SEND THE CHECKSUM ; 04E0 79 SENDCKS MOV A,C ;SEND THE.. 04E1 CDA509 CALL SEND ;..CHECKSUM 04E4 C9 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. ; 04E5 CD980A SENDCRC CALL FINCRC ;CALC THE CRC FOR THIS SECTOR 04E8 7A MOV A,D ;PUT FIRST CRC BYTE IN ACCUM 04E9 CDA509 CALL SEND ;SEND IT 04EC 7B MOV A,E ;PUT SECOND CRC BYTE IN ACCUM 04ED CDA509 CALL SEND ;SEND IT 04F0 AF XRA A ;SET ZERO RETURN CODE 04F1 C9 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. ; 04F2 060A GETACK MVI B,10 ;WAIT 10 SECONDS MAX 04F4 CD1C09 CALL RECVDG ;RECV W/GARBAGE COLLECT 04F7 DA2D05 JC GETATOT ;TIMED OUT 04FA FE06 CPI ACK ;OK? (CARRY OFF IF =) 04FC C8 RZ ;YES, RET FROM GETACK ; ;TIMEOUT OR ERROR ON ACK - BUMP ERROR COUNT ; 04FD 3ABD0A ACKERR LDA ERRCT ;GET COUNT 0500 3C INR A ;BUMP IT 0501 32BD0A STA ERRCT ;SAVE BACK 0504 FE0A CPI ERRLIM ;AT LIMIT? CP/M MACRO ASSEM 2.0 #018 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0506 D8 RC ;NOT AT LIMIT ; ;REACHED ERROR LIMIT ; 0507 CD2D0A CSABORT CALL ERXIT 050A 2B2B43414E DB '++CAN''T SEND SECTOR ' 051E 2D2041424F DB '- ABORTING++',CR,LF,'$' ; ;TIMEOUT GETTING ACK ; 052D C3FD04 GETATOT JMP ACKERR ;NO MSG ; 0530 31030B ABORT LXI SP,STACK ; 0533 0601 ABORTL MVI B,1 ;1 SEC. W/O CHARS. 0535 CD2009 CALL RECV 0538 D23305 JNC ABORTL ;LOOP UNTIL SENDER DONE 053B 3E18 MVI A,CAN ;CONTROL X 053D CDA509 CALL SEND ;STOP SENDING END ; 0540 0601 ABORTW MVI B,1 ;1 SEC W/O CHARS. 0542 CD2009 CALL RECV 0545 D24005 JNC ABORTW ;LOOP UNTIL SENDER DONE 0548 3E20 MVI A,' ' ;GET A SPACE... 054A CDA509 CALL SEND ;TO CLEAR OUT CONTROL X 054D CD2D0A CALL ERXIT ;EXIT WITH ABORT MSG 0550 584D4F4445 DB 'XMODEM PROGRAM CANCELLED',CR,LF,'$' ; ;----> INCRSNO: INCREMENT SECTOR # ; 056B 3ABA0A INCRSNO LDA SECTNO ;INCR.. 056E 3C INR A ;..SECT.. 056F 32BA0A STA SECTNO ;..NUMBER 0572 E5 PUSH H 0573 210000 LXI H,VOUT ;CK FOR OPTIONAL COUNT TO CONSOLE 0576 7C MOV A,H 0577 B5 ORA L 0578 C27D05 JNZ CONSEC 057B E1 POP H 057C C9 RET ; 057D 3E0D CONSEC: MVI A,CR 057F CD0000 CALL VOUT 0582 2ABB0A LHLD SECCNT ;UPDATE TOTAL SECTOR COUNT 0585 23 INX H 0586 22BB0A SHLD SECCNT 0589 CD8E05 CALL DECOUTX ;DISPLAY COUNT 058C E1 POP H 058D C9 RET ; 058E C5 DECOUTX PUSH B 058F D5 PUSH D 0590 E5 PUSH H 0591 01F6FF LXI B,-10 0594 11FFFF LXI D,-1 ; CP/M MACRO ASSEM 2.0 #019 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0597 09 DECOU2X DAD B 0598 13 INX D 0599 DA9705 JC DECOU2X 059C 010A00 LXI B,10 059F 09 DAD B 05A0 EB XCHG 05A1 7C MOV A,H 05A2 B5 ORA L 05A3 C48E05 CNZ DECOUTX 05A6 7B MOV A,E 05A7 C630 ADI '0' 05A9 CD0000 CALL VOUT 05AC E1 POP H 05AD D1 POP D 05AE C1 POP B 05AF C9 RET ; ;----> CHEKFIL: SEE IF FILE EXISTS ; ;IF IT EXISTS, SAY USE A DIFFERENT NAME. ; CHEKFIL IF SETAREA 05B0 CD490A CALL RECAREA ;SET THE DESIGNATED AREA UP A 01/06/81 ENDIF ; 05B3 115C00 LXI D,FCB ;POINT TO CTL BLOCK 05B6 0E11 MVI C,SRCHF ;SEE IF IT.. 05B8 CD0500 CALL BDOS ;..EXISTS 05BB 3C INR A ;FOUND? 05BC C8 RZ ;..NO, RETURN 05BD CD2D0A CALL ERXIT ;EXIT, PRINT ERROR MESSAGE 05C0 2B2B46494C DB '++FILE EXISTS - USE A DIFFERENT NAME++' 05E6 0D0A24 DB CR,LF,'$' ; ;----> MAKEFIL: MAKES THE FILE TO BE RECEIVED ; 05E9 AF MAKEFIL XRA A ;SET EXT & REC # TO 0 05EA 326800 STA FCBEXT 05ED 327C00 STA FCBSNO 05F0 115C00 LXI D,FCB ;POINT TO FCB 05F3 0E16 MVI C,MAKE ;GET BDOS FNC 05F5 CD0500 CALL BDOS ;TO THE MAKE 05F8 3C INR A ;FF=BAD? 05F9 C0 RNZ ;OPEN OK ;DIRECTORY FULL - CAN'T MAKE FILE 05FA CD2D0A CALL ERXIT 05FD 2B2B455252 DB '++ERROR - CAN''T MAKE FILE++',CR,LF 061A 4469726563 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 0633 3E3F CNREC MVI A,'?' ;MATCH ALL EXTENTS 0635 326800 STA FCBEXT CP/M MACRO ASSEM 2.0 #020 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0638 3EFF MVI A,0FFH 063A 32B60A STA MAXEXT ;INIT MAX EXT NO. 063D 0E11 MVI C,SRCHF ;GET 'SEARCH FIRST' FNC 063F 115C00 LXI D,FCB 0642 CD0500 CALL BDOS ;READ FIRST 0645 3C INR A ;WERE THERE ANY? 0646 C28206 JNZ SOME ;GOT SOME 0649 CD2D0A CALL ERXIT 064C 2B2B46494C DB '++FILE NOT FOUND++$' ; ;READ MORE DIRECTORY ENTRIES 065F 0E12 MOREDIR MVI C,SRCHN ;SEARCH NEXT 0661 115C00 LXI D,FCB 0664 CD0500 CALL BDOS ;READ DIR ENTRY 0667 3C INR A ;CHECK FOR END (0FFH) 0668 C28206 JNZ SOME ;NOT END OF DIR...PROCESS EXTENT 066B 3AB60A LDA MAXEXT ;HIT END...GET HIGHEST EXTENT NO. SEEN 066E 6F MOV L,A ;WHICH GIVES EXTENT COUNT - 1 066F 2600 MVI H,0 0671 54 MOV D,H 0672 3AB70A LDA RCNT ;GET RECORD COUNT OF MAX EXTENT SEEN 0675 5F MOV E,A ;SAVE IT IN DE 0676 29 DAD H 0677 29 DAD H ;MULTIPLY # OF EXTENTS - 1 0678 29 DAD H ; TIMES 128 0679 29 DAD H 067A 29 DAD H 067B 29 DAD H 067C 29 DAD H 067D 19 DAD D ;ADD IN SIZE OF LAST EXTENT 067E 22B70A SHLD RCNT ;SAVE TOTAL RECORD COUNT 0681 C9 RET ;AND EXIT ; ;POINT TO DIRECTORY ENTRY 0682 3D SOME DCR A ;UNDO PREV 'INR A' 0683 E603 ANI 3 ;MAKE MODULUS 4 0685 87 ADD A ;MULTIPLY... 0686 87 ADD A ;..BY 32 BECAUSE 0687 87 ADD A ;..EACH DIRECTORY 0688 87 ADD A ;..ENTRY IS 32 0689 87 ADD A ;..BYTES LONG 068A 218000 LXI H,BASE+80H ;POINT TO BUFFER 068D 85 ADD L ;POINT TO ENTRY 068E C60F ADI 15 ;OFFSET TO RECORD COUNT 0690 6F MOV L,A ;HL NOW POINTS TO REC COUNT 0691 46 MOV B,M ;GET RECORD COUNT 0692 2B DCX H 0693 2B DCX H ;BACK DOWN TO EXTENT NUMBER 0694 2B DCX H 0695 3AB60A LDA MAXEXT ;COMPARE WITH CURRENT MAX. 0698 B7 ORA A ;IF NO MAX YET 0699 FAA006 JM BIGGER ;THEN SAVE RECORD COUNT ANYWAY 069C BE CMP M 069D D25F06 JNC MOREDIR ; 06A0 78 BIGGER: MOV A,B ;SAVE NEW RECORD COUNT CP/M MACRO ASSEM 2.0 #021 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 06A1 32B70A STA RCNT 06A4 7E MOV A,M ;SAVE NEW MAX. EXTENT NO. 06A5 32B60A STA MAXEXT 06A8 C35F06 JMP MOREDIR ;GO FIND MORE EXTENTS ; ;----> OPENFIL: OPENS THE FILE TO BE SENT ; 06AB AF OPENFIL XRA A ;SET EXT & REC # TO 0 FOR PROPER OPEN 06AC 326800 STA FCBEXT 06AF 327C00 STA FCBSNO 06B2 115C00 LXI D,FCB ;POINT TO FILE 06B5 0E0F MVI C,OPEN ;GET FUNCTION 06B7 CD0500 CALL BDOS ;OPEN IT 06BA 3C INR A ;OPEN OK? 06BB C2D206 JNZ OPENOK ;..YES 06BE CD2D0A CALL ERXIT ;..NO, ABORT 06C1 2B2B4F5045 DB '++OPEN ERROR++',CR,LF,'$' ; ;CHECK FOR DISTRIBUTION-PROTECTED FILE ; 06D2 3A5D00 OPENOK LDA FCB+1 ;FIRST CHAR OF FILE NAME 06D5 E680 ANI 80H ;CHECK BIT 7 06D7 C2E206 JNZ OPENOT ;IF ON, FILE CAN'T BE SENT. 06DA 3A5E00 LDA FCB+2 ;ALSO CHECK "F2" FOR TAG. 06DD E680 ANI 80H ;IS IT SET? 06DF CA1407 JZ OPENOK2 ;IF NOT, OK TO SEND FILE. ; 06E2 CD2D0A OPENOT CALL ERXIT ;EXIT W/MESSAGE 06E5 2B2B544849 DB '++THIS FILE IS NOT FOR DISTRIBUTION, SORRY++' 0711 0D0A24 DB CR,LF,'$' ; 0714 = OPENOK2 EQU $ ; IF NOLBS OR NOCOMS ;CHECK FOR SEND RESTRICTIONS 0714 216700 LXI H,FCB+11 0717 7E MOV A,M ;CHECK FOR PROTECT ATTR 0718 E67F ANI 7FH ;REMOVE CP/M 2.X ATTRS ENDIF ;NOLBS OR NOCOMS ; IF NOLBS ;DON'T ALLOW '#' TO BE SENT. 071A FE23 CPI '#' ;CHK FOR '#' AS LAST FIRST 071C CAE206 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'? CP/M MACRO ASSEM 2.0 #022 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ JNZ OPENOK3 ;IF NOT, CONTINUE CALL ERXIT ;EXIT W/MESSAGE DB '++CAN''T SEND A .COM FILE++' DB CR,LF,'$' ENDIF ;NOCOMS ; 071F CD1B0A OPENOK3 CALL ILPRT ;PRINT: 0722 46696C6520 DB 'File Open - ',0 ; V48B BHK 0730 2AB70A LHLD RCNT ; GET RECORD COUNT. 0733 CDF707 CALL DECOUT ;PRINT DECIMAL NUMBER OF SECTORS 0736 CD1B0A CALL ILPRT 0739 202800 DB ' (',0 073C CD1908 CALL DHXOUT ;NOW PRINT SIZE IN HEX. 073F CD1B0A CALL ILPRT 0742 2048657829 DB ' Hex) Sectors',CR,LF ; V48B BHK 0751 2861707072 DB '(approximately ',0 ; V48B BHK 0761 2AB70A 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 0764 CDBC07 CALL DIVHL14 ; DIVIDE HL BY 14 (SECTORS/MIN) ; V48B BHK 0767 E5 PUSH H IF LOGCAL SHLD PGSIZE ; V50 JPR ENDIF 0768 2600 MVI H,0 076A CDF707 CALL DECOUT ; PRINT DECIMAL # OF MINUTES ; V48B BHK 076D CD1B0A CALL ILPRT ; V48B BHK 0770 206D696E73 DB ' mins, ',0 0778 E1 POP H 0779 7C MOV A,H ;REMAINDER X 4 = SECONDS 077A 07 RLC 077B 07 RLC 077C 6F MOV L,A 077D 2600 MVI H,0 077F CDF707 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 CP/M MACRO ASSEM 2.0 #023 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ MS300 ENDIF 0782 CD1B0A CALL ILPRT 0785 2073656373 DB ' secs to send at 300 baud).',CR,LF ; V48B BHK 07A2 5B436F6E74 DB '[Control-X to cancel.]',CR,LF,0 ; V48C BHK 07BB C9 RET ; ;----> DIVHL14: DIVIDES HL BY 14, ; UPON EXIT: L=QUOTIENT,H=REMAINDER ; 07BC C5 DIVHL14 PUSH B 07BD 0608 MVI B,8 ;SHIFT FACTOR TO B 07BF 0E0E MVI C,14 ;DIVISOR TO C 07C1 AF DIV2 XRA A ; CLEAR CARRY FLAG AND ACCUMULATOR 07C2 29 DAD H 07C3 7C MOV A,H 07C4 91 SUB C 07C5 FACD07 JM DIV3 ;DONT BORROW ON NEG RESULTS 07C8 67 MOV H,A 07C9 7D MOV A,L 07CA F601 ORI 1 ;BORROW 1 07CC 6F MOV L,A 07CD 05 DIV3 DCR B 07CE C2C107 JNZ DIV2 07D1 C1 POP B 07D2 C9 RET ; ;----> CLOSFIL: CLOSES THE RECEIVED FILE ; 07D3 115C00 CLOSFIL LXI D,FCB ;POINT TO FILE 07D6 0E10 MVI C,CLOSE ;GET FUNCTION 07D8 CD0500 CALL BDOS ;CLOSE IT 07DB 3C INR A ;CLOSE OK? 07DC C0 RNZ ;..YES, RETURN 07DD CD2D0A CALL ERXIT ;..NO, ABORT 07E0 2B2B43414E DB '++CAN''T CLOSE FILE++',CR,LF,'$' ; ; ;----> DECOUT: DECIMAL OUTPUT ROUTINE ; 07F7 C5 DECOUT: PUSH B 07F8 D5 PUSH D 07F9 E5 PUSH H 07FA 01F6FF LXI B,-10 07FD 11FFFF LXI D,-1 ; 0800 09 DECOU2: DAD B 0801 13 INX D 0802 DA0008 JC DECOU2 0805 010A00 LXI B,10 0808 09 DAD B 0809 EB XCHG 080A 7C MOV A,H 080B B5 ORA L 080C C4F707 CNZ DECOUT 080F 7B MOV A,E CP/M MACRO ASSEM 2.0 #024 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0810 C630 ADI '0' 0812 CDF709 CALL CTYPE 0815 E1 POP H 0816 D1 POP D 0817 C1 POP B 0818 C9 RET ; ;----> DHXOUT: - DOUBLE PRECISION HEX OUTPUT ROUTINE. ; CALL WITH HEX VALUE IN HL. ; 0819 E5 DHXOUT PUSH H ;SAVE H,L 081A F5 PUSH PSW ;SAVE A 081B 7C MOV A,H ;GET MS BYTE. 081C CD040A CALL HEXO ;OUTPUT HI ORDER BYTE. 081F 7D MOV A,L ;GET LS BYTE. 0820 CD040A CALL HEXO ;OUTPUT LO ORDER BYTE. 0823 F1 POP PSW ;RESTORE A 0824 E1 POP H ;RESTORE H,L 0825 C9 RET ;RETURN TO CALLER. ; ; ;----> RDSECT: READS A SECTOR ; ;FOR SPEED, THIS ROUTINE BUFFERS UP 16 ;SECTORS AT A TIME. ; 0826 3AC60A RDSECT LDA SECINBF ;GET # SECT IN BUFF. 0829 3D DCR A ;DECREMENT.. 082A 32C60A STA SECINBF ;..IT 082D FA3D08 JM RDBLOCK ;EXHAUSTED? NEED MORE. 0830 2AC40A LHLD SECPTR ;GET POINTER 0833 118000 LXI D,BASE+80H ;TO DATA 0836 CD5C0A CALL MOVE128 ;MOVE TO BUFFER 0839 22C40A SHLD SECPTR ;SAVE BUFFER POINTER 083C C9 RET ;FROM "READSEC" ; ;BUFFER IS EMPTY - READ IN ANOTHER BLOCK OF 16 ; 083D 3AC30A RDBLOCK LDA EOFLG ;GED EOF FLAG 0840 FE01 CPI 1 ;IS IT SET? 0842 37 STC ;TO SHOW EOF 0843 C8 RZ ;GOT EOF 0844 0E00 MVI C,0 ;SECTORS IN BLOCK 0846 11050B LXI D,DBUF ;TO DISK BUFFER ; 0849 C5 RDSECLP PUSH B 084A D5 PUSH D 084B 0E1A MVI C,STDMA ;SET DMA.. 084D CD0500 CALL BDOS ;..ADDR 0850 115C00 LXI D,FCB 0853 0E14 MVI C,READ 0855 CD0500 CALL BDOS 0858 D1 POP D 0859 C1 POP B 085A B7 ORA A ;READ OK? 085B CA7B08 JZ RDSECOK ;YES CP/M MACRO ASSEM 2.0 #025 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 085E 3D DCR A ;EOF? 085F CA8A08 JZ REOF ;GOT EOF ; ;READ ERROR ; 0862 CD2D0A CALL ERXIT 0865 2B2B46494C DB '++FILE READ ERROR++',CR,LF,'$' ; 087B 218000 RDSECOK LXI H,80H ;ADD LENGTH OF ONE SECTOR... 087E 19 DAD D ;...TO NEXT BUFF 087F EB XCHG ;BUFF TO DE 0880 0C INR C ;MORE SECTORS? 0881 79 MOV A,C ;GET COUNT 0882 FE10 CPI 16 ;DONE? 0884 CA9008 JZ RDBFULL ;..YES, BUFF IS FULL 0887 C34908 JMP RDSECLP ;READ MORE ; 088A 3E01 REOF MVI A,1 088C 32C30A STA EOFLG ;SET EOF FLAG 088F 79 MOV A,C ; ;BUFFER IS FULL, OR GOT EOF ; 0890 32C60A RDBFULL STA SECINBF ;STORE SECTOR COUNT 0893 21050B LXI H,DBUF ;INIT BUFFER.. 0896 22C40A SHLD SECPTR ;..POINTER 0899 118000 LXI D,BASE+80H ;RESET.. 089C 0E1A MVI C,STDMA ;..DMA.. 089E CD0500 CALL BDOS ;..ADDR 08A1 C32608 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. ; 08A4 2AC40A WRSECT LHLD SECPTR ;GET BUFF ADDR 08A7 EB XCHG ;TO DE FOR MOVE 08A8 218000 LXI H,BASE+80H ;FROM HERE 08AB CD5C0A CALL MOVE128 ;MOVE TO BUFFER 08AE EB XCHG ;SAVE NEXT.. 08AF 22C40A SHLD SECPTR ;..BLOCK POINTER 08B2 3AC60A LDA SECINBF ;BUMP THE.. 08B5 3C INR A ;..SECTOR #.. 08B6 32C60A STA SECINBF ;..IN THE BUFF 08B9 FE10 CPI 16 ;HAVE WE 16? 08BB C0 RNZ ;NO, RETURN ; ;----> WRBLOCK: WRITES A BLOCK TO DISK ; 08BC 3AC60A WRBLOCK LDA SECINBF ;# SECT IN BUFFER 08BF B7 ORA A ;0 MEANS END OF FILE 08C0 C8 RZ ;NONE TO WRITE 08C1 4F MOV C,A ;SAVE COUNT CP/M MACRO ASSEM 2.0 #026 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 08C2 11050B LXI D,DBUF ;POINT TO DISK BUFF ; 08C5 E5 DKWRLP PUSH H 08C6 D5 PUSH D 08C7 C5 PUSH B 08C8 0E1A MVI C,STDMA ;SET DMA 08CA CD0500 CALL BDOS ;TO BUFFER 08CD 115C00 LXI D,FCB ;THEN WRITE 08D0 0E15 MVI C,WRITE ;..THE.. 08D2 CD0500 CALL BDOS ;..BLOCK 08D5 C1 POP B 08D6 D1 POP D 08D7 E1 POP H 08D8 B7 ORA A 08D9 C2F808 JNZ WRERR ;OOPS, ERROR 08DC 218000 LXI H,80H ;LENGTH OF 1 SECT 08DF 19 DAD D ;HL= NEXT BUFF 08E0 EB XCHG ;TO DE FOR SETDMA 08E1 0D DCR C ;MORE SECTORS? 08E2 C2C508 JNZ DKWRLP ;..YES, LOOP 08E5 AF XRA A ;GET A ZERO 08E6 32C60A STA SECINBF ;RESET # OF SECTORS 08E9 21050B LXI H,DBUF ;RESET BUFFER.. 08EC 22C40A SHLD SECPTR ;..POINTER ; 08EF 118000 RSDMA LXI D,BASE+80H ;RESET.. 08F2 0E1A MVI C,STDMA ;..DMA.. 08F4 CD0500 CALL BDOS ;..ADDR 08F7 C9 RET ; 08F8 CDEF08 WRERR CALL RSDMA ;RESET DMA TO NORM. 08FB 0E18 MVI C,CAN ;CANCEL.. 08FD CDA509 CALL SEND ;..SENDER 0900 CD2D0A CALL ERXIT ;EXIT W/MSG: 0903 2B2B455252 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. ; 091C = RECVDG EQU $ ;RECEIVE W/GARBAGE DELETE 091C DB80 IN MODDATP ;GET A CHAR 091E DB80 IN MODDATP ;..TOTALLY PURGE UART ; 0920 D5 RECV PUSH D ;SAVE ; IF FASTCLK ;4MHZ? 0921 78 MOV A,B ;GET TIME REQUEST 0922 87 ADD A ;DOUBLE IT 0923 47 MOV B,A ;NEW TIME IN B ENDIF CP/M MACRO ASSEM 2.0 #027 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; 0924 1150C3 MSEC LXI D,50000 ;1 SEC DCR COUNT ; IF NOT DCH MWTI IN MODCTLP ;CHECK STATUS ENDIF ; IF DCH 0927 DB81 MWTI IN MODCTL2 ;CHECK STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ON PANEL LIGHTS ENDIF ; 0929 E601 ANI MODRCVB ;ISOLATE BIT 092B FE01 CPI MODRCVR ;READY? 092D CA4809 JZ MCHAR ;GOT CHAR 0930 1D DCR E ;COUNT.. 0931 C22709 JNZ MWTI ;..DOWN.. 0934 15 DCR D ;..FOR.. 0935 C22709 JNZ MWTI ;..TIMEOUT 0938 05 DCR B ;MORE SECONDS? 0939 C22409 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 093C DB81 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 ; 093E E640 ANI MODDCDB ;CARRIER DETECT MASK 0940 FE40 CPI MODDCDA ;IS IT STILL ON? 0942 C48609 CNZ CARCK ;IF NOT, TEST FOR 15 SECONDS ; ;MODEM TIMED OUT RECEIVING - BUT CARRIER STILL ON. ; 0945 D1 POP D ;RESTORE D,E 0946 37 STC ;CARRY SHOWS TIMEOUT 0947 C9 RET ; ;GOT CHARACTER FROM MODEM ; MCHAR: ;CHECK TO SEE IF THERE WAS A FRAMING ERROR, ;OVERRUN, OR PARITY ERROR. CP/M MACRO ASSEM 2.0 #028 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; IF PMMI OR H8 IN MODCTLP ;GET MODEM STATUS ENDIF ; IF DCH 0948 DB81 IN MODCTL2 ;GET MODEM STATUS ENDIF ; IF PMMI OR H8 OR DCH 094A 57 MOV D,A ;SAVE STATUS 094B E608 ANI MODFRME ;FRAMING ERROR? 094D FE08 CPI MODFRME 094F C25A09 JNZ MCHAR2 ;NO, CHECK FOR OVERRUN 0952 3AC00A LDA ERRCDE ;GET RECV ERR CODE 0955 F608 ORI MODFRME ;TURN ON RECV ERR CODE 0957 32C00A STA ERRCDE ;PUT IT BACK ; 095A 7A MCHAR2: MOV A,D ;RESTORE MODEM STATUS 095B E610 ANI MODOVRE ;OVERRUN? 095D FE10 CPI MODOVRE 095F C26A09 JNZ MCHAR3 ;NO, CHECK FOR PARITY ERROR 0962 3AC00A LDA ERRCDE 0965 F610 ORI MODOVRE ;TURN ON RECV ERR CODE 0967 32C00A STA ERRCDE ; 096A 7A MCHAR3: MOV A,D ;RESTORE MODEM STATUS 096B E604 ANI MODPARE ;PARITY ERROR? 096D FE04 CPI MODPARE 096F C27A09 JNZ MCHAR4 ;NO, GET DATA CHAR 0972 3AC00A LDA ERRCDE 0975 F604 ORI MODPARE 0977 32C00A STA ERRCDE ; MCHAR4: ENDIF ;PMMI OR H8 OR DCH ; ;GET DATA CHAR ; 097A DB80 IN MODDATP ;READ THE CHAR 097C D1 POP D ;RESTORE DE ; ;CALC CHECKSUM AND CRC ; 097D F5 PUSH PSW ;SAVE THE CHAR 097E CD700A CALL UPDCRC ;CALC CRC 0981 81 ADD C ;ADD TO CHECKSUM 0982 4F MOV C,A ;SAVE CHECKSUM 0983 F1 POP PSW ;RESTORE CHAR 0984 B7 ORA A ;CARRY OFF: NO ERROR 0985 C9 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. CP/M MACRO ASSEM 2.0 #029 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; 0986 1E96 CARCK MVI E,150 ;VALUE FOR 15 SECOND DELAY ; 0988 CD9909 CARCK1 CALL DELAY ;KILL .1 SECONDS ; IF EXTMOD OR H8 OR DCH 098B DB81 IN MODCTL2 ;READ MODEM STATUS ENDIF ; IF PMMI IN BAUDRP ;READ MODEM STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ENDIF ; 098D E640 ANI MODDCDB ;CARRIER DETECT MASK 098F FE40 CPI MODDCDA ;IS IT STILL ON? 0991 C8 RZ ;RETURN IF CARRIER ON 0992 1D DCR E ;HAS 15 SECONDS EXPIRED? 0993 C28809 JNZ CARCK1 ;IF NOT, CONTINUE TESTING 0996 C3330A JMP EXIT ;ELSE, ABORT TO CP/M. ; ;DELAY - 100 MILLISECOND DELAY. ; 0999 C5 DELAY PUSH B ;SAVE B,C ; IF FASTCLK ;IF 4MHZ CLOCK 099A 011B41 LXI B,16667 ;VALUE FOR 100MS DELAY ENDIF ; IF NOT FASTCLK LXI B,8334 ;VALUE FOR 100MS DELAY ENDIF ; 099D 0B DELAY2 DCX B ;UPDATE COUNT 099E 78 MOV A,B ;GET MS BYTE 099F B1 ORA C ;COUNT = ZERO? 09A0 C29D09 JNZ DELAY2 ;IF NOT, CONTINUE 09A3 C1 POP B ;RESTORE B,C 09A4 C9 RET ;RETURN TO CARCK1. ; ;----> SEND: SEND A CHARACTER TO THE MODEM ; 09A5 F5 SEND PUSH PSW ;SAVE THE CHARACTER 09A6 CD700A CALL UPDCRC ;CALC THE CRC 09A9 81 ADD C ;CALC CKSUM 09AA 4F MOV C,A ;SAVE CKSUM ; IF NOT DCH SENDW IN MODCTLP ;GET STATUS ENDIF ; IF DCH 09AB DB81 SENDW IN MODCTL2 ;GET STATUS CP/M MACRO ASSEM 2.0 #030 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ENDIF ; 09AD E602 ANI MODSNDB ;ISOLATE READY BIT 09AF FE02 CPI MODSNDR ;READY? 09B1 CAC209 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. ; 09B4 D5 PUSH D ;SAVE D,E ; IF EXTMOD OR H8 OR DCH 09B5 DB81 IN MODCTL2 ;READ MODEM STATUS ENDIF ; IF PMMI IN BAUDRP ;READ MODEM STATUS ENDIF ; IF PMMI AND FRNTPNL OUT PANEL ;DISPLAY STATUS ENDIF ; 09B7 E640 ANI MODDCDB ;CARRIER DETECT MASK 09B9 FE40 CPI MODDCDA ;IS IT STILL ON? 09BB C48609 CNZ CARCK ;IF NOT, CONTINUE TESTING IT 09BE D1 POP D ;RESTORE D,E 09BF C3AB09 JMP SENDW ;ELSE, WAIT FOR XMIT READY. ; ;XMIT STATUS READY, CARRIER STILL ON - SEND THE DATA. ; 09C2 F1 SENDR POP PSW ;GET CHAR 09C3 D380 OUT MODDATP ;OUTPUT IT 09C5 C9 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 ; 09C6 0601 WAITNAK MVI B,1 ;TIMEOUT DELAY CP/M MACRO ASSEM 2.0 #031 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 09C8 CD2009 CALL RECV ;DID WE GET.. 09CB FE15 CPI NAK ;..A NAK? 09CD C8 RZ ;YES, SEND BLOCK 09CE FE43 CPI CRC ;CRC INDICATED? 09D0 CADF09 JZ WAITCRC ;YES, GO PUT CRC IN EFFECT 09D3 FE18 CPI CAN ;WAS IT A CANCEL (CONTROL-X)? ; V48C BHK 09D5 CA3005 JZ ABORT ;YES, ABORT ; V48C BHK 09D8 1D DCR E ;80 TRIES? 09D9 CA3005 JZ ABORT ;YES, ABORT 09DC C3C609 JMP WAITNAK ;NO, LOOP ; ;----> WAITCRC: TURN ON CRC FLAG ; 09DF AF WAITCRC XRA A ;ZERO ACCUM 09E0 32C10A STA CRCFLG ;TURN ON CRC OPT 09E3 C9 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. ; 09E4 216C00 MOVEFCB LXI H,FCB+16 ;FROM 09E7 115C00 LXI D,FCB ;TO 09EA 0610 MVI B,16 ;LEN 09EC CD5E0A CALL MOVE ;DO THE MOVE 09EF AF XRA A ;GET 0 09F0 327C00 STA FCBSNO ;ZERO SECTOR # 09F3 326800 STA FCBEXT ;..AND EXTENT 09F6 C9 RET ; 09F7 C5 CTYPE PUSH B ;SAVE.. 09F8 D5 PUSH D ;..ALL.. 09F9 E5 PUSH H ;..REGS 09FA 5F MOV E,A ;CHAR TO E 09FB 0E02 MVI C,WRCON ;GET BDOS FNC 09FD CD0500 CALL BDOS ;PRIN THE CHR 0A00 E1 POP H ;RESTORE.. 0A01 D1 POP D ;..ALL.. 0A02 C1 POP B ;..REGS 0A03 C9 RET ;FROM "CTYPE" ; 0A04 F5 HEXO PUSH PSW ;SAVE FOR RIGHT DIGIT 0A05 1F RAR ;RIGHT.. 0A06 1F RAR ;..JUSTIFY.. 0A07 1F RAR ;..LEFT.. 0A08 1F RAR ;..DIGIT.. 0A09 CD0D0A CALL NIBBL ;PRINT LEFT DIGIT 0A0C F1 POP PSW ;RESTORE RIGHT ; 0A0D E60F NIBBL ANI 0FH ;ISOLATE DIGIT 0A0F FE0A CPI 10 ;IS IT <10? 0A11 DA160A JC ISNUM ;YES, NOT ALPHA CP/M MACRO ASSEM 2.0 #032 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0A14 C607 ADI 7 ;ADD ALPHA BIAS ; 0A16 C630 ISNUM ADI '0' ;MAKE PRINTABLE 0A18 C3F709 JMP CTYPE ;..THEN TYPE IT ; ;----> ILPRT: INLINE PRINT OF MESSAGE ; ;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE, ;BINARY 0 AS THE END. ; 0A1B E3 ILPRT XTHL ;SAVE HL, GET HL=MSG ; 0A1C 7E ILPLP MOV A,M ;GET CHAR 0A1D B7 ORA A ;END OF MSG? 0A1E CA280A JZ ILPRET ;..YES, RETURN 0A21 CDF709 CALL CTYPE ;TYPE THE MSG 0A24 23 INX H ;TO NEXT CHAR 0A25 C31C0A JMP ILPLP ;LOOP ; 0A28 E3 ILPRET XTHL ;RESTORE HL 0A29 C9 RET ;PAST MSG ; EXITLG ; SPECIAL LOG CALLER EXIT IF LOGCAL JMP LOGCALL ENDIF 0A2A C3330A JMP EXIT ; ;----> ERXIT: EXIT PRINTING MESSAGE FOLLOWING CALL ; 0A2D D1 ERXIT POP D ;GET MESSAGE 0A2E 0E09 MVI C,PRINT ;GET BDOS FNC 0A30 CD0500 CALL BDOS ;PRINT MESSAGE ; 0A33 2A030B EXIT LHLD STACK ;GET ORIGINAL STACK 0A36 F9 SPHL ;RESTORE IT ; IF SETAREA 0A37 CD3B0A CALL RESTU ; RESTORE OLD AREA USER & DRIVE ..A 01/06/81 ENDIF ; 0A3A C9 RET ;--EXIT-- TO CP/M ; IF SETAREA ; ;------> RESTORE THE OLD USER AREA AND DRIVE FROM A RECEIVED FILE ; 0A3B 3ABF0A RESTU LDA OLDDRV ;RESTORE THE OLD DRIVE ;A 01/06/81 0A3E 5F MOV E,A ;A 01/06/81 0A3F CD560A CALL RECDRX ;A 01/06/81 0A42 3ABE0A LDA OLDUSER ;RESTORE THE OLD USER NUMBER ;A 01/06/81 0A45 5F MOV E,A ;A 01/06/81 0A46 C34E0A JMP RECARE ;A 01/06/81 ; ;--------> SET USER AREA TO RECEIVE FILE 0A49 CD540A RECAREA CALL RECDRV ;OK SET THE DRIVE TO ITS PLACE ;A 01/06/81 CP/M MACRO ASSEM 2.0 #033 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0A4C 1E00 MVI E,RECU ;OK NOW SET THE USER AREA ;A 01/06/81 0A4E 0E20 RECARE MVI C,USER ;TELL BDOS WHAT WE WANT TO DO ;A 01/06/81 0A50 CD0500 CALL BDOS ;DO IT ;A 01/06/81 0A53 C9 RET ; 0A54 1E00 RECDRV MVI E,DEFDRV-41H ;MAKE DRIVE CP/M NUMBER ;A 01/06/81 0A56 0E0E RECDRX MVI C,SELDRV ;TELL BDOS ;A 01/06/81 0A58 CD0500 CALL BDOS ;DO IT ;A 01/06/81 0A5B C9 RET ;BACK ;A 01/06/81 ENDIF ; ;MOVE 128 CHARACTERS ; 0A5C 0680 MOVE128 MVI B,128 ;SET MOVE COUNT ; ;MOVE FROM (HL) TO (DE) LENGTH IN (B) ; 0A5E 7E MOVE MOV A,M ;GET A CHAR 0A5F 12 STAX D ;STORE IT 0A60 23 INX H ;TO NEXT "FROM" 0A61 13 INX D ;TO NEXT "TO" 0A62 05 DCR B ;MORE? 0A63 C25E0A JNZ MOVE ;..YES, LOOP 0A66 C9 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 * CP/M MACRO ASSEM 2.0 #034 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ;* 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 ; 0A67 = CLRCRC: EQU $ ; RESET CRC ACCUMULATOR FOR A NEW MESSAGE. 0A67 E5 PUSH H 0A68 210000 LXI H,0 0A6B 22B40A SHLD CRCVAL 0A6E E1 POP H 0A6F C9 RET ; 0A70 = UPDCRC: EQU $ ; UPDATE CRC ACCUMULATOR USING BYTE IN (A). 0A70 F5 PUSH PSW CP/M MACRO ASSEM 2.0 #035 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ 0A71 C5 PUSH B 0A72 E5 PUSH H 0A73 0608 MVI B,8 0A75 4F MOV C,A 0A76 2AB40A LHLD CRCVAL 0A79 79 UPDLOOP:MOV A,C 0A7A 07 RLC 0A7B 4F MOV C,A 0A7C 7D MOV A,L 0A7D 17 RAL 0A7E 6F MOV L,A 0A7F 7C MOV A,H 0A80 17 RAL 0A81 67 MOV H,A 0A82 D28D0A JNC SKIPIT 0A85 7C MOV A,H ; THE GENERATOR IS X^16 + X^12 + X^5 + 1 0A86 EE10 XRI 10H ; AS RECOMMENDED BY CCITT. 0A88 67 MOV H,A ; AN ALTERNATE GENERATOR WHICH IS OFTEN 0A89 7D MOV A,L ; USED IN SYNCHRONOUS TRANSMISSION PROTOCOLS 0A8A EE21 XRI 21H ; IS X^16 + X^15 + X^2 + 1. THIS MAY BE 0A8C 6F MOV L,A ; USED BY SUBSTITUTING XOR 80H FOR XOR 10H 0A8D 05 SKIPIT: DCR B ; AND XOR 05H FOR XOR 21H IN THE ADJACENT CODE. 0A8E C2790A JNZ UPDLOOP 0A91 22B40A SHLD CRCVAL 0A94 E1 POP H 0A95 C1 POP B 0A96 F1 POP PSW 0A97 C9 RET ; 0A98 = FINCRC: EQU $ ; FINISH CRC CALC FOR OUTBOUND MESSAGE. 0A98 F5 PUSH PSW 0A99 AF XRA A 0A9A CD700A CALL UPDCRC 0A9D CD700A CALL UPDCRC 0AA0 E5 PUSH H 0AA1 2AB40A LHLD CRCVAL 0AA4 54 MOV D,H 0AA5 5D MOV E,L 0AA6 E1 POP H 0AA7 F1 POP PSW 0AA8 C9 RET ; 0AA9 = CHKCRC: EQU $ ; CHECK CRC BYTES OF RECEIVED MESSAGE. 0AA9 E5 PUSH H 0AAA 2AB40A LHLD CRCVAL 0AAD 7C MOV A,H 0AAE B5 ORA L 0AAF E1 POP H 0AB0 C8 RZ 0AB1 3EFF MVI A,0FFH 0AB3 C9 RET ; ; 0AB4 0000 CRCVAL DW 0 ; ; CP/M MACRO ASSEM 2.0 #036 XMODEM.ASM V5.0, by Keith Petersen, W8SDZ ; ;TEMPORARY STORAGE AREA ; 0AB6 00 MAXEXT DB 0 ;HIGHEST EXTENT NO. SEEN IN FILE SIZE CALC. 0AB7 0000 RCNT DW 0 ;RECORD COUNT 0AB9 00 RCVSNO DB 0 ;SECT # RECEIVED 0ABA 00 SECTNO DB 0 ;CURRENT SECTOR NUMBER 0ABB 0000 SECCNT DW 0 ;TOTAL SECTOR COUNT 0ABD 00 ERRCT DB 0 ;ERROR COUNT 0ABE 00 OLDUSER DB 0 ;SAVE THE ORG USER NUMBER 0ABF 00 OLDDRV DB 0 ;SAVE THE ORG DRIVE NUMBER ; IF PMMI OR H8 OR DCH 0AC0 00 ERRCDE DB 0 ;RECEIVE ERROR CODE ENDIF ; 0AC1 43 CRCFLG DB 'C' ;SET TO NULL IF CRC USED 0AC2 01 FIRSTIME DB 1 ;TURNED OFF AFTER FIRST SOH RECEIVED ; ;FOLLOWING 3 USED BY DISK BUFFERING ROUTINES 0AC3 00 EOFLG DB 0 ;EOF FLAG (1=TRUE) 0AC4 050B SECPTR DW DBUF 0AC6 00 SECINBF DB 0 ;# OF SECTORS IN BUFFER 0AC7 DS 60 ;STACK AREA 0B03 STACK DS 2 ;STACK POINTER ; ;16 SECTOR DISK BUFFER ; 0B05 = DBUF EQU $ ;16 SECTOR DISK BUFFER ; ;BDOS EQUATES ; 0001 = RDCON EQU 1 0002 = WRCON EQU 2 0009 = PRINT EQU 9 000B = CONST EQU 11 ;CONSOLE STAT 000E = SELDRV EQU 14 ;SELECT DRIVE 000F = OPEN EQU 15 ;0FFH = NOT FOUND 0010 = CLOSE EQU 16 ; " " 0011 = SRCHF EQU 17 ; " " 0012 = SRCHN EQU 18 ; " " 0013 = ERASEF EQU 19 ;NO RET CODE 0014 = READ EQU 20 ;0=OK, 1=EOF 0015 = WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC 0016 = MAKE EQU 22 ;0FFH=BAD 0017 = REN EQU 23 ;0FFH=BAD 0019 = CURDRV EQU 25 ;GET CURRENT DRIVE 001A = STDMA EQU 26 ;SET DMA 0020 = USER EQU 32 ;SET USER AREA TO RECEIVE FILE 0005 = BDOS EQU BASE+5 005C = FCB EQU BASE+5CH ;SYSTEM FCB 0068 = FCBEXT EQU FCB+12 ;FILE EXTENT 007C = FCBSNO EQU FCB+32 ;SECTOR # 006C = FCB2 EQU BASE+6CH ;SECOND FCB ; 0B05 END