#pragma noroot//#pragma debug -1#pragma debug 0x8000#pragma lint -1#pragma optimize -1#include #include "deflate.h"#include "crc.h"void write(int, void *, long);int orca_sprintf(char *, const char *, ...);#define kAlloc 4096extern void PutBits(Word bits, Word bitLen, Word sane);extern void GetByteCode(Word, Word *code, Word *length);extern void GetRepeatCode(Word, Word *code, Word *len, Word *extra, Word *extralength);Word __PutRawByte(Word);static byte *buffPtr;static Handle buffHandle;static Word remain;static LongWord size;static LongWord used;static LongWord adler;Word workByte;Word workCnt;Word StartDeflate(Word MemID){ buffPtr = 0; buffHandle = 0; remain = 0; size = 0; used = 0; adler = 1; buffHandle = NewHandle(kAlloc, MemID, attrNoSpec | attrLocked, NULL); if (_toolErr) return -1; remain = kAlloc; used = 0; size = kAlloc; buffPtr = *buffHandle; __PutRawByte(0x78); __PutRawByte(0x9c); // standard dictionary, end block. PutBits(6, 3, 0);}typedef union split{ LongWord l; Byte b[4];} split;Handle EndDeflate(void){ PutBits(0, 7, 0); // end of block. if (workCnt) PutBits(0, 8 - workCnt, 0); __PutRawByte( ((split)adler).b[3]); __PutRawByte( ((split)adler).b[2]); __PutRawByte( ((split)adler).b[1]); __PutRawByte( ((split)adler).b[0]); SetHandleSize(used, buffHandle); return buffHandle;}// puts translated bytes to the output buffer.Word __PutRawByte(Word b){ if (!remain) { HUnlock(buffHandle); SetHandleSize(kAlloc + size, buffHandle); if (_toolErr) return -1; remain = kAlloc, size += kAlloc; HLock(buffHandle); buffPtr = *buffHandle + used; } *buffPtr++ = b; remain--; used++;}void GetByteCode(Word val, Word *code, Word *length){ *length = 0; *code = 0; if (val < 144) { *code = 0x30 + val; *length = 8; } else if (val < 256) { *code = 0x190 + val - 144; *length = 9; } else if (val < 280) { *code = 0x00 + val - 256; *length = 7; } else if (val < 288) { *code = 0xC0 + val - 280; *length = 8; } else { *code = 0; *length = 0; }}void GetRepeatCode(Word val, Word *code, Word *len, Word *extra, Word *elen){Word i;#if 0static char buffer[128]; write(3, buffer, orca_sprintf(buffer, "GetRepeatCode(%d)\r", val));#endif// 256--279 are 7 bit, %0000000--0010111.//280--287 are 8 bit, %11000000--11000111. *code = 0; *len = 0; *extra = 0; *elen = 0; // 3 -- 10 => codes 257-264 if (val < 11) { *code = 1 + val - 3; *len = 7; } // 11 -- 18 => codes 265-268 else if (val < 19) { val -= 11; *elen = 1; *extra = val & 0x01; *code = 9 + (val >> 1); *len = 7; } // 19 -- 34 else if (val < 35) { val -= 19; *elen = 2; *extra = val & 0x03; *code = 13 + (val >> 2); *len = 7; } // 35 -- 66 else if (val < 67) { val -= 35; *elen = 3; *extra = val & 0x07; *code = 17 + (val >> 3); *len = 7; } // 67 -- 130. 115-130 is 280, which is a different encoding... else if (val < 115) { val -= 67; *elen = 4; *extra = val & 0x0f; *code = 21 + (val >> 4); *len = 7; } // 280 - special case. else if (val < 131) { val -= 67; *elen = 4; *extra = val & 0x0f; *code = 0xC0; *len = 8; } // 131--257 else if (val < 258) { val -= 131; *elen = 5; *extra = val & 0x1f; *code = 0xc1 + (val >> 5); *len = 8; } else { *code = 0xc0 + 5; *len = 8; }#if 0 write(3, buffer, orca_sprintf(buffer, "v: %x code: %x:%x extra: %x,%x\r", val, *code, *len, *extra, *elen));#endif}Word PutBytes(Word b, Word cnt){Word code;Word length;#if 0static char buffer[128]; write(3, buffer, orca_sprintf(buffer, "PutBytes(%x, %u)\r", b, cnt));#endif GetByteCode(b, &code, &length); while (cnt) { PutBits(code, length, 0); cnt--; switch(cnt) { case 2: PutBits(code, length, 0); cnt--; case 1: PutBits(code, length, 0); cnt--; case 0: break; default: //multi bytes { Word rcode; Word rlen; Word extra; Word elength; Word tcnt; tcnt = cnt > 258 ? 258 : cnt; cnt -= tcnt; GetRepeatCode(tcnt, &rcode, &rlen, &extra, &elength); PutBits(rcode, rlen, 0); if (elength) PutBits(extra, elength, -1); PutBits(0 , 5, 0); // displacement... always 5? } } }}Word Deflate(byte *data, Word length){Word last = -1;Word cnt = 0;Word i;Word c; adler = AdlerCrc(adler, data, length); for (i = 0; i < length; i++) { c = data[i]; if (last == -1) { cnt = 1; last = c; continue; } if (c == last) { cnt++; continue; } PutBytes(last, cnt); last = c; cnt = 1; } if (cnt) PutBytes(last, cnt);}