#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 4096 extern 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 0 static 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 0 static 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); }