; m4pkt/asm ; ; Most of the code in this file was derived directly from ; the C-KERMIT program. The code here represents a line by ; line translation of the C-KERMIT code. ; MEMSTR DW 0 MAXSIZE DB 0 ; ; Encode a packet from memory contents instead of from a file ; ENCSTR EQU $ PUSH HL ;Save the registers PUSH BC PUSH DE LD (MEMSTR),HL ;Store the passed pointer CALL RSETPKT ;Reinitiaize GETPKT() parameters CALL GETPKT ;Get a packet LD HL,0 ;Reset the memory pointer LD (MEMSTR),HL POP DE ;Restore the registers POP BC POP HL RET ;Return to the caller ; ; Get a packet worth of data from the FILE indicated by the global ; FCB. Eighth bit quoting, and Repeat count prefixing are done ; as indicated by the status of EBQFLAG, and RPTFLG respectively. ; GETPKT EQU $ PUSH BC ;Save the registers PUSH DE PUSH HL LD A,(CURCHK) ;Calculate the size of a packet SUB '1' LD B,A LD A,(SPSIZ) ;Get the user specified size SUB 5 ;Minus the overhead SUB B LD (MAXSIZE),A ;Save it for later use LD HL,(NEXT) ;Get the next character, 16 bits LD BC,0 ;Subtract zero to set flags OR A ;Reset the carry flag SBC HL,BC ;Set the flags JP P,GETPKT1 CALL GETCH ;Get a character if no previous exists LD (CH),HL ;Save it GETPKT1 EQU $ LD BC,0 ;Copy leftovers from previous call GETPKT2 EQU $ LD HL,LEFTOVER ;Get the start ADD HL,BC ;Index by BC LD A,(HL) ;Get a byte LD HL,FILBUF ;Get the destination ADD HL,BC ;Index by BC LD (HL),A ;Put a byte IFZ GETPKT3 ;Exit loop if zero byte found INC C ;Point to next JR GETPKT2 ;Loop on GETPKT3 EQU $ LD A,C ;Save the initial size of leftovers LD (SIZE),A XOR A ;Nullify the string for next time LD (LEFTOVER),A GETPKT4 EQU $ LD HL,(CH) ;Get the character LD BC,0 ;Subtract zero to set the flags OR A SBC HL,BC JP M,GETPKT20 ;Jump at end of file CALL GETCH ;Get the next character LD (NEXT),HL ;Save it LD A,(SIZE) ;Get the current size LD (OSIZE),A ;Save it in case we overflow the packet LD C,A ;Make BC a 16 bit value of C LD B,0 LD HL,FILBUF ;Get the desination buffer ADD HL,BC ;Index by BC LD (CBFPTR),HL ;Save the buffer pointer LD HL,(CH) ;Get the character LD A,L ;Keep only 8 bits CALL ENCODE ;Encode it and store the result LD HL,(CBFPTR) ;Compute the new size LD BC,FILBUF ;Get the start OR A ;Reset carry SBC HL,BC ;Compute lenght LD A,L ;Keep only 8 bits LD (SIZE),A ;Store the result LD HL,(NEXT) ;Get the next character LD (CH),HL ;Store it as the current character LD A,(SIZE) ;Get the size and check the size LD C,A LD A,(MAXSIZE) ;Get the maximum length CP C ;Are they equal? JP Z,GETPKT20 ;Go return SIZE if equal JP P,GETPKT13 ;Jump if maxsize still bigger LD BC,0 ;Start from the beginning GETPKT11 EQU $ LD A,(OSIZE) ;Get the oldsize index PUSH BC ;Save the value of i ADD A,C ;Compute osize+i LD C,A ;Save the result LD HL,FILBUF ;Get the start of the buffer ADD HL,BC ;Compute &filbuf[osize+i] LD A,(HL) ;Get the character stored there POP BC ;Restore i LD HL,LEFTOVER ;Get the address of the leftover buffer ADD HL,BC ;Compute the absolute address LD (HL),A ;Store the byte OR A ;Check the value for zero JR Z,GETPKT12 ;Jump if end of string INC C ;Compute i++ JR GETPKT11 ;Go to the top of the loop GETPKT12 EQU $ LD A,(OSIZE) ;Store the new pointer LD (SIZE),A LD C,A ;Terminate the string with a NULL LD B,0 ;Get a 16 bit offset LD HL,FILBUF ;Get the starting address ADD HL,BC ;Compute the address LD (HL),0 ;Put in the NULL JP GETPKT20 ;Go to the return code GETPKT13 EQU $ JP GETPKT4 GETPKT20 EQU $ LD A,(SIZE) ;Get the size to return POP HL ;Restore the registers POP DE POP BC RET ; ; Encode the character in the Accumlator and put it into ; the packet buffer at CBFPTR. ; ENCODE EQU $ PUSH BC ;Save the regs PUSH DE PUSH HL LD C,A ;Save the character to encode LD A,(RPTFLG) ;Is repeat quoting in effect? OR A JP Z,ENCODE30 LD HL,(NEXT) ;Get the last character LD A,L IFANOT C,ENCODE3 LD A,(RPTCNT) ;Get the current repeat count INC A ;Add one to it LD (RPTCNT),A ;Store it back CP 94 ;Too many characters? JP M,ENCODE50 LD A,(RPTQ) CALL PUTCBF LD A,(RPTCNT) TOCHAR CALL PUTCBF XOR A LD (RPTCNT),A JP ENCODE30 ENCODE3 EQU $ LD A,(RPTCNT) IFANOT 1,ENCODE7 XOR A LD (RPTCNT),A LD A,C ;Get the character back CALL ENCODE ;Encode it again LD HL,(CBFPTR) ;Get the buffer pointer LD DE,FILBUF ;Get the start of the buffer OR A ;Reset the carry SBC HL,DE ;Compute the difference in L LD A,(MAXSIZE) ;Get MAXSIZE CP L ;Is L <= A? JP M,ENCODE6 LD A,L ;Get SIZE LD (OSIZE),A ;Store it in the old size ENCODE6 EQU $ XOR A LD (RPTCNT),A LD A,C ;Get the character back CALL ENCODE ;Encode it JP ENCODE50 ENCODE7 EQU $ LD A,(RPTCNT) CP 2 JP M,ENCODE10 LD A,(RPTQ) CALL PUTCBF LD A,(RPTCNT) ;Get the count ADD A,' '+1 ;Uncontrolify it CALL PUTCBF XOR A LD (RPTCNT),A ENCODE10 EQU $ ENCODE30 EQU $ LD A,C ;Get the character AND 127 ;Turn off high bit LD B,A ;Save it LD A,C ;Get the character AND 128 ;Leave only high bit LD D,A ;Save it IFZ ENCODE32 LD A,(EBQFLG) IFZ ENCODE32 LD A,(EBQ) CALL PUTCBF LD C,B ;Save only 7 bit version ENCODE32 EQU $ LD A,C ;Get all bits for check IFA 127,ENCODE33 IFAGE ' ',ENCODE34 ENCODE33 EQU $ LD A,(MYCTLQ) CALL PUTCBF LD A,C ;Get the character ADD A,64 ;Uncontrolify it AND 127 ;Keep only 7 bits LD C,A ;Save the new value ENCODE34 EQU $ LD HL,(CBFPTR) ;Do this ahead to save overhead LD A,(MYCTLQ) IFANOT B,ENCODE35 PUTHL A ;Store the byte ENCODE35 EQU $ LD A,(RPTFLG) IFZ ENCODE36 LD A,(RPTQ) IFANOT B,ENCODE36 LD A,(MYCTLQ) PUTHL A ENCODE36 EQU $ LD A,(EBQFLG) IFZ ENCODE37 LD A,(EBQ) IFANOT B,ENCODE37 LD A,(MYCTLQ) PUTHL A ENCODE37 EQU $ PUTHL C LD (CBFPTR),HL LD (HL),0 ENCODE50 EQU $ POP HL ;Restore the stack POP DE POP BC RET ; ; Decode the contents of the packet, and output them using ; the function whose address is passed in HL ; DECODE LD (OUTADDR),HL ;Save the output function PUSH BC ;Save the registers that we use PUSH DE PUSH HL LD HL,DATA ;Get the buffer address LD (DATPTR),HL ;Set the address LD C,A ;Get the length LD B,0 ;Make it 16 bits PUSH HL ;Save DATPTR ADD HL,BC ;Compute the end of the packet LD (HL),0 ;Put in the NULL byte POP HL ;Get DATPTR back DECODE0 LD A,1 ;Set the repeat count LD (RPTCNT),A LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Store the value OR A ;Is it NULL? JP Z,DECODE40 ;Quit the loop if it is LD A,(RPTFLG) ;Is repeat prefixing on? IFZ DECODE1 LD A,(RPTQ) ;Get the quote character IFANOT C,DECODE1 LD A,(HL) ;Get the count + 32 SUB ' ' ;Make it the real count INC HL ;Point to next character LD (RPTCNT),A ;Save the repeat count LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Save the character DECODE1 XOR A ;Set the initial eighth bit as ZERO LD D,A LD A,(EBQFLG) ;Is eighth bit quoting on? IFZ DECODE2 LD A,(EBQ) ;Get the eighth bit quote character IFANOT C,DECODE2 LD D,128 ;Get an eighth bit LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Save the character DECODE2 LD A,(MYCTLQ) ;Get the control character quote IFANOT C,DECODE5 LD A,(HL) ;Get a character INC HL ;Point to the next LD C,A ;Save the character AND 127 ;Keep 7 bits LD E,A ;Save only 7 bits worth LD A,E ;Check lower bound of controls CP '@' JP M,DECODE3 ;Jump if less than CP 96 ;Check upper bound of controls JP M,DECODE4 DECODE3 IFANOT '?',DECODE5 DECODE4 LD A,C ;Get the character SUB 64 ;Subtract 64 to uncontrolify it AND 127 LD C,A ;Save the new value DECODE5 LD A,D ;Get the eighth bit OR C ;Or in the character LD C,A ;Save the new value LD A,(RPTCNT) ;Get the repeat count LD B,A ;Get it into the counter DECODE8 LD IX,RTRANS ;Get the pointer CALL INCKTRANS ;Increment character counts LD A,C ;Get the character CALL PUTCH JR NZ,DECODE50 DJNZ DECODE8 ;Loop until done JP DECODE0 DECODE40 EQU $ POP HL ;Restore the stack POP DE POP BC RET DECODE50 EQU $ CALL XERROR0 ;Print a system error message LD A,1 ;Set NZ status for return OR A JR DECODE40 ;Join the exit code ; ; Get the next character from the input file. We translate CR to ; CRLF, for ASCII files. Returns with (EOFLAG) set to 0FFH at end ; of file. The character retrieved is in HL. HL will be 16bits ; of -1 and EOF, but will otherwise only be 8bits wide. H in this ; case will always be 0, and L will hold the character. ; GETCH LD A,(FILTYPE) ;Check for binary mode OR A ;Set the flags JR NZ,GETCH1 ;Jump if it is binary LD A,(PREVCH) ;Get the previous character IFANOT CR,GETCH1 LD A,10 ;Get a LF character LD (PREVCH),A ;Reset the previous character LD L,A ;Put it into HL LD H,0 RET ;Return to the caller GETCH1 EQU $ LD HL,(MEMSTR) LD A,H OR L JR Z,GETCH2 LD A,(HL) INC HL LD (MEMSTR),HL IFZ GETCH4 JR GETCH3 GETCH2 EQU $ LD DE,FCB ;Get the File Control Block CALL XGET ;Get a character into A JR NZ,GETCH4 ;Jump to EOF on error LD IX,STRANS ;Get the pointer CALL INCKTRANS ;Increment the character count GETCH3 EQU $ LD (PREVCH),A ;Set the previous character LD L,A ;Put it into HL LD H,0 RET ;Return GETCH4 EQU $ LD A,0FFH ;Set the EOF flag LD (EOFLAG),A LD (PREVCH),A ;Reset the previous character flag LD L,A ;Make HL 16bits wide -1 LD H,A RET ;Return to caller ; ; Put the next character to the output file. We convert CRLF to CR ; IFF X packets are not active, and binary mode is not active ; PUTCH PUSH HL PUSH BC ;Save the register LD C,A ;Save the character to output LD A,(PREVCH) ;Get the previous character IFANOT CR,PUTCH1 LD A,(DISFLG) ;Check if we are doing X packets IFZ PUTCH1 LD A,(FILTYPE) ;Doing D packets, so check file mode OR A JR NZ,PUTCH1 LD A,C IFA 10,PUTCH2 PUTCH1 LD A,C ;Get the character to output LD (PREVCH),A ;Make it the new previous LD HL,(OUTADDR) ;Get the output routines address CALL CALLHL ;Call the output routine PUTCH2 POP BC ;Restore the stack POP HL RET ;Return to caller ; ; Put A into the location pointed to by CBFPTR, and increment the ; pointer to point to the next location ; PUTCBF LD HL,(CBFPTR) ;Get the pointer PUTHL A LD (CBFPTR),HL ;Store the new pointer value RET ;Return ;end of file