; FILE ROUTINES ; OUTPUT THE CHARS IN A PACKET. PTCHR: LD (TEMP1),A ; SAVE THE SIZE. LD HL,DATA ; BEGINNING OF RECEIVED PACKET DATA. LD (OUTPNT),HL ; REMEMBER WHERE WE ARE. LD A,(RQUOTE) LD B,A ; KEEP THE QUOTE CHAR IN B. PTCHR1: LD HL,TEMP1 DEC (HL) ; DECREMENT # OF CHARS IN PACKET. JP M,RSKP ; RETURN SUCCESSFULLY IF DONE. PTCHR2: LD HL,(OUTPNT) ; GET POSITION IN OUTPUT BUFFER. LD A,(HL) ; GRAB A CHAR. INC HL LD (OUTPNT),HL ; AND BUMP POINTER. CP B ; IS IT THE QUOTE CHAR? JP NZ,PTCHR4 ; IF NOT PROCEED. LD A,(HL) ; GET THE QUOTED CHARACTER INC HL LD (OUTPNT),HL ; AND BUMP POINTER. LD HL,TEMP1 DEC (HL) ; DECREMENT # OF CHARS IN PACKET. LD D,A ; SAVE THE CHAR. AND 80H ; TURN OFF ALL BUT THE PARITY BIT. LD E,A ; SAVE THE PARITY BIT. LD A,D ; GET THE CHAR. AND 7FH ; TURN OFF THE PARITY BIT. CP B ; IS IT THE QUOTE CHAR? JP Z,PTCHR3 ; IF SO JUST GO WRITE IT OUT. LD A,D ; GET THE CHAR. ADD A,40H ; MAKE THE CHARACTER A CONTROL CHAR AGAIN. AND 7FH ; MODULO 128. PTCHR3: OR E ; OR IN THE PARITY BIT. LD E,A ;SAVE IT LD A,(CPMFLG) ;FILE TYPE? CP 1 ;ASCII? JR NZ,PTCR3B LD A,E CP LF ;LINE FEED? JR NZ,PTCR3B LD A,(LSTCHR) CP CR JP Z,PTCHR1 ;SKIP IT LD E,CR ;CONVERT IT PTCR3B: LD A,E LD (LSTCHR),A PTCHR4: LD DE,FCB CALL @PUT ;output character to file JP NZ,QUIT ;bad write JP PTCHR1 ; GET THE CHARS FROM THE FILE. GTCHR: LD A,(SQUOTE) ; GET THE QUOTE CHAR. LD C,A ; KEEP QUOTE CHAR IN C. LD A,(EOFLAG) OR A RET NZ LD A,(FILFLG) ; GET THE FILE FLAG. OR A ; IS THERE ANYTHING IN THE DMA? JR Z,GTCHR0 ; YUP, PROCEED. LD B,0 ; NO CHARS YET. GTCHR0: LD A,(CURCHK) ; GET CURRENT BLOCK CHECK TYPE SUB '1' ; GET THE EXTRA OVERHEAD LD B,A ; GET A COPY LD A,(SPSIZ) ; GET THE MAXIMUM PACKET SIZE. SUB 5 ; SUBTRACT THE OVERHEAD. SUB B ; DETERMINE MAX PACKET LENGTH LD (TEMP1),A ; THIS IS THE NUMBER OF CHARS WE ARE TO GET. LD HL,FILBUF ; WHERE TO PUT THE DATA. LD (CBFPTR),HL ; REMEMBER WHERE WE ARE. LD B,0 ; NO CHARS. GTCHR1: LD A,(TEMP1) DEC A ; DECREMENT THE NUMBER OF CHARS LEFT. JP P,GTCHR2 ; GO ON IF THERE IS MORE THAN ONE LEFT. LD A,B ; RETURN THE COUNT IN A. JP RSKP GTCHR2: LD (TEMP1),A LD A,(CPMFLG) ;GET THE FILE TYPE FLAG CP 1 ;ASCII JR NZ,GTCHR4 ;NOPE LD A,(LSTCHR) ;GET LAST CHARACTER CP CR ;CARRIAGE RETURN? JR NZ,GTCHR4 ;NOPE LD A,LF ;ADD A LINE FEED JR GTCR4A GTCHR4: LD DE,FCB CALL @GET ;get a character JP NZ,GTCHR9 GTCR4A: LD D,A ; SAVE THE CHAR. LD A,(CPMFLG) CP 1 JR NZ,GTCR4B LD A,D ;make sure it is a AND 7FH ;legal ASCII character LD D,A GTCR4B: AND 80H ; TURN OFF ALL BUT PARITY. LD E,A ; SAVE THE PARITY BIT. LD A,D ; RESTORE THE CHAR. AND 7FH ; TURN OFF THE PARITY. LD (LSTCHR),A ;SAVE THIS CHARACTER CP ' ' ; COMPARE TO A SPACE. JP M,GTCHR7 ; IF LESS THEN ITS A CONTROL CHAR, HANDLE IT. CP DEL ; IS THE CHAR A DELETE? JP Z,GTCHR7 CP C ; IS IT THE QUOTE CHAR? JP NZ,GTCHR8 ; IF NOT PROCEED. LD HL,TEMP1 ; POINT TO THE CHAR TOTAL REMAINING. DEC (HL) ; DECREMENT IT. LD HL,(CBFPTR) ; POSITION IN CHARACTER BUFFER. LD (HL),A ; PUT THE CHAR IN THE BUFFER. INC HL LD (CBFPTR),HL INC B ; INCREMENT THE CHAR COUNT. JP GTCHR8 GTCHR7: LD (TEMP2),A ; SAVE THE CHAR. LD HL,TEMP1 ; POINT TO THE CHAR TOTAL REMAINING. DEC (HL) ; DECREMENT IT. LD HL,(CBFPTR) ; POSITION IN CHARACTER BUFFER. LD (HL),C ; PUT THE QUOTE IN THE BUFFER. INC HL LD (CBFPTR),HL INC B ; INCREMENT THE CHAR COUNT. LD A,(TEMP2) ; GET THE CONTROL CHAR BACK. ADD A,40H ; MAKE THE NON-CONTROL. AND 7FH ; MODULO 200 OCTAL. GTCHR8: LD HL,(CBFPTR) ; POSITION IN CHARACTER BUFFER. OR E ; OR IN THE PARITY BIT. LD (HL),A ; PUT THE CHAR IN THE BUFFER. INC HL LD (CBFPTR),HL INC B ; INCREMENT THE CHAR COUNT. JP GTCHR1 GTCHR9: LD A,0FFH LD (EOFLAG),A LD A,B JP RSKP ;MULTI-FILE ACCESS SUBROUTINE. ALLOWS PROCESSING OF MULTIPLE FILES ;(I.E., *.ASM) FROM DISK. THIS ROUTINE BUILDS THE PROPER NAME IN THE ;FCB EACH TIME IT IS CALLED. THIS COMMAND WOULD BE USED IN SUCH PRO- ;GRAMS SUCH AS MODEM TRANSFER, TAPE SAVE, ETC. IN WHICH YOU WANT TO ;PROCESS SINGLE OR MULTIPLE FILES. ; ;THE FCB WILL BE SET UP WITH THE NEXT NAME, READY TO DO NORMAL PROCES- ;SING (OPEN, READ, ETC.) WHEN ROUTINE IS CALLED. ; ;CARRY IS SET IF NO MORE NAMES CAN BE FOUND ; ; MFFLG1 IS COUNT/SWITCH [0 FOR FIRST TIME THRU, POS FOR ALL OTHERS] ; MFFLG2 IS COUNTED DOWN FOR EACH SUCCESSIVE GETNEXT FILE CALL MFNAME: JP NC,MFN00 CCF ;CLEAR CARRY MFN00: PUSH BC ;SAVE REGISTERS PUSH DE PUSH HL LD B,50 LD HL,FCB MFN0A: LD (HL),20H INC HL DJNZ MFN0A LD B,32 LD HL,MFREQ MFN0B: LD (HL),20H INC HL DJNZ MFN0B LD HL,(MFNPTR) LD DE,MFREQ CALL @FSPEC LD (MFNPTR),HL JR NZ,MFFIX2 MFN01: LD HL,MFREQ ;SFIRST REQ NAME LD DE,FCB CALL @FSPEC ;MOVE TO FCB MFFIX1: POP HL ; RESTORE REGISTERS POP DE POP BC RET ;AND RETURN MFFIX2: SCF ;SET CARRY JR MFFIX1 ;RETURN WITH CARRY SET GETFIL: LD A,0FFH LD (FILFLG),A ; NOTHING IN THE DMA. XOR A LD (EOFLAG),A ; NOT THE END OF FILE. LD (LSTCHR),A PUSH HL LD DE,FCB LD HL,BUFF CALL @OPEN POP HL JP NZ,ERRORD JP RSKP GOFIL: LD HL,DATA ; GET THE ADDRESS OF THE FILE NAME. LD (DATPTR),HL ; STORE THE ADDRESS. LD HL,FCB ; ADDRESS OF THE FCB. LD (FCBPTR),HL ; SAVE IT. XOR A LD (TEMP1),A ; INITIALIZE THE CHAR COUNT. LD (TEMP2),A LD B,50 GOFIL1: LD (HL),20H ; BLANK THE FCB. INC HL DJNZ GOFIL1 GOFIL2: LD HL,(DATPTR) ; GET THE NAME FIELD. LD A,(HL) INC HL LD (DATPTR),HL CP '.' ; SEPERATOR? JP NZ,GOFIL3 LD A,(TEMP1) LD (TEMP2),A XOR A LD (TEMP1),A JP GOFIL5 GOFIL3: OR A ; TRAILING NULL? JP Z,GOFIL7 ; THEN WE'RE DONE. LD HL,(FCBPTR) LD (HL),A INC HL LD (FCBPTR),HL LD A,(TEMP1) ; GET THE CHAR COUNT. INC A LD (TEMP1),A CP 8H ; ARE WE FINISHED WITH THIS FIELD? JP M,GOFIL2 GOFIL4: LD (TEMP2),A XOR A LD (TEMP1),A LD HL,(DATPTR) LD A,(HL) INC HL LD (DATPTR),HL OR A JP Z,GOFIL7 CP '.' ; IS THIS THE TERMINATOR? JP NZ,GOFIL4 ; GO UNTIL WE FIND IT. GOFIL5 LD HL,(FCBPTR) LD (HL),'/' ;PUT IN A SLASH INC HL LD (FCBPTR),HL GOFIL6: LD HL,(DATPTR) ; GET THE TYPE FIELD. LD A,(HL) INC HL LD (DATPTR),HL OR A ; TRAILING NULL? JP Z,GOFIL7 ; THEN WE'RE DONE. LD HL,(FCBPTR) LD (HL),A INC HL LD (FCBPTR),HL LD A,(TEMP1) ; GET THE CHAR COUNT. INC A LD (TEMP1),A CP 03H ; ARE WE FINISHED WITH THIS FIELD? JP M,GOFIL6 GOFIL7: LD HL,(DATPTR) LD (HL),'$' ; PUT IN A DOLLAR SIGN FOR PRINTING. LD DE,SCRFLN ; POSITION CURSOR CALL PRTSTR LD DE,DATA ; PRINT THE FILE NAME CALL PRTSTR LD HL,(FCBPTR) LD (HL),3 ;PUT TERMINATOR IN FCB LD A,(FLWFLG) ;IS FILE WARNING ON? OR A JP Z,GOFIL9 ; IF NOT, JUST PROCEED. LD DE,FCB LD HL,BUFF CALL @OPEN JP NZ,GOFIL9 ; IF NOT CREATE IT. LD DE,INFMS5 CALL ERROR3 LD DE,FCB CALL @CLOSE ;close opened file GOFIL8: LD HL,(FCBPTR) ;make a new filename GOFL8A DEC HL GOFL8B LD A,(HL) CP 'B' JR C,GOFL8A ;TOO SMALL DEC (HL) ;DECREMENT CHARACTER LD (FCBPTR),HL LD DE,FCB ;new file name ok? LD HL,BUFF CALL @OPEN JP NZ,GOFL89 ; yes! LD DE,FCB CALL @CLOSE LD HL,(FCBPTR) OR A SBC HL,DE JR NZ,GOFIL8 ;TRY AGAIN GOFL88: LD DE,ERMS16 ; TELL USER THAT WE CAN'T RENAME IT. CALL PRTSTR RET GOFL89: LD HL,FCB ;move it for usage by other routines LD DE,MFREQ CALL @FSPEC LD A,':' LD BC,14 LD HL,MFREQ CPIR INC HL LD (HL),'$' LD DE,MFREQ CALL PRTSTR GOFIL9: XOR A LD (LSTCHR),A LD DE,FCB LD HL,BUFF CALL @INIT JP Z,RSKP PUSH AF LD DE,ERMS11 CALL ERROR3 POP AF JP ERRORD ; PACKET ROUTINES ; SEND_PACKET ; THIS ROUTINE ASSEMBLES A PACKET FROM THE ARGUMENTS GIVEN AND SENDS IT ; TO THE HOST. ; ; EXPECTS THE FOLLOWING: ; A - TYPE OF PACKET (D,Y,N,S,R,E,F,Z,T) ; ARGBLK - PACKET SEQUENCE NUMBER ; ARGBLK+1 - NUMBER OF DATA CHARACTERS ; RETURNS: +1 ON FAILURE ; +2 ON SUCCESS SPACK: LD (ARGBLK+2),A LD HL,PACKET ; GET ADDRESS OF THE SEND PACKET. LD A,SOH ; GET THE START OF HEADER CHAR. LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. LD A,(CURCHK) ; GET CURRENT CHECKSUM TYPE SUB '1' ; DETERMINE EXTRA LENGTH OF CHECKSUM LD B,A ; COPY LENGTH LD A,(ARGBLK+1) ; GET THE NUMBER OF DATA CHARS. ADD A,' '+3 ; REAL PACKET CHARACTER COUNT MADE PRINTABLE. ADD A,B ; DETERMINE OVERALL LENGTH LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. LD BC,0 ; ZERO THE CHECKSUM AC. LD C,A ; START THE CHECKSUM. LD A,(ARGBLK) ; GET THE PACKET NUMBER. ADD A,' ' ; ADD A SPACE SO THE NUMBER IS PRINTABLE. LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. ADD A,C LD C,A ; ADD THE PACKET NUMBER TO THE CHECKSUM. LD A,0 ; CLEAR A (CANNOT BE XRA A, SINCE WE CAN'T TOUCH CARRY FLAG) ADC A,B ; GET HIGH ORDER PORTION OF CHECKSUM LD B,A ; COPY BACK TO B LD A,(ARGBLK+2) ; GET THE PACKET TYPE. LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. ADD A,C LD C,A ; ADD THE PACKET NUMBER TO THE CHECKSUM. LD A,0 ; CLEAR A ADC A,B ; GET HIGH ORDER PORTION OF CHECKSUM LD B,A ; COPY BACK TO B SPACK2: LD A,(ARGBLK+1) ; GET THE PACKET SIZE. OR A ; ARE THERE ANY CHARS OF DATA? JP Z,SPACK3 ; NO, FINISH UP. DEC A ; DECREMENT THE CHAR COUNT. LD (ARGBLK+1),A ; PUT IT BACK. LD A,(HL) ; GET THE NEXT CHAR. INC HL ; POINT TO NEXT CHAR. ADD A,C LD C,A ; ADD THE PACKET NUMBER TO THE CHECKSUM. LD A,0 ; CLEAR A ADC A,B ; GET HIGH ORDER PORTION OF CHECKSUM LD B,A ; COPY BACK TO B JP SPACK2 ; GO TRY AGAIN. SPACK3: LD A,(CURCHK) ; GET THE CURRENT CHECKSUM TYPE CP '2' ; TWO CHARACTER? JP Z,SPACK4 ; YES, GO HANDLE IT JP NC,SPACK5 ; NO, GO HANDLE CRC IF '3' LD A,C ; GET THE CHARACTER TOTAL. AND 0C0H ; TURN OFF ALL BUT THE TWO HIGH ORDER BITS. ; RRC ; RRC ; RRC ; RRC ; RRC ; RRC ; SHIFT THEM INTO THE LOW ORDER POSITION. RLCA ; TWO LEFT ROTATES SAME AS 6 RIGHTS RLCA ; . . . ADD A,C ; ADD IT TO THE OLD BITS. AND 3FH ; TURN OFF THE TWO HIGH ORDER BITS. (MOD 64) ADD A,' ' ; ADD A SPACE SO THE NUMBER IS PRINTABLE. LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. JP SPACK7 ; GO STORE EOL CHARACTER ; HERE FOR 3 CHARACTER CRC-CCITT SPACK5: LD (HL),0 ; STORE A NULL FOR CURRENT END PUSH HL ; SAVE H LD HL,PACKET+1 ; POINT TO FIRST CHECKSUMED CHARACTER CALL CRCCLC ; CALCULATE THE CRC POP HL ; RESTORE THE POINTER LD C,E ; GET LOW ORDER HALF FOR LATER LD B,D ; COPY THE HIGH ORDER LD A,D ; GET THE HIGH ORDER PORTION RLCA ; SHIFT OFF LOW 4 BITS RLCA ; . . . RLCA ; . . . RLCA ; . . . AND 0FH ; KEEP ONLY LOW 4 BITS ADD A,' ' ; PUT INTO PRINTING RANGE LD (HL),A ; STORE THE CHARACTER INC HL ; POINT TO NEXT POSITION ; HERE FOR TWO CHARACTER CHECKSUM SPACK4: LD A,B ; GET HIGH ORDER PORTION AND 0FH ; ONLY KEEP LAST FOUR BITS RLCA ; SHIFT UP TWO BITS RLCA ; . . . LD B,A ; COPY BACK INTO SAFE PLACE LD A,C ; GET LOW ORDER HALF RLCA ; SHIFT HIGH TWO BITS RLCA ; TO LOW TWO BITS AND 03H ; KEEP ONLY TWO LOW BITS OR B ; GET HIGH ORDER PORTION IN ADD A,' ' ; CONVERT TO PRINTING CHARACTER RANGE LD (HL),A ; STORE THE CHARACTER INC HL ; POINT TO NEXT CHARACTER LD A,C ; GET LOW ORDER PORTION AND 3FH ; KEEP ONLY SIX BITS ADD A,' ' ; CONVERT TO PRINTING RANGE LD (HL),A ; STORE IT INC HL ; BUMP THE POINTER SPACK7: LD A,(SEOL) ; GET THE EOL THE OTHER HOST WANTS. LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. XOR A ; GET A NULL. LD (HL),A ; PUT IN THE PACKET. LD A,(DBFLG) OR A JR Z,SPACK8 ;debug is off INC HL ; POINT TO NEXT CHAR. LD A,'$' ; GET A DOLLAR SIGN. LD (HL),A ; PUT IN THE PACKET. SPACK8: CALL OUTPKT ; CALL THE SYSTEM DEPENDENT ROUTINE. JP QUIT JP RSKP ; WRITE OUT A PACKET. OUTPKT LD A,(SPAD) ; GET THE NUMBER OF PADDING CHARS. LD (TEMP1),A OUTPK2: LD A,(TEMP1) ; GET THE COUNT. DEC A OR A JP M,OUTPK6 ; IF NONE LEFT PROCEED. LD (TEMP1),A LD A,(SPADCH) ; GET THE PADDING CHAR. LD E,A ; PUT THE CHAR IN RIGHT AC. CALL OUTCHR ; OUTPUT IT. JP OUTPK2 OUTPK6: LD A,(IBMFLG) ; IS THIS THE (DUMB) IBM. OR A JP Z,OUTPK8 ; IF NOT THEN PROCEED. LD A,(STATE) ; CHECK IF THIS IS THE SEND-INIT PACKET. CP 'S' ;* THIS WILL ALSO HAVE TO BE TAKEN CARE FOR 'R' (RECEIVE), 'G' (GENERIC) ;* AND 'C' (COMMAND) PACKETS IF THE IBM BECOMES A SERVER. JP Z,OUTPK8 ; IF SO DON'T WAIT FOR THE XON. OUTPK7: CALL INCHR ; WAIT FOR THE TURN AROUND CHAR. JP OUTPK8 CP XON ; IS IT THE IBM TURN AROUND CHARACTER? JP NZ,OUTPK7 ; IF NOT, GO UNTIL IT IS. OUTPK8: LD A,(DBFLG) OR A JR Z,OUTPK9 LD DE,SPPOS ; PRINT THE PACKET CALL PRTSTR LD DE,PACKET+1 CALL PRTSTR OUTPK9: LD HL,PACKET ; POINT TO THE PACKET. OUTLUP: LD A,(HL) ; GET THE NEXT CHARACTER. OR A ; IS IT A NULL? JP Z,OUTLUD ; IF SO RETURN SUCCESS. LD E,A ; PUT THE CHAR IN RIGHT AC. CALL OUTCHR ; OUTPUT THE CHARACTER. INC HL ; INCREMENT THE CHAR POINTER. JP OUTLUP OUTLUD: JP RSKP ; JUST RETURN ; THIS ROUTINE WAITS FOR A PACKET TO ARRIVE FROM THE HOST. IT READS ; CHARACTERS UNTIL IT FINDS A SOH. IT THEN READS THE PACKET INTO PACKET. ; ; RETURNS: +1 FAILURE (IF THE CHECKSUM IS WRONG OR THE PACKET TRASHED) ; +2 SUCCESS WITH A - MESSAGE TYPE ; ARGBLK - MESSAGE NUMBER ; ARGBLK+1 - LENGTH OF DATA RPACK: CALL INPKT ; READ UP TO A CARRIAGE RETURN. JP QUIT ; RETURN BAD. RPACK0: CALL GETCHR ; GET A CHARACTER. JP RPACK ; HIT A CR; NULL LINE; JUST START OVER. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JR NZ,RPACK0 ; NO, GO UNTIL IT IS. RPACK1: CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JR Z,RPACK1 ; YES, THEN GO START OVER. LD (PACKET+1),A ; STORE IN PACKET ALSO LD C,A ; START THE CHECKSUM. LD A,(CURCHK) ; GET BLOCK CHECK TYPE SUB '1' ; DETERMINE EXTRA LENGTH OF BLOCK CHECK LD B,A ; GET A COPY LD A,C ; GET BACK LENGTH CHARACTER SUB ' '+3 ; GET THE REAL DATA COUNT. SUB B ; GET TOTAL LENGTH LD (ARGBLK+1),A LD B,0 ; CLEAR HIGH ORDER HALF OF CHECKSUM CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JR Z,RPACK1 ; YES, THEN GO START OVER. LD (ARGBLK),A LD (PACKET+2),A ; SAVE ALSO IN PACKET ADD A,C LD C,A ; ADD THE CHARACTER TO THE CHECKSUM. LD A,0 ; CLEAR A ADC A,B ; GET HIGH ORDER PORTION OF CHECKSUM LD B,A ; COPY BACK TO B LD A,(ARGBLK) SUB ' ' ; GET THE REAL PACKET NUMBER. LD (ARGBLK),A CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK1 ; YES, THEN GO START OVER. LD (TEMP1),A ; SAVE THE MESSAGE TYPE. LD (PACKET+3),A ; SAVE IN PACKET ADD A,C LD C,A ; ADD THE CHARACTER TO THE CHECKSUM. LD A,0 ; CLEAR A ADC A,B ; GET HIGH ORDER PORTION OF CHECKSUM LD B,A ; COPY BACK TO B LD A,(ARGBLK+1) ; GET THE NUMBER OF DATA CHARACTERS. LD (TEMP2),A LD HL,DATA ; POINT TO THE DATA BUFFER. LD (DATPTR),HL RPACK2: LD A,(TEMP2) SUB 1 ; ANY DATA CHARACTERS? JP M,RPACK3 ; IF NOT GO GET THE CHECKSUM. LD (TEMP2),A CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK1 ; YES, THEN GO START OVER. LD HL,(DATPTR) LD (HL),A ; PUT THE CHAR INTO THE PACKET. INC HL ; POINT TO THE NEXT CHARACTER. LD (DATPTR),HL ADD A,C LD C,A ; ADD THE CHARACTER TO THE CHECKSUM. LD A,0 ; CLEAR A ADC A,B ; GET HIGH ORDER PORTION OF CHECKSUM LD B,A ; COPY BACK TO B JR RPACK2 ; GO GET ANOTHER. RPACK3: CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK1 ; YES, THEN GO START OVER. SUB ' ' ; TURN THE CHAR BACK INTO A NUMBER. LD (TEMP3),A ; DETERMINE TYPE OF CHECKSUM LD A,(CURCHK) ; GET THE CURRENT CHECKSUM TYPE CP '2' ; 1, 2 OR 3 CHARACTER? JP Z,RPACK4 ; IF ZERO, 2 CHARACTER JP NC,RPACK5 ; GO HANDLE 3 CHARACTER LD A,C ; GET THE CHARACTER TOTAL. AND 0C0H ; TURN OFF ALL BUT THE TWO HIGH ORDER BITS. ; RRC ; RRC ; RRC ; RRC ; RRC ; RRC ; SHIFT THEM INTO THE LOW ORDER POSITION. RLCA ; TWO LEFT ROTATES SAME AS SIX RIGHTS RLCA ; . . . ADD A,C ; ADD IT TO THE OLD BITS. AND 3FH ; TURN OFF THE TWO HIGH ORDER BITS. (MOD 64) LD B,A LD A,(TEMP3) ; GET THE REAL RECEIVED CHECKSUM. CP B ; ARE THEY EQUAL? JP Z,RPACK7 ; IF SO, PROCEED. RPACK9: CALL UPDRTR ; IF NOT, UPDATE THE NUMBER OF RETRIES. RET ; RETURN ERROR. ; HERE FOR THREE CHARACTER CRC-CCITT RPACK5: LD HL,(DATPTR) ; GET THE ADDRESS OF THE DATA LD (HL),0 ; STORE A ZERO IN THE BUFFER TO TERMINATE PACKET LD HL,PACKET+1 ; POINT AT START OF CHECKSUMMED REGION CALL CRCCLC ; CALCULATE THE CRC LD C,E ; SAVE LOW ORDER HALF FOR LATER LD B,D ; ALSO COPY HIGH ORDER LD A,D ; GET HIGH BYTE RLCA ; WANT HIGH FOUR BITS RLCA ; . . . RLCA ; AND SHIFT TWO MORE RLCA ; . . . AND 0FH ; KEEP ONLY 4 BITS LD D,A ; BACK INTO D LD A,(TEMP3) ; GET FIRST VALUE BACK CP D ; CORRECT? JR NZ,RPACK9 ; NO, PUNT CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK1 ; YES, THEN GO START OVER. SUB ' ' ; REMOVE SPACE OFFSET LD (TEMP3),A ; STORE FOR LATER CHECK ; HERE FOR A TWO CHARACTER CHECKSUM AND LAST TWO CHARACTERS OF CRC RPACK4: LD A,B ; GET HIGH ORDER PORTION AND 0FH ; ONLY FOUR BITS RLCA ; SHIFT UP TWO BITS RLCA ; . . . LD B,A ; SAVE BACK IN B LD A,C ; GET LOW ORDER RLCA ; MOVE TWO HIGH BITS TO LOW BITS RLCA ; . . . AND 03H ; SAVE ONLY LOW TWO BITS OR B ; GET OTHER 4 BITS LD B,A ; SAVE BACK IN B LD A,(TEMP3) ; GET THIS PORTION OF CHECKSUM CP B ; CHECK FIRST HALF JP NZ,RPACK9 ; IF BAD, GO GIVE UP CALL GETCHR ; GET A CHARACTER. JP QUIT ; HIT THE CARRIAGE RETURN, RETURN BAD. CP SOH ; IS THE CHAR THE START OF HEADER CHAR? JP Z,RPACK1 ; YES, THEN GO START OVER. SUB ' ' ; REMOVE SPACE OFFSET LD B,A ; SAVE IN SAFE PLACE LD A,C ; GET LOW 8 BITS OF CHECKSUM AND 3FH ; KEEP ONLY 6 BITS CP B ; CORRECT VALUE JP NZ,RPACK9 ; BAD, GIVE UP RPACK7: LD HL,(DATPTR) LD (HL),0 ; PUT A NULL AT THE END OF THE DATA. LD A,(TEMP1) ; GET THE TYPE. JP RSKP INPKT: LD HL,RECPKT ; POINT TO THE BEGINNING OF THE PACKET. LD (PKTPTR),HL INPKT2: CALL INCHR ; GET A CHARACTER. JP QUIT ; RETURN FAILURE. LD HL,(PKTPTR) LD (HL),A ; PUT THE CHAR IN THE PACKET. INC HL LD (PKTPTR),HL LD B,A LD A,(REOL) ; GET THE EOL CHAR. CP B JR NZ,INPKT2 LD A,(DBFLG) OR A JR Z,INPKT3 ;DEBUG MODE IS OFF LD A,'$' ; GET A DOLLAR SIGN. LD (HL),A ; PUT IN THE PACKET. INC HL ; POINT TO NEXT CHAR. LD DE,RPPOS ; PRINT THE PACKET CALL PRTSTR LD DE,RECPKT+1 CALL PRTSTR INPKT3: LD HL,RECPKT LD (PKTPTR),HL ; SAVE THE PACKET POINTER. JP RSKP ; IF SO WE ARE DONE. GETCHR: LD HL,(PKTPTR) ; GET THE PACKET POINTER. LD A,(HL) ; GET THE CHAR. INC HL LD (PKTPTR),HL CP CR ; IS IT THE CARRIAGE RETURN? JP NZ,RSKP ; IF NOT RETURN RETSKP. RET ; IF SO RETURN FAILURE. ; ; THIS ROUTINE WILL CALCULATE A CRC USING THE CCITT POLYNOMIAL FOR ;A STRING. ; ; USAGE: ; HL/ ADDRESS OF STRING ; A/ LENGTH OF STRING ; CALL CRCCLC ; ; 16-BIT CRC VALUE IS RETURNED IN DE. ; ; REGISTERS BC AND HL ARE PRESERVED. ; CRCCLC: PUSH HL ; SAVE HL PUSH BC ; AND BC LD DE,0 ; INITIAL CRC VALUE IS 0 CRCCL0: LD A,(HL) ; GET A CHARACTER OR A ; CHECK IF ZERO JP Z,CRCCL1 ; IF SO, ALL DONE PUSH HL ; SAVE THE POINTER XOR E ; ADD IN WITH PREVIOUS VALUE LD E,A ; GET A COPY AND 0FH ; GET LAST 4 BITS OF COMBINED VALUE LD C,A ; GET INTO C LD B,0 ; AND MAKE HIGH ORDER ZERO LD HL,CRCTB2; POINT AT LOW ORDER TABLE ADD HL,BC ; POINT TO CORRECT ENTRY ADD HL,BC ; . . . PUSH HL ; SAVE THE ADDRESS LD A,E ; GET COMBINED VALUE BACK AGAIN RRCA ; SHIFT OVER TO MAKE INDEX RRCA ; . . . RRCA ; . . . AND 1EH ; KEEP ONLY 4 BITS LD C,A ; SET UP TO OFFSET TABLE LD HL,CRCTAB; POINT AT HIGH ORDER TABLE ADD HL,BC ; CORRECT ENTRY LD A,(HL) ; GET LOW ORDER PORTION OF ENTRY XOR D ;XOR US HIGH ORDER HALF INC HL ; POINT TO HIGH ORDER BYTE LD D,(HL) ; GET INTO D POP HL ; GET BACK POINTER TO OTHER TABLE ENTRY XOR (HL) ; INCLUDE WITH NEW HIGH ORDER HALF LD E,A ; COPY NEW LOW ORDER PORTION INC HL ; POINT TO OTHER PORTION LD A,(HL) ; GET THE OTHER PORTION OF THE TABLE ENTRY XOR D ; INCLUDE WITH OTHER HIGH ORDER PORTION LD D,A ; MOVE BACK INTO D POP HL ; AND H INC HL ; POINT TO NEXT CHARACTER JP CRCCL0 ; GO GET NEXT CHARACTER CRCCL1: POP BC ; RESTORE B POP HL ; AND HL RET ; AND RETURN, DE=CRC-CCITT CRCTAB: DW 00000H DW 01081H DW 02102H DW 03183H DW 04204H DW 05285H DW 06306H DW 07387H DW 08408H DW 09489H DW 0A50AH DW 0B58BH DW 0C60CH DW 0D68DH DW 0E70EH DW 0F78FH CRCTB2: DW 00000H DW 01189H DW 02312H DW 0329BH DW 04624H DW 057ADH DW 06536H DW 074BFH DW 08C48H DW 09DC1H DW 0AF5AH DW 0BED3H DW 0CA6CH DW 0DBE5H DW 0E97EH DW 0F8F7H