Quellcode durchsuchen

Import ttpack.c from the TIGCC Tools Suite as export/pucrunch.c.
Add it to the makefile for the standalone builds.
Fix warnings.


git-svn-id: file:///var/svn/tigccpp/trunk@1127 9552661e-59e3-4036-b4f2-dbe53926924f

kevinkofler vor 17 Jahren
Ursprung
Commit
0680cba65f
3 geänderte Dateien mit 2132 neuen und 1 gelöschten Zeilen
  1. 1 1
      tigcc/ld-tigcc/Makefile
  2. 2129 0
      tigcc/ld-tigcc/export/pucrunch.c
  3. 2 0
      tigcc/ld-tigcc/generic.h

+ 1 - 1
tigcc/ld-tigcc/Makefile

@@ -27,7 +27,7 @@ COMPILE_C = $(CC) -c $(CFLAGS) $(ARCHFLAGS) $(WARN_CFLAGS) $(DEFINES)
 
 HEADERS = *.h formats/*.h import/*.h export/*.h bincode/*.h insert/*.h insert/model/*.h int_def.inc
 AR_HEADERS = ar/*.h ar/import/*.h ar/export/*.h *.h formats/*.h
-OBJECTS = main.o integers.o int_arb.o manip.o constmrg.o gcunused.o reorder.o import/import.o import/imp_coff.o import/imp_amig.o import/imp_ar.o export/export.o export/exp_def.o export/exp_os.o export/exp_tios.o export/exp_ndll.o export/exp_farg.o export/exp_data.o export/exp_dbg.o bincode/fix_m68k.o bincode/fix_tios.o bincode/fix_emu.o bincode/cutrange.o insert/ins_def.o insert/model/list.o insert/kernel.o insert/comprrlc.o insert/other.o special.o dump.o
+OBJECTS = main.o integers.o int_arb.o manip.o constmrg.o gcunused.o reorder.o import/import.o import/imp_coff.o import/imp_amig.o import/imp_ar.o export/export.o export/exp_def.o export/exp_os.o export/exp_tios.o export/exp_ndll.o export/exp_farg.o export/exp_data.o export/exp_dbg.o export/pucrunch.o bincode/fix_m68k.o bincode/fix_tios.o bincode/fix_emu.o bincode/cutrange.o insert/ins_def.o insert/model/list.o insert/kernel.o insert/comprrlc.o insert/other.o special.o dump.o
 AR_OBJECTS = ar/main.o ar/manip.o ar/import/import.o ar/import/imp_coff.o ar/import/imp_amig.o ar/export/exp_ar.o ar/dump.o integers.o
 DLL_OBJECTS = main.do integers.do int_arb.do manip.do constmrg.do gcunused.do reorder.do import/import.do import/imp_coff.do import/imp_amig.do import/imp_ar.do export/export.do export/exp_def.do export/exp_os.do export/exp_tios.do export/exp_ndll.do export/exp_farg.do export/exp_data.do export/exp_dbg.do bincode/fix_m68k.do bincode/fix_tios.do bincode/fix_emu.do bincode/cutrange.do insert/ins_def.do insert/model/list.do insert/kernel.do insert/comprrlc.do insert/other.do special.do
 DLL_AR_OBJECTS = ar/main.do ar/manip.do ar/import/import.do ar/import/imp_coff.do ar/import/imp_amig.do ar/export/exp_ar.do

+ 2129 - 0
tigcc/ld-tigcc/export/pucrunch.c

@@ -0,0 +1,2129 @@
+/* pucrunch.c: Pucrunch compression code
+
+   Pucrunch 1997-2005 by Pasi 'Albert' Ojala, a1bert@iki.fi
+   Copyright (C) 2000 Thomas Nussbaumer
+   Copyright (C) 2007 Kevin Kofler
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "../generic.h"
+#include "../formats/packhead.h"    // compressed header definition
+
+#define DEFAULT_ITEMS_PER_LINE  10
+
+#define FIXF_MACHMASK  0xff
+#define FIXF_WRAP	   256
+#define FIXF_DLZ	   512
+
+
+#define F_VERBOSE    (1<<0)
+#define F_STATS      (1<<1)
+#define F_AUTO       (1<<2)
+#define F_NOOPT      (1<<3)
+#define F_AUTOEX     (1<<4)
+#define F_TEXTINPUT  (1<<5)
+#define F_TEXTOUTPUT (1<<6)
+#define F_NORLE      (1<<9)
+#define F_ERROR      (1<<15)
+
+#ifndef min
+#define min(a,b) ((a<b)?(a):(b))
+#endif
+
+
+#define LRANGE          (((2<<maxGamma)-3)*256) /* 0..125, 126 -> 1..127 */
+#define MAXLZLEN        (2<<maxGamma)
+#define MAXRLELEN       (((2<<maxGamma)-2)*256) /* 0..126 -> 1..127 */
+#define DEFAULT_LZLEN   LRANGE
+
+
+
+unsigned short *rle, *elr, *lzlen, *lzpos;
+unsigned short *lzlen2, *lzpos2;
+int *length, inlen;
+unsigned char *indata, *mode, *newesc;
+unsigned short *backSkip;
+
+
+enum MODE {
+    LITERAL = 0,
+    LZ77    = 1,
+    RLE     = 2,
+    DLZ     = 3,
+    MMARK   = 4
+};
+
+int lzopt          = 0;
+int maxGamma       = 7;
+int reservedBytes  = 2;
+int escBits        = 2;
+int escMask        = 0xc0;
+int extraLZPosBits = 0;
+int rleUsed        = 31;
+
+
+unsigned char rleLen[256];
+int lenValue[256];
+int lrange, maxlzlen, maxrlelen;
+
+int gainedEscaped = 0;
+int gainedRle = 0, gainedSRle = 0, gainedLRle = 0;
+int gainedLz = 0, gainedRlecode = 0;
+int gainedDLz = 0, timesDLz = 0;
+
+int timesEscaped = 0, timesNormal = 0;
+int timesRle = 0, timesSRle = 0, timesLRle = 0;
+int timesLz = 0;
+
+int lenStat[8][4];
+
+unsigned char rleValues[32] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                               0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+int rleHist[256];
+
+
+
+
+#define OUT_SIZE 65536
+unsigned char outBuffer[OUT_SIZE];
+int outPointer = 0;
+int bitMask    = 0x80;
+
+int quiet      = 0;
+
+
+void TTPackInit(void) {
+    int i;
+
+    rleValues[0] = 1;
+    for (i=1;i<32;i++) rleValues[i] = 0;
+
+    for (i=0;i<256;i++) {
+        rleLen[i]   = 0;
+        lenValue[i] = 0;
+        rleHist[i]  = 0;
+    }
+
+    for (i=0;i<OUT_SIZE;i++) outBuffer[i] = 0;
+
+    lrange = 0, maxlzlen = 0, maxrlelen = 0;
+
+
+    gainedEscaped = 0;
+    gainedRle = 0, gainedSRle = 0, gainedLRle = 0;
+    gainedLz = 0, gainedRlecode = 0;
+    gainedDLz = 0, timesDLz = 0;
+
+    timesEscaped = 0, timesNormal = 0;
+    timesRle = 0, timesSRle = 0, timesLRle = 0;
+    timesLz = 0;
+
+    lrange         = 0;
+    maxlzlen       = 0;
+    maxrlelen      = 0;
+    outPointer     = 0;
+    bitMask        = 0x80;
+    lzopt          = 0;
+    maxGamma       = 7;
+    reservedBytes  = 2;
+    escBits        = 2;
+    escMask        = 0xc0;
+    extraLZPosBits = 0;
+    rleUsed        = 31;
+    rle            = NULL;
+    elr            = NULL;
+    lzlen          = NULL;
+    lzpos          = NULL;
+    lzlen2         = NULL;
+    lzpos2         = NULL;
+    length         = NULL;
+    inlen          = 0;
+    indata         = NULL;
+    mode           = NULL;
+    newesc         = NULL;
+    backSkip       = NULL;
+}
+
+
+
+//=============================================================================
+// the packing code
+//=============================================================================
+int SavePack(int flags,int type, unsigned char *data, int size, char *target,
+             int start ATTRIBUTE_UNUSED, int escape, unsigned char *rleValues,
+             int endAddr ATTRIBUTE_UNUSED, int extraLZPosBits,
+             int memStart ATTRIBUTE_UNUSED, int memEnd ATTRIBUTE_UNUSED)
+{
+    FILE *fp = NULL;
+
+    int  i;
+
+    if (!data)   return 10;
+    if (!target) fp = stdout;
+
+    if ((type & FIXF_MACHMASK) == 0) {
+        /* Save without decompressor */
+
+        if (fp || (fp = fopen(target, "wb"))) {
+            PackedHeader   cth;
+            RLEEntries     re;
+
+            cth.origsize_lo  = inlen & 0xff;
+            cth.origsize_hi  = (inlen >> 8);
+            cth.magic1       = MAGIC_CHAR1;
+            cth.magic2       = MAGIC_CHAR2;
+            cth.compsize_lo  = (size + rleUsed + sizeof(PackedHeader)) & 0xff;
+            cth.compsize_hi  = (size + rleUsed + sizeof(PackedHeader)) >> 8;
+            cth.esc1         = (escape >> (8-escBits));
+            cth.notused3     = 0; // just to make sure it has a defined value
+            cth.notused4     = 0; // just to make sure it has a defined value
+            cth.esc2         = escBits;
+            cth.gamma1       = maxGamma + 1;
+            cth.gamma2       = (1 << maxGamma);
+            cth.extralz      = extraLZPosBits;
+            cth.notused1     = 0; // just to make sure it has a defined value
+            cth.notused2     = 0; // just to make sure it has a defined value
+            cth.rleentries   = rleUsed;
+
+            for(i=0; i<rleUsed; i++) re.value[i] = rleValues[i+1];
+
+            if (flags & F_TEXTOUTPUT) {
+                unsigned int loop;
+                unsigned int written=0;
+                for (loop=0;loop<sizeof(PackedHeader);loop++,written++) {
+                    fprintf(fp,"0x%02x,",*(((unsigned char*)&cth)+loop));
+                    if ((!(written % DEFAULT_ITEMS_PER_LINE)) && written) fputc('\n',fp);
+                }
+                for (loop=0;loop<cth.rleentries;loop++,written++) {
+                    fprintf(fp,"0x%02x,",re.value[loop]);
+                    if (!(written % DEFAULT_ITEMS_PER_LINE)) fputc('\n',fp);
+                }
+                for (i=0;i < size;i++,written++) {
+                    if (i < size - 1)  fprintf(fp,"0x%02x,",data[i]);
+                    else                  fprintf(fp,"0x%02x",data[i]);
+                    if (!(written % DEFAULT_ITEMS_PER_LINE)) fputc('\n',fp);
+                }
+            }
+            else {
+                fwrite(&cth, 1, sizeof(PackedHeader), fp); // write header
+                fwrite(&re,  1, cth.rleentries, fp);       // write rle values
+                fwrite(data, size, 1, fp);                 // write compressed data
+                if(fp != stdout) fclose(fp);
+            }
+            return 0;
+        }
+        fprintf(stderr, "ERROR: Could not open %s for writing\n", target);
+        return 10;
+    }
+
+    fprintf(stderr, "FATAL: invalid type!!\n");
+    return 10;
+}
+
+
+
+//=============================================================================
+//
+//=============================================================================
+void FlushBits(void) {
+    if (bitMask != 0x80) outPointer++;
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+void PutBit(int bit) {
+    if (bit && outPointer < OUT_SIZE) outBuffer[outPointer] |= bitMask;
+    bitMask >>= 1;
+
+    if (!bitMask) {
+        bitMask = 0x80;
+        outPointer++;
+    }
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+void PutValue(int value) {
+    int bits = 0, count = 0;
+
+    while (value>1) {
+        bits = (bits<<1) | (value & 1); /* is reversed compared to value */
+        value >>= 1;
+        count++;
+        PutBit(1);
+    }
+
+    if (count<maxGamma) PutBit(0);
+
+    while (count--) {
+        PutBit((bits & 1));     /* output is reversed again -> same as value */
+        bits >>= 1;
+    }
+}
+
+
+
+//--------------------------------------------
+// why not initializing value lenValue[0] ????
+//--------------------------------------------
+//=============================================================================
+//
+//=============================================================================
+void InitValueLen() {
+    int i;
+
+    // could be heavily optimized, but isn't necessary
+    for (i=1; i<256; i++) {
+        int count = 0;
+
+        if (i<2)        count = 0;  /* 1       */
+        else if (i<4)   count = 1;  /* 2-3     */
+        else if (i<8)   count = 2;  /* 4-7     */
+        else if (i<16)  count = 3;  /* 8-15    */
+        else if (i<32)  count = 4;  /* 16-31   */
+        else if (i<64)  count = 5;  /* 32-63   */
+        else if (i<128) count = 6;  /* 64-127  */
+        else if (i<256) count = 7;  /* 128-255 */
+
+        lenValue[i] = 2*count;
+        if (count<maxGamma) lenValue[i]++;
+    }
+}
+
+
+#define LenValue(a) (lenValue[a])
+
+
+//=============================================================================
+//
+//=============================================================================
+void PutNBits(int byte, int bits) {
+    while (bits--)
+        PutBit((byte & (1<<bits)));
+}
+
+
+
+
+//=============================================================================
+//
+//=============================================================================
+int OutputNormal(int *esc, unsigned char *data, int newesc) {
+    timesNormal++;
+    if ((data[0] & escMask) == *esc) {
+        PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
+        PutBit(0);
+        PutBit(1);
+        PutBit(0);
+
+        *esc = newesc;
+        PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
+        PutNBits(data[0], 8-escBits);
+
+        gainedEscaped += escBits + 3;
+        timesEscaped++;
+        return 1;
+    }
+    PutNBits(data[0], 8);
+    return 0;
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+void OutputEof(int *esc) {
+    /* EOF marker */
+    PutNBits((*esc>>(8-escBits)), escBits);     /* escBits>=0 */
+    PutValue(3);        /* >2 */
+    PutValue((2<<maxGamma)-1);  /* Maximum value */
+    FlushBits();
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+void PutRleByte(int data) {
+    int index;
+
+    for (index = 1; index < 32; index++) {
+        if (data == rleValues[index]) {
+            if (index==1)       lenStat[0][3]++;
+            else if (index<=3)  lenStat[1][3]++;
+            else if (index<=7)  lenStat[2][3]++;
+            else if (index<=15) lenStat[3][3]++;
+            else if (index<=31) lenStat[4][3]++;
+
+            gainedRlecode += 8 - LenValue(index);
+
+            PutValue(index);
+            return;
+        }
+    }
+    PutValue(32 + (data>>3));
+
+    gainedRlecode -= LenValue(32+(data>>3)) + 3;
+
+    PutNBits(data, 3);
+
+    lenStat[5][3]++;
+}
+
+
+
+
+//=============================================================================
+//
+//=============================================================================
+void InitRleLen() {
+    int i;
+
+    for (i=0; i<256; i++) rleLen[i] = LenValue(32 + 0) + 3;
+    for (i=1; i<32; i++) rleLen[rleValues[i]] = LenValue(i);
+}
+
+#define LenRleByte(d) (rleLen[d])
+
+
+//=============================================================================
+//
+//=============================================================================
+int LenRle(int len, int data) {
+    int out = 0;
+
+    do {
+        if (len == 1) {
+            out += escBits + 3 + 8;
+            len = 0;
+        }
+        else if (len <= (1<<maxGamma)) {
+            out += escBits + 3 + LenValue(len-1) + LenRleByte(data);
+            len = 0;
+        }
+        else {
+            int tmp = min(len, maxrlelen);
+            out += escBits + 3 + maxGamma + 8 +
+                        LenValue(((tmp-1)>>8)+1) + LenRleByte(data);
+            len -= tmp;
+        }
+    } while (len);
+    return out;
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+int OutputRle(int *esc, unsigned char *data, int rlelen) {
+    int len = rlelen, tmp;
+
+    while (len) {
+        if (len >= 2 && len <= (1<<maxGamma)) {
+            /* Short RLE */
+            if (len==2)        lenStat[0][2]++;
+            else if (len<=4)   lenStat[1][2]++;
+            else if (len<=8)   lenStat[2][2]++;
+            else if (len<=16)  lenStat[3][2]++;
+            else if (len<=32)  lenStat[4][2]++;
+            else if (len<=64)  lenStat[5][2]++;
+            else if (len<=128) lenStat[6][2]++;
+            else if (len<=256) lenStat[6][2]++;
+
+            PutNBits((*esc>>(8-escBits)), escBits);     /* escBits>=0 */
+            PutBit(0);
+            PutBit(1);
+            PutBit(1);
+            PutValue(len-1);
+            PutRleByte(*data);
+
+            tmp = 8*len -escBits -3 -LenValue(len-1) -LenRleByte(*data);
+            gainedRle += tmp;
+            gainedSRle += tmp;
+
+            timesRle++;
+            timesSRle++;
+            return 0;
+        }
+        if (len<3) {
+            while (len--)
+                OutputNormal(esc, data, *esc);
+            return 0;
+        }
+
+        if (len <= maxrlelen) {
+            /* Run-length encoding */
+            PutNBits((*esc>>(8-escBits)), escBits);     /* escBits>=0 */
+
+            PutBit(0);
+            PutBit(1);
+            PutBit(1);
+
+            PutValue((1<<maxGamma) + (((len-1)&0xff)>>(8-maxGamma)));
+
+            PutNBits((len-1), 8-maxGamma);
+            PutValue(((len-1)>>8) + 1);
+            PutRleByte(*data);
+
+            tmp = 8*len -escBits -3 -maxGamma -8 -LenValue(((len-1)>>8)+1)
+                -LenRleByte(*data);
+            gainedRle += tmp;
+            gainedLRle += tmp;
+
+            timesRle++;
+            timesLRle++;
+            return 0;
+        }
+
+        /* Run-length encoding */
+        PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
+
+        PutBit(0);
+        PutBit(1);
+        PutBit(1);
+
+        PutValue((1<<maxGamma) + (((maxrlelen-1)&0xff)>>(8-maxGamma)));
+
+        PutNBits((maxrlelen-1) & 0xff, 8-maxGamma);
+        PutValue(((maxrlelen-1)>>8)+1);
+        PutRleByte(*data);
+
+        tmp = 8*maxrlelen -escBits -3 -maxGamma -8
+            -LenValue(((maxrlelen-1)>>8)+1) -LenRleByte(*data);
+        gainedRle += tmp;
+        gainedLRle += tmp;
+        timesRle++;
+        timesLRle++;
+        len -= maxrlelen;
+        data += maxrlelen;
+    }
+    return 0;
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+int LenLz(int lzlen, int lzpos) {
+    if (lzlen==2) {
+        if (lzpos <= 256) return escBits + 2 + 8;
+        else              return 100000;
+    }
+
+    return escBits + 8 + extraLZPosBits +
+           LenValue(((lzpos-1)>>(8+extraLZPosBits))+1) +
+           LenValue(lzlen-1);
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+int OutputLz(int *esc, int lzlen, int lzpos, char *data ATTRIBUTE_UNUSED, int curpos) {
+    if (lzlen==2)        lenStat[0][1]++;
+    else if (lzlen<=4)   lenStat[1][1]++;
+    else if (lzlen<=8)   lenStat[2][1]++;
+    else if (lzlen<=16)  lenStat[3][1]++;
+    else if (lzlen<=32)  lenStat[4][1]++;
+    else if (lzlen<=64)  lenStat[5][1]++;
+    else if (lzlen<=128) lenStat[6][1]++;
+    else if (lzlen<=256) lenStat[7][1]++;
+
+    if (lzlen >= 2 && lzlen <= maxlzlen) {
+        int tmp;
+
+        PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
+
+        tmp = ((lzpos-1)>>(8+extraLZPosBits))+2;
+        if (tmp==2)         lenStat[0][0]++;
+        else if (tmp<=4)    lenStat[1][0]++;
+        else if (tmp<=8)    lenStat[2][0]++;
+        else if (tmp<=16)   lenStat[3][0]++;
+        else if (tmp<=32)   lenStat[4][0]++;
+        else if (tmp<=64)   lenStat[5][0]++;
+        else if (tmp<=128)  lenStat[6][0]++;
+        else if (tmp<=256)  lenStat[6][0]++;
+
+        if (lzlen==2) {
+            PutValue(lzlen-1);
+            PutBit(0);
+            if (lzpos > 256) fprintf(stderr,"ERROR at %d: lzpos too long (%d) for lzlen==2\n",curpos, lzpos);
+        }
+        else {
+            PutValue(lzlen-1);
+            PutValue( ((lzpos-1) >> (8+extraLZPosBits)) +1);
+            PutNBits( ((lzpos-1) >> 8), extraLZPosBits);
+        }
+        PutNBits(((lzpos-1) & 0xff) ^ 0xff, 8);
+
+        gainedLz += 8*lzlen -LenLz(lzlen, lzpos);
+        timesLz++;
+        return 3;
+    }
+    fprintf(stderr, "ERROR: lzlen too short/long (%d)\n", lzlen);
+    return lzlen;
+}
+
+
+
+/* Non-recursive version */
+/* NOTE! IMPORTANT! the "length" array length must be inlen+1 */
+
+//=============================================================================
+//
+//=============================================================================
+int OptimizeLength(int optimize) {
+    int i;
+
+    length[inlen] = 0;          /* one off the end, our 'target' */
+    for (i=inlen-1; i>=0; i--) {
+        int r1 = 8 + length[i+1], r2, r3;
+
+        if (!lzlen[i] && !rle[i] && (!lzlen2 || !lzlen2[i])) {
+            length[i] = r1;
+            mode[i] = LITERAL;
+            continue;
+        }
+
+        /* If rle>maxlzlen, skip to the start of the rle-maxlzlen.. */
+        if (rle[i] > maxlzlen && elr[i] > 1) {
+            int z = elr[i];
+
+            i -= elr[i];
+
+            r2 = LenRle(rle[i], indata[i]) + length[i+ rle[i]];
+            if (optimize) {
+                int ii, mini = rle[i], minv = r2;
+
+                int bot = rle[i] - (1<<maxGamma);
+                if (bot < 2)
+                    bot = 2;
+
+                for (ii=mini-1; ii>=bot; ii--) {
+                    int v = LenRle(ii, indata[i]) + length[i + ii];
+                    if (v < minv) {
+                        minv = v;
+                        mini = ii;
+                    }
+                }
+                if (minv != r2) {
+                    lzopt += r2 - minv;
+                    rle[i] = mini;
+                    r2 = minv;
+                }
+            }
+            length[i] = r2;
+            mode[i] = RLE;
+
+            for (; z>=0; z--) {
+                length[i+z] = r2;
+                mode[i+z] = RLE;
+            }
+            continue;
+        }
+        r3 = r2 = r1 + 1000; /* r3 >= r2 > r1 */
+
+        if (rle[i]) {
+            r2 = LenRle(rle[i], indata[i]) + length[i+ rle[i]];
+
+            if (optimize) {
+                int ii, mini = rle[i], minv = r2;
+
+                /* Check only the original length and all shorter
+                   lengths that are power of two.
+
+                   Does not really miss many 'minimums' this way,
+                   at least not globally..
+
+                   Makes the assumption that the Elias Gamma Code is
+                   used, i.e. values of the form 2^n are 'optimal' */
+                ii = 2;
+                while (rle[i] > ii) {
+                    int v = LenRle(ii, indata[i]) + length[i + ii];
+                    if (v < minv) {
+                        minv = v;
+                        mini = ii;
+                    }
+                    ii <<= 1;
+                }
+                if (minv != r2) {
+                    lzopt += r2 - minv;
+                    rle[i] = mini;
+                    r2 = minv;
+                }
+            }
+        }
+        if (lzlen[i]) {
+            r3 = LenLz(lzlen[i], lzpos[i]) + length[i + lzlen[i]];
+
+            if (optimize && lzlen[i]>2) {
+                int ii, mini = lzlen[i], minv = r3;
+                int topLen = LenLz(lzlen[i], lzpos[i])
+                    - LenValue(lzlen[i]-1);
+
+                /* Check only the original length and all shorter
+                   lengths that are power of two.
+
+                   Does not really miss many 'minimums' this way,
+                   at least not globally..
+
+                   Makes the assumption that the Elias Gamma Code is
+                   used, i.e. values of the form 2^n are 'optimal' */
+                ii = 4;
+                while (lzlen[i] > ii) {
+                    int v = topLen + LenValue(ii-1) + length[i + ii];
+                    if (v < minv) {
+                        minv = v;
+                        mini = ii;
+                    }
+                    ii <<= 1;
+                }
+                /*
+                  Note:
+                  2-byte optimization checks are no longer done
+                  with the rest, because the equation gives too long
+                  code lengths for 2-byte matches if extraLzPosBits>0.
+                  */
+                /* Two-byte rescan/check */
+                if (backSkip[i] && backSkip[i] <= 256) {
+                    /* There are previous occurrances (near enough) */
+                    int v = LenLz(2, (int)backSkip[i]) + length[i + 2];
+
+                    if (v < minv) {
+                        minv = v;
+                        mini = 2;
+                        lzlen[i] = mini;
+                        r3 = minv;
+                        lzpos[i] = (int)backSkip[i];
+                    }
+                }
+                if (minv != r3 && minv < r2) {
+                    lzopt += r3 - minv;
+                    lzlen[i] = mini;
+                    r3 = minv;
+                }
+            }
+        }
+
+        if (r2 <= r1) {
+            if (r2 <= r3) {
+                length[i] = r2;
+                mode[i]   = RLE;
+            }
+            else {
+                length[i] = r3;
+                mode[i]   = LZ77;
+            }
+        }
+        else {
+            if (r3 <= r1) {
+                length[i] = r3;
+                mode[i]   = LZ77;
+            }
+            else {
+                length[i] = r1;
+                mode[i]   = LITERAL;
+            }
+        }
+        if (lzlen2 && lzlen2[i] > 3) {
+            r3 = escBits + 2*maxGamma + 16 + LenValue(lzlen2[i]-1) + length[i + lzlen2[i]];
+            //r3 = LenDLz(lzlen2[i], lzpos2[i]) + length[i + lzlen2[i]];
+            if (r3 < length[i]) {
+                length[i] = r3;
+                mode[i]   = DLZ;
+            }
+        }
+    }
+    return length[0];
+}
+
+
+/*
+    The algorithm in the OptimizeEscape() works as follows:
+    1) Only unpacked bytes are processed, they are marked
+       with MMARK. We proceed from the end to the beginning.
+       Variable A (old/new length) is updated.
+    2) At each unpacked byte, one and only one possible
+       escape matches. A new escape code must be selected
+       for this case. The optimal selection is the one which
+       provides the shortest number of escapes to the end
+       of the file,
+        i.e. A[esc] = 1+min(A[0], A[1], .. A[states-1]).
+       For other states A[esc] = A[esc];
+       If we change escape in this byte, the new escape is
+       the one with the smallest value in A.
+    3) The starting escape is selected from the possibilities
+       and mode 0 is restored to all mode 3 locations.
+
+ */
+
+//=============================================================================
+//
+//=============================================================================
+int OptimizeEscape(int *startEscape, int *nonNormal) {
+    int  i, j, states = (1<<escBits);
+    long minp = 0, minv = 0, other = 0;
+    long a[256]; /* needs int/long */
+    long b[256]; /* Remembers the # of escaped for each */
+    int  esc8 = 8-escBits;
+
+    for (i=0; i<256; i++) b[i] = a[i] = -1;
+
+    if (states>256) {
+        fprintf(stderr, "Escape optimize: only 256 states (%d)!\n",states);
+        return 0;
+    }
+
+    /* Mark those bytes that are actually outputted */
+    for (i=0; i<inlen; ) {
+        switch (mode[i]) {
+            case DLZ:
+                other++;
+                i += lzlen2[i];
+                break;
+
+            case LZ77:
+                other++;
+                i += lzlen[i];
+                break;
+
+            case RLE:
+                other++;
+                i += rle[i];
+                break;
+
+            /*case LITERAL:*/
+            default:
+                mode[i++] = MMARK; /* mark it used so we can identify it */
+                break;
+        }
+    }
+
+    for (i=inlen-1; i>=0; i--) {
+        /* Using a table to skip non-normal bytes does not help.. */
+        if (mode[i] == MMARK) {
+            int k = (indata[i] >> esc8);
+
+            /* Change the tag values back to normal */
+            mode[i] = LITERAL;
+
+            /*
+                k are the matching bytes,
+                minv is the minimum value,
+                minp is the minimum index
+             */
+
+            newesc[i] = (minp << esc8);
+            a[k] = minv + 1;
+            b[k] = b[minp] + 1;
+            if (k==minp) {
+                /* Minimum changed -> need to find a new minimum */
+                /* a[k] may still be the minimum */
+                minv++;
+                for (k=states-1; k>=0; k--) {
+                    if (a[k] < minv) {
+                        minv = a[k];
+                        minp = k;
+                        /*
+                            There may be others, but the first one that
+                            is smaller than the old minimum is equal to
+                            any other new minimum.
+                         */
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /* Select the best value for the initial escape */
+    if (startEscape) {
+        i = inlen;      /* make it big enough */
+        for (j=states-1; j>=0; j--) {
+            if (a[j] <= i) {
+                *startEscape = (j << esc8);
+                i = a[j];
+            }
+        }
+    }
+    if (nonNormal)
+        *nonNormal = other;
+    return b[startEscape ? (*startEscape>>esc8) : 0];
+}
+
+
+//=============================================================================
+// Initialize the RLE byte code table according to all RLE's found so far O(n)
+//=============================================================================
+void InitRle(int flags ATTRIBUTE_UNUSED) {
+    int p, mr, mv, i;
+
+    for (i=1; i<32; i++) {
+        mr = -1;
+        mv = 0;
+
+        for (p=0; p<256; p++) {
+            if (rleHist[p] > mv) {
+                mv = rleHist[p];
+                mr = p;
+            }
+        }
+        if (mv>0) {
+            rleValues[i] = mr;
+            rleHist[mr] = -1;
+        } else
+            break;
+    }
+    InitRleLen();
+}
+
+
+//=============================================================================
+// Initialize the RLE byte code table according to RLE's actually used O(n)
+//=============================================================================
+void OptimizeRle(int flags) {
+    int p, mr, mv, i;
+
+    if ((flags & F_NORLE)) {
+        rleUsed = 0;
+        return;
+    }
+    if (flags & F_STATS) fprintf(stderr, "RLE Byte Code Re-Tune, RLE Ranks:\n");
+
+    for (p=0; p<256; p++) rleHist[p] = 0;
+
+    for (p=0; p<inlen; ) {
+        switch (mode[p]) {
+            case DLZ:
+                p += lzlen2[p];
+                break;
+            case LZ77:
+                p += lzlen[p];
+                break;
+
+            case RLE:
+                rleHist[indata[p]]++;
+                p += rle[p];
+                break;
+
+            default:
+                p++;
+                break;
+        }
+    }
+
+    for (i=1; i<32; i++) {
+        mr = -1;
+        mv = 0;
+
+        for (p=0; p<256; p++) {
+            if (rleHist[p] > mv) {
+                mv = rleHist[p];
+                mr = p;
+            }
+        }
+        if (mv>0) {
+            rleValues[i] = mr;
+            if (flags & F_STATS) {
+                fprintf(stderr, " %2d.0x%02x %-3d ", i, mr, mv);
+                if (!((i - 1) % 6)) fprintf(stderr, "\n");
+            }
+            rleHist[mr] = -1;
+        }
+        else {
+            break;
+        }
+    }
+    rleUsed = i-1;
+
+    if (flags & F_STATS)
+        if (((i - 1) % 6)!=1) fprintf(stderr, "\n");
+    InitRleLen();
+}
+
+
+//=============================================================================
+//
+//=============================================================================
+int PackLz77(int lzsz, int flags, int *startEscape,int endAddr, int memEnd, int type)
+{
+    int i, j, outlen, p, headerSize;
+    int escape;
+    unsigned char *hashValue;
+    unsigned char *a;
+    int k;
+
+    unsigned short *lastPair;
+    unsigned short err_occured = 0;
+
+    int rescan = 0;
+
+
+
+
+    if (lzsz < 0 || lzsz > lrange) {
+        fprintf(stderr, "LZ range must be from 0 to %d (was %d). Set to %d.\n",
+                lrange, lzsz, lrange);
+        lzsz = lrange;
+    }
+    if (lzsz > 65535) {
+        fprintf(stderr,
+                "LZ range must be from 0 to 65535 (was %d). Set to 65535.\n",
+                lzsz);
+        lzsz = 65535;
+    }
+    if (!lzsz) fprintf(stderr, "Warning: zero LZ range. Only RLE packing used.\n");
+
+    InitRleLen();
+    length = (int *)calloc(sizeof(int), inlen + 1);
+    mode   = (unsigned char  *)calloc(sizeof(unsigned char),  inlen);
+    rle    = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+    elr    = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+    lzlen  = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+    lzpos  = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+    if ((type & FIXF_DLZ)) {
+        lzlen2  = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+        lzpos2  = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+    }
+    else {
+        lzlen2 = lzpos2 = NULL;
+    }
+    newesc    = (unsigned char  *)calloc(sizeof(unsigned char),  inlen);
+    backSkip  = (unsigned short *)calloc(sizeof(unsigned short), inlen);
+    hashValue = (unsigned char  *)malloc(inlen);
+    lastPair  = (unsigned short *)calloc(sizeof(unsigned short), 256*256);
+
+
+    /* error checking */
+    if (!length || !mode || !rle || !elr || !lzlen || !lzpos || !newesc ||
+        !lastPair || !backSkip
+        || ((type & FIXF_DLZ) && (!lzlen2 || !lzpos2))
+        || !hashValue)
+    {
+        fprintf(stderr, "ERROR: Memory allocation failed!\n");
+        err_occured = 1;
+        goto errorexit;
+    }
+
+    i = 0;
+    j = 0;
+    a = indata + inlen;
+    for (p=inlen-1; p>=0; p--) {
+        k = j;
+        j = i;
+        i = *--a;       /* Only one read per position */
+        hashValue[p] = i*3 + j*5 + k*7; /* 7.95 % */
+    }
+
+    /* Detect all RLE and LZ77 jump possibilities */
+    for (p=0; p<inlen; p++) {
+        if (flags & F_VERBOSE) {
+            if (!(p & 2047)) {
+                fprintf(stderr, "\r%d ", p);
+                fflush(stderr);     /* for SAS/C */
+            }
+        }
+        /* check run-length code - must be done, LZ77 search needs it! */
+        if (rle[p] <= 0) {
+            unsigned char *a = indata + p;
+            int val = *a++; /* if this were uchar, it would go to stack..*/
+            int top = inlen - p;
+            int rlelen = 1;
+
+            /* Loop for the whole RLE */
+            while (rlelen<top && *a++ == (unsigned char)val) rlelen++;
+
+            if (rlelen>=2) {
+                rleHist[indata[p]]++;
+
+                for (i=rlelen-1; i>=0; i--) {
+                    rle[p+i] = rlelen-i;
+                    elr[p+i] = i;       /* For RLE backward skipping */
+                }
+
+            }
+        }
+
+        /* check LZ77 code */
+        if (p+rle[p]+1<inlen) {
+            int bot = p - lzsz, maxval, maxpos, rlep = rle[p];
+            unsigned char hashCompare = hashValue[p];
+
+            /*
+                There's always 1 equal byte, although it may
+                not be marked as RLE.
+             */
+            if (rlep <= 0)
+                rlep = 1;
+            if (bot < 0)
+                bot = 0;
+            bot += (rlep-1);
+
+            /*
+                First get the shortest possible match (if any).
+                If there is no 2-byte match, don't look further,
+                because there can't be a longer match.
+             */
+            i = (int)lastPair[ (indata[p]<<8) | indata[p+1] ] -1;
+            if (i>=0 && i>=bot) {
+                /* Got a 2-byte match at least */
+                maxval = 2;
+                maxpos = p-i;
+
+                /*
+                    A..AB       rlep # of A's, B is something else..
+
+                    Search for bytes that are in p + (rlep-1), i.e.
+                    the last rle byte ('A') and the non-matching one
+                    ('B'). When found, check if the rle in the compare
+                    position (i) is long enough (i.e. the same number
+                    of A's at p and i-rlep+1).
+
+                    There are dramatically less matches for AB than for
+                    AA, so we get a huge speedup with this approach.
+                    We are still guaranteed to find the most recent
+                    longest match there is.
+                 */
+
+                i = (int)lastPair[(indata[p+(rlep-1)]<<8) | indata[p+rlep]] -1;
+                while (i>=bot /* && i>=rlep-1 */) {   /* bot>=rlep-1, i>=bot  ==> i>=rlep-1 */
+
+                    /* Equal number of A's ? */
+                    if (!(rlep-1) || rle[i-(rlep-1)]==rlep) {   /* 'head' matches */
+                        /* rlep==1 ==> (rlep-1)==0 */
+                        /* ivanova.run: 443517 rlep==1,
+                           709846 rle[i+1-rlep]==rlep */
+
+                        /*
+                            Check the hash values corresponding to the last
+                            two bytes of the currently longest match and
+                            the first new matching(?) byte. If the hash
+                            values don't match, don't bother to check the
+                            data itself.
+                         */
+                        if (
+                            hashValue[i+maxval-rlep-1] == hashCompare
+                           ) {
+                            unsigned char *a = indata + i+2;    /* match  */
+                            unsigned char *b = indata + p+rlep-1+2;/* curpos */
+                            int topindex = inlen-(p+rlep-1);
+
+                            /* the 2 first bytes ARE the same.. */
+                            j = 2;
+                            while (j < topindex && *a++==*b++)
+                                j++;
+
+                            if (j + rlep-1 > maxval) {
+                                int tmplen = j+rlep-1, tmppos = p-i+rlep-1;
+
+                                if (tmplen > maxlzlen)
+                                    tmplen = maxlzlen;
+
+                                /* Accept only versions that really are shorter */
+                                if (tmplen*8 - LenLz(tmplen, tmppos) >
+                                    maxval*8 - LenLz(maxval, maxpos)) {
+                                    maxval = tmplen;
+                                    maxpos = tmppos;
+                                    hashCompare = hashValue[p+maxval-2];
+                                }
+                                if (maxval == maxlzlen)
+                                    break;
+                            }
+                        }
+                    }
+                    if (!backSkip[i])
+                        break; /* No previous occurrances (near enough) */
+                    i -= (int)backSkip[i];
+                }
+
+                /*
+                    If there is 'A' in the previous position also,
+                    RLE-like LZ77 is possible, although rarely
+                    shorter than real RLE.
+                 */
+                if (p && rle[p-1] > maxval) {
+                    maxval = rle[p-1] - 1;
+                    maxpos = 1;
+                }
+                /*
+                    Last, try to find as long as possible match
+                    for the RLE part only.
+                 */
+                if (maxval < maxlzlen && rlep > maxval) {
+                    bot = p - lzsz;
+                    if (bot < 0)
+                        bot = 0;
+
+                    /* Note: indata[p] == indata[p+1] */
+                    i = (int)lastPair[indata[p]*257] -1;
+                    while (/* i>= rlep-2 &&*/ i>=bot) {
+                        if (elr[i] + 2 > maxval) {
+                            maxval = min(elr[i] + 2, rlep);
+                            maxpos = p - i + (maxval-2);
+                            if(maxval == rlep)
+                                break; /* Got enough */
+                        }
+                        i -= elr[i];
+                        if (!backSkip[i])
+                            break; /* No previous occurrances (near enough) */
+                        i -= (int)backSkip[i];
+                    }
+                }
+                if (p+maxval > inlen) {
+                    fprintf(stderr,"Error @ %d, lzlen %d, pos %d - exceeds inlen\n",p, maxval, maxpos);
+                    maxval = inlen - p;
+                }
+                if (maxpos<=256 || maxval > 2) {
+                    if (maxpos < 0) fprintf(stderr, "Error @ %d, lzlen %d, pos %d\n",p, maxval, maxpos);
+                    lzlen[p] = (maxval<maxlzlen)?maxval:maxlzlen;
+                    lzpos[p] = maxpos;
+                }
+            }
+        }
+
+        /* check LZ77 code again, ROT1..255 */
+        if ((type & FIXF_DLZ) && p+rle[p]+1<inlen) {
+        int rot;
+
+        for (rot = 1; rot < 255; rot++) {
+            int bot = p - /*lzsz*/256, maxval, maxpos, rlep = rle[p];
+            unsigned char valueCompare = (indata[p+2] + rot) & 0xff;
+
+            if (rlep <= 0) rlep = 1;
+            if (bot < 0)   bot = 0;
+            bot += (rlep-1);
+
+            i = (int)lastPair[ (((indata[p] + rot) & 0xff)<<8) |
+                                ((indata[p+1] + rot) & 0xff) ] -1;
+            if (i>=0 && i>=bot) {
+                maxval = 2;
+                maxpos = p-i;
+
+                /*
+                    A..AB       rlep # of A's, B is something else..
+
+                    Search for bytes that are in p + (rlep-1), i.e.
+                    the last rle byte ('A') and the non-matching one
+                    ('B'). When found, check if the rle in the compare
+                    position (i) is long enough (i.e. the same number
+                    of A's at p and i-rlep+1).
+
+                    There are dramatically less matches for AB than for
+                    AA, so we get a huge speedup with this approach.
+                    We are still guaranteed to find the most recent
+                    longest match there is.
+                 */
+
+                i = (int)lastPair[(((indata[p+(rlep-1)] + rot) & 0xff)<<8) |
+                                   ((indata[p+rlep] + rot) & 0xff)] -1;
+                while (i>=bot /* && i>=rlep-1 */) {   /* bot>=rlep-1, i>=bot  ==> i>=rlep-1 */
+
+                    /* Equal number of A's ? */
+                    if (!(rlep-1) || rle[i-(rlep-1)]==rlep) {   /* 'head' matches */
+                        /* rlep==1 ==> (rlep-1)==0 */
+                        /* ivanova.run: 443517 rlep==1,
+                           709846 rle[i+1-rlep]==rlep */
+
+                        /*
+                            Check the hash values corresponding to the last
+                            two bytes of the currently longest match and
+                            the first new matching(?) byte. If the hash
+                            values don't match, don't bother to check the
+                            data itself.
+                         */
+                        if (indata[i+maxval-rlep+1] == valueCompare) {
+                            unsigned char *a = indata + i+2;    /* match  */
+                            unsigned char *b = indata + p+rlep-1+2;/* curpos */
+                            int topindex = inlen-(p+rlep-1);
+
+                            /* the 2 first bytes ARE the same.. */
+                            j = 2;
+                            while (j < topindex && *a++==((*b++ + rot) & 0xff))
+                                j++;
+
+                            if (j + rlep-1 > maxval) {
+                                int tmplen = j+rlep-1, tmppos = p-i+rlep-1;
+
+                                if (tmplen > maxlzlen)
+                                    tmplen = maxlzlen;
+
+                                /* Accept only versions that really are shorter */
+                                if (tmplen*8 - LenLz(tmplen, tmppos) >
+                                    maxval*8 - LenLz(maxval, maxpos)) {
+                                    maxval = tmplen;
+                                    maxpos = tmppos;
+
+                                    valueCompare = (indata[p+maxval] + rot) & 0xff;
+                                }
+                                if (maxval == maxlzlen)
+                                    break;
+                            }
+                        }
+                    }
+                    if (!backSkip[i])
+                        break; /* No previous occurrances (near enough) */
+                    i -= (int)backSkip[i];
+                }
+
+                if (p+maxval > inlen) {
+                    fprintf(stderr,"Error @ %d, lzlen %d, pos %d - exceeds inlen\n",p, maxval, maxpos);
+                    maxval = inlen - p;
+                }
+                if (maxval > 3 && maxpos <= 256 &&
+                    (maxval > lzlen2[p] ||
+                     (maxval == lzlen2[p] && maxpos < lzpos2[p]))) {
+                    if (maxpos < 0)
+                        fprintf(stderr, "Error @ %d, lzlen %d, pos %d\n",p, maxval, maxpos);
+                    lzlen2[p] = (maxval<maxlzlen)?maxval:maxlzlen;
+                    lzpos2[p] = maxpos;
+                }
+            }
+        }
+        if (lzlen2[p] <= lzlen[p] || lzlen2[p] <= rle[p]) {
+            lzlen2[p] = lzpos2[p] = 0;
+        }
+        }
+
+        /* Update the two-byte history ('hash table') &
+           backSkip ('linked list') */
+        if (p+1<inlen) {
+            int index = (indata[p]<<8) | indata[p+1];
+            int ptr = p - (lastPair[index]-1);
+
+            if (ptr > p || ptr > 0xffff)
+                ptr = 0;
+
+            backSkip[p] = ptr;
+            lastPair[index] = p+1;
+        }
+    }
+    if ((flags & F_NORLE)) {
+        for (p=1; p<inlen; p++) {
+            if (rle[p-1]-1 > lzlen[p]) {
+                lzlen[p] = (rle[p]<maxlzlen)?rle[p]:maxlzlen;
+                lzpos[p] = 1;
+            }
+        }
+        for (p=0; p<inlen; p++) {
+            rle[p] = 0;
+        }
+    }
+
+    if (flags & F_VERBOSE) {
+        fprintf(stderr, "\rChecked: %d \n", p);
+        fflush(stderr);
+    }
+
+
+    /* Initialize the RLE selections */
+    InitRle(flags);
+
+    /* Check the normal bytes / all ratio */
+    if ((flags & F_AUTO)) {
+        int mb, mv;
+
+        if (flags & F_VERBOSE) {
+            fprintf(stderr, "Selecting the number of escape bits.. ");
+            fflush(stderr);
+        }
+
+        /*
+            Absolute maximum number of escaped bytes with
+            the escape optimize is 2^-n, where n is the
+            number of escape bits used.
+
+            This worst case happens only on equal-
+            distributed normal bytes (01230123..).
+            This is why the typical values are so much smaller.
+         */
+
+        mb = 0;
+        mv = 8*OUT_SIZE;
+        for (escBits=1; escBits<9; escBits++) {
+            int escaped, other = 0, c;
+
+            escMask = (0xff00>>escBits) & 0xff;
+
+            /* Find the optimum path for selected escape bits (no optimize) */
+            OptimizeLength(0);
+
+            /* Optimize the escape selections for this path & escBits */
+            escaped = OptimizeEscape(&escape, &other);
+
+            /* Compare value: bits lost for escaping -- bits lost for prefix */
+            c = (escBits+3)*escaped + other*escBits;
+            if (flags & F_STATS) {
+                fprintf(stderr, " %d:%d", escBits, c);
+                fflush(stderr); /* for SAS/C */
+            }
+            if (c < mv) {
+                mb = escBits;
+                mv = c;
+            } else {
+                /* minimum found */
+                break;
+            }
+            if (escBits==4 && (flags & F_STATS)) fprintf(stderr, "\n");
+        }
+        if (mb==1) {    /* Minimum was 1, check 0 */
+            int escaped;
+
+            escBits = 0;
+            escMask = 0;
+
+            /* Find the optimum path for selected escape bits (no optimize) */
+            OptimizeLength(0);
+            /* Optimize the escape selections for this path & escBits */
+            escaped = OptimizeEscape(&escape, NULL);
+
+            if ((flags & F_STATS)) {
+                fprintf(stderr, " %d:%d", escBits, 3*escaped);
+                fflush(stderr); /* for SAS/C */
+            }
+            if (3*escaped < mv) {
+                mb = 0;
+                /* mv = 3*escaped; */
+            }
+        }
+        if ((flags & F_STATS)) fprintf(stderr, "\n");
+
+        if (flags & F_VERBOSE) fprintf(stderr, "Selected %d-bit escapes\n", mb);
+        escBits = mb;
+        escMask = (0xff00>>escBits) & 0xff;
+    }
+
+
+    if (!(flags & F_NOOPT)) {
+        if (flags & F_VERBOSE) {
+            fprintf(stderr, "Optimizing LZ77 and RLE lengths...");
+            fflush(stderr);
+        }
+    }
+
+    /* Find the optimum path (optimize) */
+    OptimizeLength((flags & F_NOOPT)?0:1);
+    if (flags & F_STATS) {
+        if (!(flags & F_NOOPT)) fprintf(stderr, " gained %d units.\n", lzopt/8);
+    }
+    else {
+        if (flags & F_VERBOSE) fprintf(stderr, "\n");
+    }
+
+    if (1 || (flags & F_AUTOEX)) {
+        long lzstat[5] = {0,0,0,0,0}, i, cur = 0, old = extraLZPosBits;
+
+        if (flags & F_VERBOSE) {
+            fprintf(stderr, "Selecting LZPOS LO length.. ");
+            fflush(stderr);
+        }
+
+        for (p=0; p<inlen; ) {
+            switch (mode[p]) {
+            case LZ77:
+                extraLZPosBits = 0;
+                lzstat[0] += LenLz(lzlen[p], lzpos[p]);
+                extraLZPosBits = 1;
+                lzstat[1] += LenLz(lzlen[p], lzpos[p]);
+                extraLZPosBits = 2;
+                lzstat[2] += LenLz(lzlen[p], lzpos[p]);
+                extraLZPosBits = 3;
+                lzstat[3] += LenLz(lzlen[p], lzpos[p]);
+                extraLZPosBits = 4;
+                lzstat[4] += LenLz(lzlen[p], lzpos[p]);
+                p += lzlen[p];
+                break;
+            case DLZ:
+                p += lzlen2[p];
+                break;
+            case RLE:
+                p += rle[p];
+                break;
+
+            default:
+                p++;
+                break;
+            }
+        }
+        for (i=0; i<5; i++) {
+            if (flags & F_STATS) fprintf(stderr, " %ld:%ld", i + 8, lzstat[i]);
+
+            if (lzstat[i] < lzstat[cur]) cur = i;
+        }
+        extraLZPosBits = (flags & F_AUTOEX)?cur:old;
+
+        if (flags & F_STATS) fprintf(stderr, "\n");
+
+        if (flags & F_VERBOSE) {
+            fprintf(stderr, "Selected %d-bit LZPOS LO part\n",extraLZPosBits + 8);
+            if (cur != old) fprintf(stderr,"Note: Using option -p%ld you may get better results.\n",cur);
+        }
+        /* Find the optimum path (optimize) */
+        if (extraLZPosBits != old) OptimizeLength((flags & F_NOOPT)?0:1);
+    }
+    if (1) {
+        long stat[4] = {0,0,0,0};
+
+        for (p=0; p<inlen; ) {
+            switch (mode[p]) {
+            case LZ77:
+                if ((lzpos[p] >> 8)+1 > (1<<maxGamma))
+                    stat[3]++;
+                if (lzlen[p] > (1<<maxGamma))
+                    stat[0]++;
+                p += lzlen[p];
+                break;
+
+            case RLE:
+                if (rle[p] > (1<<(maxGamma-1))) {
+                    if (rle[p] <= (1<<maxGamma))
+                        stat[1]++;
+
+                }
+                p += rle[p];
+                break;
+            case DLZ:
+                p += lzlen2[p];
+                break;
+            default:
+                p++;
+                break;
+            }
+        }
+        /* TODO: better formula.. */
+        if (maxGamma < 7 && stat[0] + stat[1] + stat[3] > 10) {
+            if (flags & F_VERBOSE) fprintf(stderr,"Note: Using option -m%d you may get better results.\n",maxGamma+1);
+        }
+        if (maxGamma > 5 && stat[0] + stat[1] + stat[3] < 4) {
+            if (flags & F_VERBOSE) fprintf(stderr,"Note: Using option -m%d you may get better results.\n",maxGamma-1);
+        }
+    }
+
+    /* Optimize the escape selections */
+    OptimizeEscape(&escape, NULL);
+    if (startEscape) *startEscape = escape;
+    OptimizeRle(flags); /* Retune the RLE selections */
+
+    if (flags & F_VERBOSE) {
+        int oldEscape = escape;
+        if (flags & F_VERBOSE) printf("normal RLE  LZLEN LZPOS(absolute)\n\n");
+
+        for (p=0; p<inlen; ) {
+            switch (mode[p]) {
+            case LZ77:
+                mode[p - lzpos[p]] |= MMARK; /* Was referred to by lz77 */
+                p += lzlen[p];
+                break;
+            case RLE:
+                p += rle[p];
+                break;
+            case DLZ:
+                mode[p - lzpos2[p]] |= MMARK; /* Was referred to by lz77 */
+                p += lzlen2[p];
+                break;
+        /*  case LITERAL:
+            case MMARK:*/
+            default:
+                p++;
+                break;
+            }
+        }
+
+        j = 0;
+        for (p=0; p<inlen; p++) {
+            switch (mode[p]) {
+            case MMARK | DLZ:
+            case DLZ:
+                if (j==p) {
+                    if (flags & F_VERBOSE) printf(">");
+                    j += lzlen2[p];
+                } else
+                    printf(" ");
+                if (lzpos2) {
+                    if (flags & F_VERBOSE) printf(" %04x*%03d*+%02x", lzpos2[p], lzlen2[p],(indata[p] - indata[p-lzpos2[p]]) & 0xff);
+                }
+                if (flags & F_VERBOSE) printf(" 001   %03d   %03d  %04x(%04x)  %02x %s\n",
+                                              rle[p],lzlen[p],lzpos[p],p-lzpos[p],indata[p],
+                                              (mode[p] & MMARK)?"#":" ");
+                break;
+            case MMARK | LITERAL:
+            case LITERAL:
+                if (flags & F_VERBOSE) {
+                    if (j==p) printf(">");
+                    else      printf(" ");
+
+                    if (lzpos2) {
+                        printf(" %04x %03d +%02x", lzpos2[p], lzlen2[p],
+                               (indata[p] - indata[p-lzpos2[p]]) & 0xff);
+                    }
+                }
+                if (j==p) {
+                    if (flags & F_VERBOSE) {
+                        printf("*001*  %03d   %03d  %04x(%04x)  %02x %s %02x",
+                               rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
+                               (mode[p] & MMARK)?"#":" ", newesc[p]);
+                    }
+                    if ((indata[p] & escMask) == escape) {
+                        escape = newesc[p];
+                        if (flags & F_VERBOSE) printf("«");
+                    }
+                    if (flags & F_VERBOSE) printf("\n");
+                    j += 1;
+                } else {
+                    if (flags & F_VERBOSE) printf("*001*  %03d   %03d  %04x(%04x)  %02x %s %02x\n",
+                                                  rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
+                                                  (mode[p] & MMARK)?"#":" ", newesc[p]);
+                }
+                break;
+            case MMARK | LZ77:
+            case LZ77:
+                if (j==p) {
+                    if (flags & F_VERBOSE) printf(">");
+                    j += lzlen[p];
+                } else
+                    if (flags & F_VERBOSE) printf(" ");
+                if (lzpos2) {
+                    if (flags & F_VERBOSE) printf(" %04x %03d +%02x", lzpos2[p], lzlen2[p],
+                                                  (indata[p] - indata[p-lzpos2[p]]) & 0xff);
+                }
+                if (flags & F_VERBOSE) printf(" 001   %03d  *%03d* %04x(%04x)  %02x %s\n",
+                                              rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
+                                              (mode[p] & MMARK)?"#":" ");
+                break;
+            case MMARK | RLE:
+            case RLE:
+                if (j==p) {
+                    if (flags & F_VERBOSE) printf(">");
+                    j += rle[p];
+                } else
+                    if (flags & F_VERBOSE) printf(" ");
+                if (lzpos2) {
+                    if (flags & F_VERBOSE) printf(" %04x %03d +%02x", lzpos2[p], lzlen2[p],
+                                                  (indata[p] - indata[p-lzpos2[p]]) & 0xff);
+                }
+                if (flags & F_VERBOSE) printf(" 001  *%03d*  %03d  %04x(%04x)  %02x %s\n",
+                                              rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
+                                              (mode[p] & MMARK)?"#":" ");
+                break;
+            default:
+                j++;
+                break;
+            }
+            mode[p] &= ~MMARK;
+        }
+        escape = oldEscape;
+    }
+
+    for (p=0; p<inlen; ) {
+        switch (mode[p]) {
+        case LITERAL: /* normal */
+            length[p] = outPointer;
+
+            OutputNormal(&escape, indata+p, newesc[p]);
+            p++;
+            break;
+
+        case DLZ:
+            for (i=0; i<lzlen2[p]; i++) length[p+i] = outPointer;
+
+            PutNBits((escape>>(8-escBits)), escBits);
+            PutValue(lzlen2[p]-1);
+            PutValue((2<<maxGamma)-1);
+            PutNBits((indata[p] - indata[p-lzpos2[p]]) & 0xff, 8);
+            PutNBits(((lzpos2[p]-1) & 0xff) ^ 0xff, 8);
+            gainedDLz += 8*lzlen2[p] -(escBits + LenValue(lzlen2[p]-1) + 2*maxGamma + 16);
+            timesDLz++;
+            p += lzlen2[p];
+            break;
+
+        case LZ77: /* lz77 */
+
+            /* Not possible for smaller backSkip table
+               (the table is overwritten during previous use) */
+            /* Re-search matches to get the closest one */
+            if (lzopt && lzlen[p] > 2 && lzlen[p] > rle[p]) {
+                int bot = p - lzpos[p] + 1, i;
+                unsigned short rlep = rle[p];
+
+                if (!rlep)
+                    rlep = 1;
+                if (bot < 0)
+                    bot = 0;
+                bot += (rlep-1);
+
+                i = p - (int)backSkip[p];
+                while (i>=bot /* && i>=rlep-1 */) {
+                    /* Equal number of A's ? */
+                    if (rlep==1 || rle[i-rlep+1]==rlep) {       /* 'head' matches */
+                        unsigned char *a = indata + i+1;        /* match  */
+                        unsigned char *b = indata + p+rlep-1+1; /* curpos */
+                        int topindex = inlen-(p+rlep-1);
+
+                        j = 1;
+                        while (j < topindex && *a++==*b++)
+                            j++;
+
+                        if (j + rlep-1 >= lzlen[p]) {
+                            int tmppos = p-i+rlep-1;
+
+                            rescan +=
+                                LenLz(lzlen[p], lzpos[p]) -
+                                LenLz(lzlen[p], tmppos);
+                            lzpos[p] = tmppos;
+                            break;
+                        }
+                    }
+                    if (!backSkip[i])
+                        break; /* No previous occurrances (near enough) */
+                    i -= (int)backSkip[i];
+                }
+            }
+
+            for (i=0; i<lzlen[p]; i++)
+                length[p+i] = outPointer;
+            OutputLz(&escape, lzlen[p], lzpos[p], (char *)(indata+p-lzpos[p]), p);
+            p += lzlen[p];
+            break;
+
+        case RLE: /* rle */
+            for (i=0; i<rle[p]; i++)
+                length[p+i] = outPointer;
+            OutputRle(&escape, indata+p, rle[p]);
+            p += rle[p];
+            break;
+
+        default: /* Error Flynn :-) */
+            p++;
+            fprintf(stderr, "Internal error: mode %d\n", mode[p]);
+            break;
+        }
+    }
+    OutputEof(&escape);
+
+    i = inlen;
+    for (p=0; p<inlen; p++) {
+        int pos = (inlen - outPointer) + (int)length[p] - p;
+        i = min(i, pos);
+    }
+    if (i<0)
+        reservedBytes = -i + 2;
+    else
+        reservedBytes = 0;
+
+    // TOMTOM !!!
+
+    if ((type & FIXF_MACHMASK) == 0) {
+        headerSize = 16 + rleUsed;
+    } else
+    {
+        if (endAddr + reservedBytes + 3 > memEnd) {
+            type |= FIXF_WRAP;
+        } else {
+            type &= ~FIXF_WRAP;
+        }
+        headerSize = 47 + rleUsed - 31;
+    }
+    outlen = outPointer + headerSize;   /* unpack code */
+
+    if (flags & F_VERBOSE) fprintf(stderr, "In: %d, out: %d, ratio: %5.2f%% (%4.2f[%4.2f] b/B)"
+                                   ", gained: %5.2f%%\n",
+                                   inlen, outlen, (double)outlen*100.0/(double)inlen + 0.005,
+                                   8.0*(double)outlen/(double)inlen + 0.005,
+                                   8.0*(double)(outlen-headerSize+rleUsed+4)/(double)inlen + 0.005,
+                                   100.0 - (double)outlen*100.0/(double)inlen + 0.005);
+
+    if ((type & FIXF_DLZ)) {
+        if (flags & F_VERBOSE) {
+            fprintf(stderr, "Gained RLE: %d (S+L:%d+%d), DLZ: %d, LZ: %d, Esc: %d"
+                    ", Decompressor: %d\n",
+                    gainedRle/8, gainedSRle/8, gainedLRle/8, gainedDLz/8,
+                    gainedLz/8, -gainedEscaped/8, -headerSize);
+
+            fprintf(stderr, "Times  RLE: %d (%d+%d), DLZ: %d, LZ: %d, Esc: %d (normal: %d)"
+                    ", %d escape bit%s\n",
+                    timesRle, timesSRle, timesLRle, timesDLz,
+                    timesLz, timesEscaped, timesNormal,
+                    escBits, (escBits==1)?"":"s" );
+        }
+    }
+    else {
+        if (flags & F_VERBOSE) {
+            fprintf(stderr, "Gained RLE: %d (S+L:%d+%d), LZ: %d, Esc: %d"
+                    ", Decompressor: %d\n",
+                    gainedRle/8, gainedSRle/8, gainedLRle/8,
+                    gainedLz/8, -gainedEscaped/8, -headerSize);
+
+            fprintf(stderr, "Times  RLE: %d (%d+%d), LZ: %d, Esc: %d (normal: %d)"
+                    ", %d escape bit%s\n",
+                    timesRle, timesSRle, timesLRle,
+                    timesLz, timesEscaped, timesNormal,
+                    escBits, (escBits==1)?"":"s" );
+        }
+    }
+    if ((flags & F_STATS)) {
+        const char *ll[] = {"2", "3-4", "5-8", "9-16", "17-32", "33-64",
+                            "65-128", "129-256"};
+        fprintf(stderr, "(Gained by RLE Code: %d, LZPOS LO Bits %d"
+                ", maxLen: %d, tag bit/prim. %4.2f)\n",
+                gainedRlecode/8 - rleUsed,
+                extraLZPosBits + 8,
+                (2<<maxGamma),
+                (double)((timesRle+timesLz)*escBits +
+                         timesEscaped*(escBits + 3))/
+                (double)(timesRle+timesLz+timesNormal) + 0.0049);
+
+        fprintf(stderr, "   LZPOS HI+2 LZLEN S-RLE RLEcode\n");
+        fprintf(stderr, "   ------------------------------\n");
+        for (i=0; i<=maxGamma; i++) {
+            fprintf(stderr, "%-7s %5d %5d", ll[i],
+                    lenStat[i][0], lenStat[i][1]);
+            if (i<maxGamma)
+                fprintf(stderr, " %5d", lenStat[i][2]);
+            else
+                fprintf(stderr, "     -");
+
+            if (i<6)
+                fprintf(stderr, "   %5d%s\n", lenStat[i][3], (i==5)?"*":"");
+            else
+                fprintf(stderr, "       -\n");
+        }
+        fprintf(stderr, "LZ77 rescan gained %d bytes\n", rescan/8);
+    }
+
+errorexit:
+    if (rle)       free(rle);
+    if (elr)       free(elr);
+    if (lzlen)     free(lzlen);
+    if (lzpos)     free(lzpos);
+    if (length)    free(length);
+    if (mode)      free(mode);
+    if (newesc)    free(newesc);
+    if (lastPair)  free(lastPair);
+    if (backSkip)  free(backSkip);
+    if (hashValue) free(hashValue);
+    return err_occured;
+}
+
+#define NO_HEX_CHARACTER       255
+
+//=============================================================================
+// converts hexdigit to number
+//=============================================================================
+unsigned char hex2int(unsigned char c) {
+    c = tolower(c);
+
+    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+    if (c >= '0' && c <= '9') return c - '0';
+    return NO_HEX_CHARACTER;
+}
+
+
+//=============================================================================
+// converts hex text into binary
+//=============================================================================
+int ConvertText2Bin(unsigned char* ib,int origlen) {
+    int           pos;
+    int           cnt = 0;
+    int           searchforendofline = 0;
+    int           len_after_convert  = 0;
+    unsigned char val = 0;
+    unsigned char actual;
+
+    len_after_convert = 0;
+    for (pos = 0; pos < origlen;pos++) {
+        if (searchforendofline) {
+            if (ib[pos] == '\n') searchforendofline = 0;
+            continue;
+        }
+        if (ib[pos] == '/') {
+            cnt = 0;
+            if (pos < origlen-1 && ib[pos+1] == '/') searchforendofline = 1;
+            continue;
+        }
+
+        actual = hex2int(ib[pos]);
+        if (actual == NO_HEX_CHARACTER) {
+            cnt = 0;
+            continue;
+        }
+        if (cnt == 0) {
+            val = actual*16;
+            cnt++;
+        }
+        else {
+            val += actual;
+            cnt=0;
+            ib[len_after_convert++] = val;
+        }
+    }
+    return(len_after_convert);
+}
+
+
+//=============================================================================
+// as usual: the main, but a long one ...
+//=============================================================================
+int TTPack(int argc,char *argv[]) {
+    int   startAddr   = 0x258;
+    int   flags       = F_AUTO | F_AUTOEX;
+    int   lzlen       = -1;
+    int   buflen;
+    int   newlen;
+    int   startEscape;
+    int   n;
+    char *fileIn  = NULL;
+    char *fileOut = NULL;
+    FILE *infp;
+
+    unsigned long timeused = clock();
+
+    int   memStart    = 0x801;
+    int   memEnd      = 0x10000;
+    int   type        = 0;
+
+    quiet = 0;
+
+
+    TTPackInit();
+
+
+    lrange    = LRANGE;
+    maxlzlen  = MAXLZLEN;
+    maxrlelen = MAXRLELEN;
+
+    InitValueLen();
+
+    for (n=1; n<argc; n++) {
+        if (!strcmp(argv[n], "-fnorle"))      flags |= F_NORLE;
+        else if (!strcmp(argv[n], "-fdelta")) type  |= FIXF_DLZ;
+        else if (!strcmp(argv[n], "-hti"))    flags |= F_TEXTINPUT;
+        else if (!strcmp(argv[n], "-hto"))    flags |= F_TEXTOUTPUT;
+        else if (!strcmp(argv[n], "-quiet"))  flags &= ~F_VERBOSE, quiet = 1;
+
+        else if (argv[n][0]=='-' || argv[n][0]=='/') {
+            int i = 1;
+            char *val, *tmp, c;
+            long tmpval;
+
+            while (argv[n][i]) {
+                switch (argv[n][i]) {
+
+                case 'n':       /* noopt, no rle/lzlen optimization */
+                    flags |= F_NOOPT;
+                    break;
+
+                case 's':
+                    flags |= F_STATS;
+                    break;
+
+                case 'v':
+                    flags |= F_VERBOSE;
+                    quiet = 0;
+                    break;
+
+                case 'h':
+                case '?':
+                    flags |= F_ERROR;
+                    break;
+
+                case 'r':
+                case 'm':
+                case 'e':
+                case 'p':
+                    c = argv[n][i]; /* Remember the option */
+                    if (argv[n][i+1]) {
+                        val = argv[n]+i+1;
+                    } else if (n+1 < argc) {
+                        val = argv[n+1];
+                        n++;
+                    } else {
+                        flags |= F_ERROR;
+                        break;
+                    }
+
+                    i = strlen(argv[n])-1;
+                    if (*val=='$') tmpval = strtol(val+1, &tmp, 16);
+                    else           tmpval = strtol(val, &tmp, 0);
+
+                    if (*tmp) {
+                        fprintf(stderr,"ERROR: invalid number: \"%s\"\n", val);
+                        flags |= F_ERROR;
+                        break;
+                    }
+
+                    switch (c) {
+                        case 'r':
+                            lzlen = tmpval;
+                            break;
+                        case 'm':
+                            maxGamma = tmpval;
+                            if (maxGamma < 5 || maxGamma > 7) {
+                                fprintf(stderr, "ERROR: Max length must be 5..7!\n");
+                                flags |= F_ERROR;
+                                maxGamma = 7;
+                            }
+                            lrange = LRANGE;
+                            maxlzlen = MAXLZLEN;
+                            maxrlelen = MAXRLELEN;
+                            InitValueLen();
+                            break;
+                        case 'e':
+                            escBits = tmpval;
+                            if (escBits < 0 || escBits > 8) {
+                                fprintf(stderr, "ERROR: Escape bits must be 0..8!\n");
+                                flags |= F_ERROR;
+                            }
+                            else flags &= ~F_AUTO;
+                            escMask = (0xff00>>escBits) & 0xff;
+                            break;
+                        case 'p':
+                            extraLZPosBits = tmpval;
+                            if (extraLZPosBits < 0 || extraLZPosBits > 4) {
+                                fprintf(stderr,"ERROR: Extra LZ-pos bits must be 0..4!\n");
+                                flags |= F_ERROR;
+                            }
+                            else flags &= ~F_AUTOEX;
+                            break;
+                    }
+                    break;
+
+                default:
+                    fprintf(stderr, "ERROR: Unknown option \"%c\"\n",argv[n][i]);
+                    flags |= F_ERROR;
+                }
+                i++;
+            }
+        } else {
+            if (!fileIn) {
+                fileIn = argv[n];
+            }
+            else if (!fileOut) {
+                fileOut = argv[n];
+            }
+            else {
+                fprintf(stderr, "ERROR: Only two filenames wanted!\n");
+                flags |= F_ERROR;
+            }
+        }
+    }
+
+    // input and output file
+    if ((flags & F_ERROR) || !fileIn || !fileOut) {
+        return 1;
+    }
+
+    if (lzlen == -1) lzlen = DEFAULT_LZLEN;
+
+    if (fileIn) {
+        if (!(infp = fopen(fileIn, "rb"))) {
+            fprintf(stderr, "ERROR: Could not open %s for reading!\n", fileIn);
+            return 1;
+        }
+    }
+    else {
+        fprintf(stderr, "assuming stdin as text input.\nCtrl-C to abort, Ctrl-Z for EOF.\n");
+        infp = stdin;
+    }
+
+    /* Read in the data */
+    inlen  = 0;
+    buflen = 0;
+    indata = NULL;
+    while (1) {
+        if (buflen < inlen + lrange) {
+            unsigned char *tmp = realloc(indata, buflen + lrange);
+            if (!tmp) {
+                free(indata);
+                fprintf(stderr, "ERROR: realloc failed!\n");
+                return 1;
+            }
+            indata = tmp;
+            buflen += lrange;
+        }
+        newlen = fread(indata + inlen, 1, lrange, infp);
+        if (newlen <= 0) break;
+        inlen += newlen;
+    }
+
+    //-----------------------------------------------------------
+    // convert the input buffer from hex text to binary
+    // if the user asks for it
+    //-----------------------------------------------------------
+    if (flags & F_TEXTINPUT) inlen = ConvertText2Bin(indata,inlen);
+
+    if (infp != stdin) fclose(infp);
+
+
+    if (startAddr + inlen -1 > 0xffff) {
+        fprintf(stderr,"ERROR: File is too large to handle (>64936 Bytes)");
+        if (indata) free(indata);
+        return 1;
+    }
+
+    if (flags & F_VERBOSE) {
+        fprintf(stderr, "Load address 0x%04x=%d, Last byte 0x%04x=%d\n",
+                         startAddr, startAddr, startAddr+inlen-1, startAddr+inlen-1);
+        fprintf(stderr, "New load address 0x%04x=%d\n", memStart, memStart);
+    }
+
+    n = PackLz77(lzlen, flags, &startEscape, startAddr + inlen, memEnd, type);
+
+    if (!n) {
+        int endAddr = startAddr + inlen; /* end for uncompressed data */
+
+        if (endAddr - ((outPointer + 255) & ~255) < memStart + 3) {
+            /* would overwrite the decompressor, move a bit upwards */
+            if (flags & F_VERBOSE) fprintf(stderr,"$%x < $%x, decompressor overwrite possible, moving upwards\n",
+                                          endAddr - ((outPointer + 255) & ~255), memStart + 3);
+            endAddr = memStart + 3 + ((outPointer + 255) & ~255);
+        }
+
+        /* 3 bytes reserved for EOF */
+        /* bytes reserved for temporary data expansion (escaped chars) */
+        endAddr += 3 + reservedBytes;
+
+        if (!timesDLz) type &= ~FIXF_DLZ;
+
+        // type      ... may vary
+        // outBuffer ... static global array (65536 Bytes)
+
+        SavePack(flags,type, outBuffer, outPointer, fileOut,
+                 startAddr, startEscape, rleValues,
+                 endAddr, extraLZPosBits,
+                 memStart, memEnd);
+
+        timeused = clock()-timeused;
+        if (!timeused) timeused++;
+        if (flags & F_VERBOSE) fprintf(stderr,
+                                       "Compressed %d bytes in %4.2f seconds (%4.2f kB/sec)\n",
+                                       inlen,
+                                       (double)timeused/CLOCKS_PER_SEC,
+                                       (double)CLOCKS_PER_SEC*inlen/timeused/1024.0);
+        return 0;
+    }
+
+    if (indata) free(indata);
+    return n;
+}

+ 2 - 0
tigcc/ld-tigcc/generic.h

@@ -186,7 +186,9 @@ typedef COUNT SIZE;
 // These are for setting only! Do not use them to check values.
 #define FALSE 0
 #define TRUE  (!FALSE)
+#ifndef NULL
 #define NULL  ((void *) 0)
+#endif
 
 // Diagnostic messages.
 #ifdef TARGET_EMBEDDED