// =============================================================================
// -----------------------------------------------------------------------------
// Twizzler
// -----------------------------------------------------------------------------
// Start-{0-U-U-U-U-U-U-U-U----------------------------------------------------------------------------------}-Repeat
//       \1{0-S-S-S-S-R-R-R-R-R-R-R-R-R-R-R-R-R-R-R-R-(9-10007)}-{0-C-(2-3)----------------------------------|
//         \1{0-R-R-R-(1-8)------------------------------------| \1{C-C-(4-6)--------------------------------|
//           \1-H-H-H-H-H-H-H-H-H-H-H-H-H-H-H-H-H-H-(R)--------/   \1-1{1{C-C-C-(7-D)------------------------|
//                                                                     | \1-1-1{1{C-C-C-C-(E-1C)-------------|
//                                                                     |       | \1-1-1-1-C-C-C-C-C-(1D-3C)--|
//                                                                     |       \0-C-C-C-C-C-C-C-C-C-(3D-23C)-|
//                                                                     \0-H-H-H-H-H-H-H-H-H-H-H-H-(C)--------/
// -----------------------------------------------------------------------------

#define rangeof(ENTRY) (0x01<<(0x08*sizeof(ENTRY)))

#define COPY_MIN 0x02
#define COPY_EXT 0x3D
#define COPY_MAX (COPY_EXT + 0x1FF)
#define RETRACE_SHORT 0x08
#define RETRACE_DIST 0xFFFF
#define RETRACE_MAX (RETRACE_DIST + RETRACE_SHORT)
#define WINDOW_SIZE (0x10000 * 0x02)
#define WINDOW_WRAP (WINDOW_SIZE - 0x01)
#define HUFFRET_BITSIZE (0x12 - 0x01)
#define HUFFCOPY_BITSIZE (0x0C - 0x01)

#define MODULE_WRAP (MODULE_SIZE - 0x01)

// -----------------------------------------------------------------------------
// Routine macros
// -----------------------------------------------------------------------------

#define SAVEFIELD(BField,BCount,BLoc,BNextLoc,BSize)\
{\
	if (--BCount == 0x00)\
	{\
		*BLoc = BField;\
		BLoc = BNextLoc++;\
		BSize++;\
		BField = 0x00;\
		BCount = 0x08;\
	}\
}

#define CLEARBIT(BField,BCount,BLoc,BNextLoc,BSize)\
{\
	SAVEFIELD (BField, BCount, BLoc, BNextLoc, BSize);\
	BField <<= 0x01;\
}

#define SETBIT(BField,BCount,BLoc,BNextLoc,BSize)\
{\
	SAVEFIELD (BField, BCount, BLoc, BNextLoc, BSize);\
	BField = (BField << 0x01) | 0x01;\
}

#define PLACEBIT(BValue,BField,BCount,BLoc,BNextLoc,BSize)\
{\
	SAVEFIELD (BField, BCount, BLoc, BNextLoc, BSize);\
	BField = (BField << 0x01) | ((BValue) & 0x01);\
}

#define GETBIT(BValue,BField,BCount,BNextLoc)\
{\
	if (--BCount == 0x00)\
	{\
		BField = *BNextLoc++;\
		BCount = 0x08;\
	}\
	BValue = (BValue << 0x01) | ((BField >> 0x07) & 0x01);\
	BField <<= 0x01;\
}

#define TwizAlloc(TYPE,Pointer,Size)\
{\
	do\
	{\
		Pointer = (TYPE) malloc (Size);\
	}\
	while (Pointer == NULL);\
}

#define TwizAllZZ(TYPE,Pointer,Size)\
{\
	TwizAlloc (TYPE, Pointer, Size);\
	memset (Pointer, 0x00, Size);\
}

// -----------------------------------------------------------------------------
// Lookup Tables
// -----------------------------------------------------------------------------

	// --- Number of bits that are lost from "SavedCur" depending on copy type ---

static const int SavedCopies [] = {	0x00, 0x00,			// Invalid/Padding

					0x01, 0x01,			// Short copy	- 0C

					0x02, 0x02, 0x02,		// Distant copy	- 1CC

					0x06, 0x06, 0x06, 0x06,		// Distant copy	- 1111CCC
					0x06, 0x06, 0x06,

					0x0B, 0x0B, 0x0B, 0x0B,		// Distant copy	- 11111111CCCC
					0x0B, 0x0B, 0x0B, 0x0B,
					0x0B, 0x0B, 0x0B, 0x0B,
					0x0B, 0x0B, 0x0B,

					0x10, 0x10, 0x10, 0x10,		// Distant copy	- 111111111111CCCCC
					0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10,

					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,	// Extended copy - 11111110CCCCCCCCC
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,

					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,

					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,

					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
					0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10

					};

	// --- Subtracting "CopyCur" to minimum before saving ---

