/*---------------------------------------------------------------------------*/ /* Compress.c - implements compression based on code by Richard B. Johnson */ /* and utilises the existing Zmodem send/receive routines by */ /* recognising special packets. */ /* */ /* See the other source (extract) files for information on how */ /* to implement this code into your version of Zmodem. */ /* */ /* This source code (and its header file) is submitted to the public with no */ /* warranty for its merchantibility or fitness for a particular purpose. You */ /* are permitted to use these routines in your version of Zmodem without */ /* payment of any kind to me. */ /* */ /* */ /*---------------------------------------------------------------------------*/ int Compressed; /* For detecting if the packet was sent with it. */ BYTE *CompBuff; /* Compression buffer */ /*---------------------------------------------------------------------------*/ /* This routine does the actual compression of the block (BufferIn) and */ /* places the output into BufferOut. A constant check is kept and if the */ /* amount of bytes in the compressed packet exceeds the number in the un- */ /* compressed packet, the routine is aborted. This ensures that Zmodem does */ /* not send packets larger than it should. (For obvious reasons!). */ /*---------------------------------------------------------------------------*/ int pascal Compress(register BYTE *BufferIn, register BYTE *BufferOut, register int length) { static unsigned short NumDupes; static unsigned short count; static BYTE Duplicate; static int Blocksize; NumDupes = count = 0; Blocksize = length; /* Make sure compressed length doesn't exceed */ /* the uncompressed length. */ while (length) { if ((*BufferIn == (BYTE )0xBB) || (*BufferIn == *(BufferIn+1))) { *BufferOut++ = (BYTE )0xBB; Duplicate = *BufferIn; NumDupes = 0; while ((*BufferIn++ == Duplicate) && length) { NumDupes++; length--; } *BufferOut++ = (BYTE ) NumDupes; *BufferOut++ = (BYTE )(NumDupes >> 8); *BufferOut++ = Duplicate; count += 4; BufferIn--; } else { *BufferOut++ = *BufferIn++; count++; length--; } if (count > Blocksize) return (Blocksize + 99); /* Don't send this compressed */ } return count; } /*---------------------------------------------------------------------------*/ /* This routine takes the compressed buffer (BufferIn) and places the */ /* decoded data into the buffer (BufferOut). The resultant buffer size will */ /* be the same as the uncompressed size of the transmitted block. */ /*---------------------------------------------------------------------------*/ int pascal DeCompress(register BYTE *BufferIn, register BYTE *BufferOut, int length) { static unsigned short NumDupes; static unsigned short count; static BYTE ch, *limit; NumDupes = count = 0; limit = BufferIn + length; while (BufferIn < limit) { if (*BufferIn == (BYTE )0xBB) { BufferIn++; NumDupes = (unsigned short )*BufferIn++; NumDupes = NumDupes | (unsigned short ) (*BufferIn++ << 8); ch = *BufferIn++; for (; NumDupes > 0; NumDupes--) { *BufferOut++ = ch; count++; } } else { *BufferOut++ = *BufferIn++; count++; } } return count; /* Will return current Zmodem blocksize */ }