
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

unsigned char *src, *dest, *destorg, lwm, mask, byte;
unsigned int recentoff, gamma;

int getbit()
{
	if (mask&1)
		byte = *src++;
	mask = (mask>>1) | ((mask<<7) & (1<<7));
	return (byte&mask);
}

void getbitgamma()
{
	gamma <<= 1;
	if (getbit())
		gamma++;
}

void ap_getgamma()
{
	gamma = 1;
	do {
		getbitgamma();
	} while (getbit());
}

void copyloop()
{
	do {
		*dest++ = dest[-recentoff];
	} while (--gamma);
}

void ap_is_lwm()
{
	recentoff = *src++ + (gamma<<8);
	ap_getgamma();
	if (recentoff >= 32000)
		gamma++;
	if (recentoff >= 1280)
		gamma++;
	if (recentoff < 128)
		gamma += 2;
	copyloop();
}

int depack()
{
	int done = 0;
	*dest++ = *src++;
	mask = 0x01;
	lwm = 0;
	do {
		if (getbit()) {
			//apbranch1
			if (!getbit()) {
				//apbranch2
				ap_getgamma();
				gamma -= 2;
				if (lwm) {
					ap_is_lwm();
				} else {
					lwm = 1;
					if (gamma) {
						gamma--;
						ap_is_lwm();
					} else {
						ap_getgamma();
						copyloop();
					}
				}
			} else if (!getbit()) {
				//apbranch3
				gamma = *src++;
				recentoff = gamma>>1;
				if (!recentoff) {
					done = 1;
				} else {
					if (gamma&1) {
						*dest++ = dest[-recentoff];
					}
					*dest++ = dest[-recentoff];
					*dest++ = dest[-recentoff];
					lwm = 1;
				}
			} else {
				gamma = 0;
				getbitgamma();
				getbitgamma();
				getbitgamma();
				getbitgamma();
				if (gamma)
					gamma = dest[-gamma];
				*dest++ = (unsigned char) gamma;
				lwm = 0;
			}
		} else {
			*dest++ = *src++;
			lwm = 0;
		}
	} while(!done);
	return dest-destorg;
}

int main()
{
	int in, out;
	src = malloc(1024*1024);
	destorg = dest = malloc(1024*1024);
	in = read(0, src, 1024*1024);
	fprintf(stderr, "%d\n", in);
	out = depack();
	fprintf(stderr, "%d\n", out);
	write(1, destorg, out);
	return 0;
}