static const int CopySubtract [] = {	0x00, 0x00,			// Invalid/Padding

					0x02, 0x02,			// Short copy	- 0C

					0x04, 0x04, 0x04,		// Distant copy	- 1CC

					0x07, 0x07, 0x07, 0x07,		// Distant copy	- 1111CCC
					0x07, 0x07, 0x07,

					0x0E, 0x0E, 0x0E, 0x0E,		// Distant copy	- 11111111CCCC
					0x0E, 0x0E, 0x0E, 0x0E,
					0x0E, 0x0E, 0x0E, 0x0E,
					0x0E, 0x0E, 0x0E,

					0x1D, 0x1D, 0x1D, 0x1D,		// Distant copy	- 111111111111CCCCC
					0x1D, 0x1D, 0x1D, 0x1D,
					0x1D, 0x1D, 0x1D, 0x1D,
					0x1D, 0x1D, 0x1D, 0x1D,
					0x1D, 0x1D, 0x1D, 0x1D,
					0x1D, 0x1D, 0x1D, 0x1D,
					0x1D, 0x1D, 0x1D, 0x1D,
					0x1D, 0x1D, 0x1D, 0x1D,

					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,	// Extended copy - 11111110CCCCCCCCC
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,

					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,

					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,

					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D,
					0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D

					};

	// --- Number of "1" bits to fill (see comments for example) ---

static const int CopyBitFill [] = {	0x00, 0x00,			// Invalid/Padding

					0x00, 0x00,			// Short copy	- 0C

					0x01, 0x01, 0x01,		// Distant copy	- 1CC

					0x04, 0x04, 0x04, 0x04,		// Distant copy	- 1111CCC
					0x04, 0x04, 0x04,

					0x08, 0x08, 0x08, 0x08,		// Distant copy	- 11111111CCCC
					0x08, 0x08, 0x08, 0x08,
					0x08, 0x08, 0x08, 0x08,
					0x08, 0x08, 0x08,

					0x0C, 0x0C, 0x0C, 0x0C,		// Distant copy	- 111111111111CCCCC
					0x0C, 0x0C, 0x0C, 0x0C,
					0x0C, 0x0C, 0x0C, 0x0C,
					0x0C, 0x0C, 0x0C, 0x0C,
					0x0C, 0x0C, 0x0C, 0x0C,
					0x0C, 0x0C, 0x0C, 0x0C,
					0x0C, 0x0C, 0x0C, 0x0C,
					0x0C, 0x0C, 0x0C, 0x0C,

					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,	// Extended copy - 11111110CCCCCCCCC
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,	// Negative = placing 0 on the end
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,

					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,

					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,

					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07,
					-0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07, -0x07

					};

	// --- Number of "C" bits to fill (see comments for example) ---

static const int CopyBitCount [] = {	0x00, 0x00,			// Invalid/Padding

					0x01, 0x01,			// Short copy	- 0C

					0x02, 0x02, 0x02,		// Distant copy	- 1CC

					0x03, 0x03, 0x03, 0x03,		// Distant copy	- 1111CCC
					0x03, 0x03, 0x03,

					0x04, 0x04, 0x04, 0x04,		// Distant copy	- 11111111CCCC
					0x04, 0x04, 0x04, 0x04,
					0x04, 0x04, 0x04, 0x04,
					0x04, 0x04, 0x04,

					0x05, 0x05, 0x05, 0x05,		// Distant copy	- 111111111111CCCCC
					0x05, 0x05, 0x05, 0x05,
					0x05, 0x05, 0x05, 0x05,
					0x05, 0x05, 0x05, 0x05,
					0x05, 0x05, 0x05, 0x05,
					0x05, 0x05, 0x05, 0x05,
					0x05, 0x05, 0x05, 0x05,
					0x05, 0x05, 0x05, 0x05,

					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,	// Extended copy - 11111110CCCCCCCCC
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,

					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,

					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,

					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
					0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09

					};

// =============================================================================
// -----------------------------------------------------------------------------
// Twizzler Compression Algorithm
// -----------------------------------------------------------------------------

void TwizComp (char *&Input, int &InputSize)

{
	const char *WindowCur, *RetraceCur;
	const char *InputAccess = Input;

	int WindowLoc = 0x00;
	int WindowPos;
	int WindowCopy;
	int WindowCount = InputSize;
	int InputLoc = 0x00;
	int InputCount = InputSize;
	int RetraceLoc;
	int RetracePos;
	int RetraceCount;
	int RetraceBest;
	int CopyCur;
	int CopyBest;
	int CopyTotal = COPY_MAX;
	int SavedCur;
	int SavedBest;
	int SavedTotal = 0x00;

	u_short *Document;
	u_short *DocuStore;
	int DocuSize = 0x00;

	int BinaryRange;
	const int *HuffReadOnly;

	int HuffRetLoc;
	int HuffRetSize;
	int HuffRetBest;
	const int *HuffRetPrev;
	const int *HuffRetOff;

	int HuffCopyLoc;
	int HuffCopySize;
	int HuffCopyBest;
	const int *HuffCopyPrev;
	const int *HuffCopyOff;

	int OutputSize;
	char *Output;
	char *OutputAccess;

	int Count, Offset, ExtendSet = 0x00;
	u_short Word;
	char Byte;

	char *BitLoc;
	char BitField;
	char BitCount;

	int *RetStart;
	int *RetCount;
	int *Retraces;
	u_short *WindowWord;
	char *Window;

	int *HuffRetrace;
	int *HuffRetChain;

	int *HuffCopy;
	int *HuffCopyChain;

	TwizAlloc (int*, RetStart, rangeof (u_short) * sizeof (int));
	TwizAllZZ (int*, RetCount, rangeof (u_short) * sizeof (int));
	TwizAlloc (int*, Retraces, WINDOW_SIZE * sizeof (int));
	TwizAlloc (u_short*, WindowWord, WINDOW_SIZE * sizeof (u_short));
	TwizAlloc (char*, Window, (WINDOW_SIZE + (COPY_MAX + 0x01)) * sizeof (u_short));
	TwizAllZZ (int*, HuffRetrace, (RETRACE_MAX + 0x01) * sizeof (int));
	TwizAllZZ (int*, HuffCopy, (COPY_MAX + 0x01) * sizeof (int));
	TwizAlloc (u_short*, DocuStore, (InputSize * 0x02) * sizeof (u_short));

// -----------------------------------------------------------------------------
// Main Search Loop
// -----------------------------------------------------------------------------

	Document = DocuStore;
	while (WindowCount > 0x00)
	{
			// --- Update Window ---

		WindowCopy = (COPY_MAX + 0x01) - (InputLoc - WindowLoc);
		if (WindowCopy > InputCount)
		{
			WindowCopy = InputCount;
		}
		while (WindowCopy > 0x00)
		{
			if (InputLoc >= WINDOW_SIZE)
			{
				Word = WindowWord [(InputLoc & WINDOW_WRAP)];
			/*	if (RetCount [Word] == 0x00)
				{
					printf ("Error; we've got a problem here...\n");
					printf ("InputLoc: %X (WINDOW_WRAP: %X)\n", InputLoc, InputLoc & WINDOW_WRAP);
					printf ("Word: %0.4X\n", Word);
					printf ("WindowLoc: %X (WINDOW_WRAP: %X)\n", WindowLoc, WindowLoc & WINDOW_WRAP);
					fflush (stdin);
					getchar ( );
				}	*/
				RetCount [Word]--;
			}
			Byte = *InputAccess++;
			if ((InputLoc & WINDOW_WRAP) <= (COPY_MAX + 0x01))
			{
				Window [(InputLoc & WINDOW_WRAP) + WINDOW_SIZE] = Byte;
			}
			Window [(InputLoc++ & WINDOW_WRAP)] = Byte;
			InputCount--;
			WindowCopy--;
		}

			// --- Retrace Search ---

		WindowPos = WindowLoc;
		Word = Window [(WindowPos++ & WINDOW_WRAP)] & 0xFF;
		Word |= Window [(WindowPos++ & WINDOW_WRAP)] << 0x08;
		RetraceLoc = RetStart [Word];
		RetraceCount = RetCount [Word];
		SavedBest = -0x01; CopyBest = 0x01;
		if (COPY_MAX > WindowCount)
		{
			CopyTotal = WindowCount;
		}
#if MODULED==TRUE
		while (RetraceLoc >= (WindowLoc - MODULE_SIZE) && RetraceCount-- > 0x00)
#else
		while (RetraceLoc >= (WindowLoc - RETRACE_MAX) && RetraceCount-- > 0x00)
#endif
		{
			WindowCur = Window + (WindowPos & WINDOW_WRAP);
			RetraceCur = Window + ((RetraceLoc + 0x02) & WINDOW_WRAP);
			CopyCur = COPY_MIN;
			while (*WindowCur++ == *RetraceCur++)
			{
				CopyCur++;
				if (CopyCur >= CopyTotal)
				{
					CopyCur = CopyTotal;
					break;
				}
			}
			if (CopyCur > CopyBest)
			{
				SavedCur = (CopyCur * 0x08) - 0x03;
				RetracePos = WindowLoc - RetraceLoc;

					// --- Retrace Check ---

				if (RetracePos <= RETRACE_SHORT)
				{
					SavedCur -= 3 + 1;
				}
				else
				{
					// It's OK to use "__builtin_clz" as "RetracePos - RETRACE_SHORT" will never equal 0
					SavedCur -= 4 + ((0x20 - (__builtin_clz (RetracePos - RETRACE_SHORT))) - 0x01); // Highest MSB set + 4
				}

					// --- Copy Check ---

				SavedCur -= SavedCopies [CopyCur];

					// --- Saved Bits Check ---

				if (SavedCur > SavedBest)
				{
					SavedBest = SavedCur;
					CopyBest = CopyCur;
					RetraceBest = RetracePos;
					if (CopyBest == CopyTotal)
					{
						break;
					}
				}
			}
			RetraceLoc = Retraces [(RetraceLoc & WINDOW_WRAP)];
		}
		SavedTotal += SavedBest;

			// --- Documenting Results ---

		if (SavedBest == -0x01)
		{
			*Document++ = -0x01;
			*Document++ = Word;
		}
		else
		{
			if (RetraceBest > 0xFFFF)
			{
				*Document++ = ((RetraceBest - 0xFFFF) << 0x0B) | CopyBest;
				*Document++ = 0xFFFF;
			}
			else
			{
				*Document++ = CopyBest;
				*Document++ = RetraceBest;
			}
			HuffRetrace [RetraceBest]++;
			HuffCopy [CopyBest]++;
		}
		DocuSize++;

			// --- Update Retraces ---

		do
		{
			WindowPos = WindowLoc;
			Word = Window [(WindowLoc++ & WINDOW_WRAP)] & 0xFF;
			Word |= Window [(WindowLoc & WINDOW_WRAP)] << 0x08;
			Retraces [(WindowPos & WINDOW_WRAP)] = RetStart [Word];
			RetStart [Word] = WindowPos;
			RetCount [Word]++;
			WindowWord [(WindowPos & WINDOW_WRAP)] = Word;
			WindowCount--;
		}
		while (--CopyBest > 0x00);
	}
	free (Input);
	free (RetStart);
	free (RetCount);
	free (Retraces);
	free (WindowWord);
	free (Window);

// -----------------------------------------------------------------------------
// Calculating Huffman Retrace Tree
// -----------------------------------------------------------------------------

	TwizAlloc (int*, HuffRetChain, ((RETRACE_MAX + 0x01) + 0x01) * sizeof (int));
	int HuffRetOrder [HUFFRET_BITSIZE] = { 0x00 };

		// --- Creating a chain to speed up searches ---

	for (HuffRetSize = 0x00, Count = 0x00; Count < (RETRACE_MAX + 0x01); Count++)
	{
		if (HuffRetrace [Count] > 0x01)
		{
			HuffRetChain [HuffRetSize++] = Count;
		}	
	}

		// --- Main Search & Reorder ---

	HuffRetBest = 0x01;
	BinaryRange = 1 + 1;
	while (BinaryRange < HUFFRET_BITSIZE + (1 + 1) && HuffRetBest != 0x00)
	{
		HuffReadOnly = HuffRetChain - 0x01;
		HuffRetBest = 0x00;
		for (Count = HuffRetSize; Count > 0x00; Count--)
		{
			RetraceBest = *++HuffReadOnly;
			if (HuffRetrace [RetraceBest] > HuffRetBest)
			{
				HuffRetBest = HuffRetrace [RetraceBest];
				HuffRetOff = HuffReadOnly;
			}
		}
		if (HuffRetBest != 0x00)
		{
			RetraceBest = *HuffRetOff;
			if (RetraceBest <= RETRACE_SHORT)
			{
				SavedCur = 3 + 1;
			}
			else
			{
				// It's OK to use "__builtin_clz" as "RetraceBest - RETRACE_SHORT" will never equal 0
				SavedCur = 4 + ((0x20 - (__builtin_clz (RetraceBest - RETRACE_SHORT))) - 0x01); // Highest MSB set + 4
			}
			if (SavedCur > BinaryRange)
			{
				HuffRetOrder [(BinaryRange++ - (1 + 1))] = RetraceBest;
			}
			HuffRetrace [RetraceBest] = 0x00;
		}
	}
	HuffRetSize = BinaryRange - (1 + 1);

// -----------------------------------------------------------------------------
// Calculating Huffman Copy Tree
// -----------------------------------------------------------------------------

	TwizAlloc (int*, HuffCopyChain, ((COPY_MAX + 0x01) + 0x01) * sizeof (int));
	int HuffCopyOrder [HUFFCOPY_BITSIZE] = { 0x00 };

		// --- Creating a chain to speed up searches ---

	for (HuffCopySize = 0x00, Count = 0x00; Count < (COPY_MAX + 0x01); Count++)
	{
		if (HuffCopy [Count] > 0x01)
		{
			HuffCopyChain [HuffCopySize++] = Count;
		}	
	}

		// --- Main Search & Reorder ---

	HuffCopyBest = 0x01;
	BinaryRange = 1 + 1 + 2;
	while (BinaryRange < HUFFCOPY_BITSIZE + (1 + 1 + 2) && HuffCopyBest != 0x00)
	{
		HuffReadOnly = HuffCopyChain - 0x01;
		HuffCopyBest = 0x00;
		for (Count = HuffCopySize; Count > 0x00; Count--)
		{
			CopyBest = *++HuffReadOnly;
			if (HuffCopy [CopyBest] > HuffCopyBest)
			{
				HuffCopyBest = HuffCopy [CopyBest];
				HuffCopyOff = HuffReadOnly;
			}
		}
		if (HuffCopyBest != 0x00)
		{
			CopyBest = *HuffCopyOff;
			SavedCur = SavedCopies [CopyBest];
			if (SavedCur > BinaryRange)
			{
				HuffCopyOrder [(BinaryRange++ - (1 + 1 + 2))] = CopyBest;
			}
			HuffCopy [CopyBest] = 0x00;
		}
	}
	HuffCopySize = BinaryRange - (1 + 1 + 2);

// -----------------------------------------------------------------------------
// Setting up data dumping
// -----------------------------------------------------------------------------

		// --- Creating Memory & Prep ---

	TwizAlloc (char*, Output, ((((InputSize * 0x08) - SavedTotal) / 0x08) + 0x01) + 0x1000); // Adding an extra 1000 for counters that are written first...
	OutputAccess = Output;

		// --- Bit Field Preparation ---

	BitField = 0x00;
	BitCount = 0x09;
	BitLoc = OutputAccess++;
	OutputSize = 0x01;

		// --- Saving Decompression Size ---

	Offset = InputSize;
	if (Offset == 0x00)
	{
		Count = 0x00;
	}
	else
	{
		Count = ((0x20 - (__builtin_clz (Offset))) - 0x01); // Highest MSB set
	}
	Offset <<= 0x20 - Count;
	PLACEBIT (Count >> 4, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	while (--Count >= 0x00)
	{
		PLACEBIT (Offset >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		Offset <<= 0x01;
	}

		// --- Saving Section Count ---

	Offset = DocuSize;
	if (Offset == 0x00)
	{
		Count = 0x00;
	}
	else
	{
		Count = ((0x20 - (__builtin_clz (Offset))) - 0x01); // Highest MSB set
	}
	Offset <<= 0x20 - Count;
	PLACEBIT (Count >> 4, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	while (--Count >= 0x00)
	{
		PLACEBIT (Offset >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		Offset <<= 0x01;
	}

		// --- Saving/Creating Huffman Retrace Tree ---

	memset (HuffRetrace, 0x00, (RETRACE_MAX + 0x01) * sizeof (int));
	Offset = HuffRetSize;

	if (Offset == 0x00)
	{
		Count = 0x00;
	}
	else
	{
		Count = (0x20 - (__builtin_clz (Offset))); // Highest MSB set (Meant to have the "- 0x01" removed, incase huffman tree is empty...
	}
	Offset <<= 0x20 - Count;
	PLACEBIT (Count >> 4, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	while (--Count >= 0x00)
	{
		PLACEBIT (Offset >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		Offset <<= 0x01;
	}
	for (HuffRetLoc = 0x00; HuffRetLoc < HuffRetSize; HuffRetLoc++)
	{
		Offset = HuffRetOrder [HuffRetLoc];
		HuffRetrace [Offset] = HuffRetLoc + 0x01;
		if (Offset == 0x00)
		{
			Count = 0x00;
		}
		else
		{
			Count = ((0x20 - (__builtin_clz (Offset))) - 0x01); // Highest MSB set
		}
		Offset <<= 0x20 - Count;
		PLACEBIT (Count >> 4, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		while (--Count >= 0x00)
		{
			PLACEBIT (Offset >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
			Offset <<= 0x01;
		}
	}

		// --- Saving/Creating Huffman Copy Tree ---

	memset (HuffCopy, 0x00, (COPY_MAX + 0x01) * sizeof (int));
	Offset = HuffCopySize;

	if (Offset == 0x00)
	{
		Count = 0x00;
	}
	else
	{
		Count = (0x20 - (__builtin_clz (Offset))); // Highest MSB set (Meant to have the "- 0x01" removed, incase huffman tree is empty...
	}
	Offset <<= 0x20 - Count;
	PLACEBIT (Count >> 4, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	while (--Count >= 0x00)
	{
		PLACEBIT (Offset >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		Offset <<= 0x01;
	}
	for (HuffCopyLoc = 0x00; HuffCopyLoc < HuffCopySize; HuffCopyLoc++)
	{
		Offset = HuffCopyOrder [HuffCopyLoc];
		HuffCopy [Offset] = HuffCopyLoc + 0x01;
		if (Offset == 0x00)
		{
			Count = 0x00;
		}
		else
		{
			Count = ((0x20 - (__builtin_clz (Offset))) - 0x01); // Highest MSB set
		}
		Offset <<= 0x20 - Count;
		PLACEBIT (Count >> 4, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
		while (--Count >= 0x00)
		{
			PLACEBIT (Offset >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
			Offset <<= 0x01;
		}
	}

// -----------------------------------------------------------------------------
// Main Compression Loop
// -----------------------------------------------------------------------------

	Document = DocuStore;
	while (--DocuSize >= 0x00)
	{
		if (*Document == (-0x01 & 0xFFFF))
		{
				// --- Uncompressed ---

			Document++;
			CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
			*OutputAccess++ = *Document++;
			OutputSize++;
		}
		else
		{
			SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
			CopyBest = (*Document & 0x7FF);
			RetraceBest = (*Document++ >> 0x0B) & 0x1F;
			RetraceBest += (*Document++) & 0xFFFF;
			if (HuffRetrace [RetraceBest] != 0x00)
			{
					// --- Huffman Retrace ---

				SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				Count = HuffRetrace [RetraceBest] - 0x01;
				while (Count-- > 0x00)
				{
					SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				}
				CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
			}
			else if (RetraceBest <= RETRACE_SHORT)
			{
					// --- Short Retrace ---

				RetraceBest--;
				SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);				// 1
				CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);			// 0
				PLACEBIT (RetraceBest >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);	// R
				PLACEBIT (RetraceBest >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);	// R
				PLACEBIT (RetraceBest >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);	// R
			}
			else
			{
					// --- Distant Retrace ---

				RetraceBest -= RETRACE_SHORT;
				Count = (0x20 - (__builtin_clz (RetraceBest))) - 0x01;
				RetraceBest <<= (0x20 - Count);
				CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);			// 0
				PLACEBIT (Count >> 3, BitField, BitCount, BitLoc, OutputAccess, OutputSize);		// S
				PLACEBIT (Count >> 2, BitField, BitCount, BitLoc, OutputAccess, OutputSize);		// S
				PLACEBIT (Count >> 1, BitField, BitCount, BitLoc, OutputAccess, OutputSize);		// S
				PLACEBIT (Count >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);		// S
				while (--Count >= 0)									// R...
				{
					PLACEBIT (RetraceBest >> 0x1F, BitField, BitCount, BitLoc, OutputAccess, OutputSize);
					RetraceBest <<= 0x01;
				}
			}

			if (HuffCopy [CopyBest] != 0x00)
			{
					// --- Huffman Copy ---

				SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				Count = HuffCopy [CopyBest] - 0x01;
				while (Count-- > 0x00)
				{
					SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				}
				CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
			}
			else if (CopyBest < (COPY_MIN + 0x02))
			{
					// --- Short Copy ---

				CopyBest -= CopySubtract [CopyBest];
				CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);			// 0
				PLACEBIT (CopyBest >> 0, BitField, BitCount, BitLoc, OutputAccess, OutputSize);		// C
			}
			else
			{
					// --- Distant Copy ---

				Count = CopyBitFill [CopyBest];
				if (Count < 0x00)
				{
					Count = -Count;
					ExtendSet = -0x01;
				}
				do											// 1...
				{
					SETBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				}
				while (--Count > 0x00);
				if (ExtendSet != 0x00)
				{
					ExtendSet = 0x00;
					CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);		// 0 - For extended copy
				}
				Count = CopyBitCount [CopyBest];
				CopyBest -= CopySubtract [CopyBest];
				do											// C...
				{
					PLACEBIT ((CopyBest >> --Count), BitField, BitCount, BitLoc, OutputAccess, OutputSize);
				}
				while (Count > 0x00);
			}
		}
	}
	free (DocuStore);
	do
	{
		CLEARBIT (BitField, BitCount, BitLoc, OutputAccess, OutputSize);
	}
	while (BitCount != 0x08);
	OutputSize--;

// -----------------------------------------------------------------------------
// Finish/Cleanup
// -----------------------------------------------------------------------------

	Input = Output;
	InputSize = OutputSize;

	free (HuffRetrace);
	free (HuffRetChain);
	free (HuffCopy);
	free (HuffCopyChain);
}

// =============================================================================
// -----------------------------------------------------------------------------
// Twizzler Decompression Algorithm
// -----------------------------------------------------------------------------

void TwizDec (char *&Input, int &InputSize)

{
	const char *InputAccess = Input;
	const char *InputRetrace;
	char *Output;
	char *OutputAccess;
	int OutputLoc = 0x00;
	int OutputSize;
	int SectionCount;
	int RetraceBest;
	int CopyBest;
	int HuffRetLoc;
	int HuffRetSize;
	int HuffCopyLoc;
	int HuffCopySize;
	int AddBit;
	int CheckBit;
	int CountBit;
	int AdvanceBit;
	int CountCur;
	int LimitBit;
	int Count, Offset;
	char Byte;
	char BitCount = 0x09;
	char BitField = *InputAccess++;
	int HuffRetOrder [HUFFRET_BITSIZE];
	int HuffCopyOrder [HUFFCOPY_BITSIZE];

		// --- Getting Decompression Size ---

	Count = 0x00;
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	OutputSize = 0x01;
	while (Count-- > 0x00)
	{
		GETBIT (OutputSize, BitField, BitCount, InputAccess);
	}
		// --- Getting Section Counter ---

	Count = 0x00;
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	SectionCount = 0x01;
	while (Count-- > 0x00)
	{
		GETBIT (SectionCount, BitField, BitCount, InputAccess);
	}

		// --- Unpacking Huffman Retrace Tree ---

	Count = 0x00;
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	HuffRetSize = 0x00;		// Meant to be 0, incase huffman tree is empty...
	while (Count-- > 0x00)
	{
		GETBIT (HuffRetSize, BitField, BitCount, InputAccess);
	}

	for (HuffRetLoc = 0x00; HuffRetLoc < HuffRetSize; HuffRetLoc++)
	{
		Count = 0x00;
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		Offset = 0x01;
		while (Count-- > 0x00)
		{
			GETBIT (Offset, BitField, BitCount, InputAccess);
		}
		HuffRetOrder [HuffRetLoc] = Offset;
	}

		// --- Unpacking Huffman Copy Tree ---

	Count = 0x00;
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	GETBIT (Count, BitField, BitCount, InputAccess);
	HuffCopySize = 0x00;		// Meant to be 0, incase huffman tree is empty...
	while (Count-- > 0x00)
	{
		GETBIT (HuffCopySize, BitField, BitCount, InputAccess);
	}

	for (HuffCopyLoc = 0x00; HuffCopyLoc < HuffCopySize; HuffCopyLoc++)
	{
		Count = 0x00;
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		GETBIT (Count, BitField, BitCount, InputAccess);
		Offset = 0x01;
		while (Count-- > 0x00)
		{
			GETBIT (Offset, BitField, BitCount, InputAccess);
		}
		HuffCopyOrder [HuffCopyLoc] = Offset;
	}

		// --- Creating Memory & Prep ---

	do
	{
		Output = (char*) malloc (OutputSize);
	}
	while (Output == NULL);
	OutputAccess = Output;

// -----------------------------------------------------------------------------
// Main Decompression Loop
// -----------------------------------------------------------------------------

	while (--SectionCount >= 0x00)
	{
		Count = 0x00;
		GETBIT (Count, BitField, BitCount, InputAccess);
		if (Count == 0x00)
		{
				// --- Uncompressed ---

			*OutputAccess++ = *InputAccess++;
			OutputLoc++;
		}
		else
		{
			RetraceBest = 0x00;
			Count = 0x00;
			GETBIT (Count, BitField, BitCount, InputAccess);
			if (Count != 0x00)
			{
				Count = 0x00;
				GETBIT (Count, BitField, BitCount, InputAccess);
				if (Count != 0x00)
				{
						// --- Huffman Retrace ---

					Offset = 0x00;
					HuffRetLoc = -0x01;
					do
					{
						HuffRetLoc++;
						GETBIT (Offset, BitField, BitCount, InputAccess);
					}
					while ((Offset & 0x01) != 0x00);
					RetraceBest = HuffRetOrder [HuffRetLoc];
				}
				else
				{
						// --- Short Retrace ---

					GETBIT (RetraceBest, BitField, BitCount, InputAccess);
					GETBIT (RetraceBest, BitField, BitCount, InputAccess);
					GETBIT (RetraceBest, BitField, BitCount, InputAccess);
					RetraceBest++;
				}
			}
			else
			{
					// --- Distant Retrace ---

				Count = 0x00;
				GETBIT (Count, BitField, BitCount, InputAccess);
				GETBIT (Count, BitField, BitCount, InputAccess);
				GETBIT (Count, BitField, BitCount, InputAccess);
				GETBIT (Count, BitField, BitCount, InputAccess);
				RetraceBest = 0x01;
				while (Count-- > 0x00)
				{
					GETBIT (RetraceBest, BitField, BitCount, InputAccess);
				}
				RetraceBest += RETRACE_SHORT;

			}
			CopyBest = 0x00;
			Count = 0x00;
			GETBIT (Count, BitField, BitCount, InputAccess);
			if (Count == 0x00)
			{
					// --- Short Copy ---

				GETBIT (CopyBest, BitField, BitCount, InputAccess);
			}
			else
			{
					// --- Distant Copy ---

				CheckBit = 0x03;
				GETBIT (CopyBest, BitField, BitCount, InputAccess);
				GETBIT (CopyBest, BitField, BitCount, InputAccess);
				if (CopyBest == CheckBit)
				{
					CountBit = 0x03;
					LimitBit = 0x02;
					AddBit = 0x00;
					AdvanceBit = 0x01;
					do
					{
						if (AdvanceBit == 0x01)
						{
							Count = 0x00;
							GETBIT (Count, BitField, BitCount, InputAccess);
							if (Count == 0x00)
							{
									// --- Huffman Copy ---

								Offset = 0x00;
								HuffCopyLoc = -0x01;
								do
								{
									HuffCopyLoc++;
									GETBIT (Offset, BitField, BitCount, InputAccess);
								}
								while ((Offset & 0x01) != 0x00);
								CopyBest = HuffCopyOrder [HuffCopyLoc] - (COPY_MIN + COPY_MIN);
								break;
							}
							AdvanceBit--;
						}
						else if (AdvanceBit == 0x00)
						{
							Count = 0x00;
							GETBIT (Count, BitField, BitCount, InputAccess);
							if (Count == 0x00)
							{
									// --- Extended Copy ---

								CopyBest = 0x00;
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								GETBIT (CopyBest, BitField, BitCount, InputAccess);
								CopyBest += COPY_EXT - (COPY_MIN + COPY_MIN);
								break;
							}
							AdvanceBit--;
						}
						Count = 0x00;
						for (CountCur = CountBit; CountCur > 0x00; CountCur--)
						{
							GETBIT (Count, BitField, BitCount, InputAccess);
						}
						CountBit++;
						AddBit += CheckBit;
						CopyBest = (Count + AddBit);
						CheckBit = (CheckBit << 0x01) | 0x01;
					}
					while (Count == CheckBit && LimitBit-- > 0x00);
				}
				CopyBest += COPY_MIN;
			}
			CopyBest += COPY_MIN;

				// --- Unpacking LZ ---

			InputRetrace = Output + (OutputLoc - RetraceBest);
			OutputLoc += CopyBest;
			while (--CopyBest >= 0x00)
			{
				*OutputAccess++ = *InputRetrace++;
			}
		}
	}
	free (Input);
	Input = Output;
	InputSize = OutputLoc;
}

// =============================================================================



















