/*************************************************************
 *                                                           *
 *    ths  Filesystem                  04.10.94      V1.1    *
 *                                                           *
 *    Thomas Scheuermann     ths@ai-lab.fh-furtwangen.de     *
 *                                                           *
 *************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/malloc.h>

#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>

#include "ths.h"
#include "ths_i.h"

/*
 * Test auf 44530002
 */

int arttest(long *data)
{
	if(*data == 0x02005344)
		return 0;
	else
		return 1;
}

/*
 * Daten holen
 */

void nextdata(unsigned char **data, int *bz, int *cc,long *zc,struct super_block *s,long sektor, struct buffer_head **bh)
{
	while(*bz < 25)
	{
		if (!(*cc % 512))
			*data = ths_uread(s,sektor+(*cc)/512,bh);
		*zc |= (unsigned long)(*data)[*cc%512]<<*bz;
		(*cc)++;
		if (!(*cc % 512))
			brelse(*bh);
		*bz +=8;
	}
}

/*
 * Dekompressionsalgorithmus
 * funktioniert nur mit Komprimierung 2
 */

void decompress(struct super_block *s, struct ths_buffer *tbf, int mdfat)
{
	unsigned char zu,flag,*data=NULL;
	unsigned long sektor,zc;
	struct buffer_head *bh;
	int k,rb,rl,hz,m,sek,sekmax,bz,cc,test;


#ifdef DEBUG
	printk("decompress %d\n",mdfat);
#endif

	sektor = (mdfat & 0x1fffff) +1;
	sekmax = ((mdfat & 0x3c000000)>>26) +1;

/*
 * i	: Bitzaehler
 * k	: Zeichenzaehler dekomprimiert
 * hz	: Hilfszaehler fuer Bits;
 * rb	: Rueckwaertsbezug rb Bytes
 * rl	: Laenge des Rueckwaertsbezugs
 * m	: Laengenhilfsspeicher
 * flag	: Status
 * zc	: komprimierte Daten(max 4 Byte)
 * bz	: Bitzaehler fuer zc
 * cc	: Zeichenzaehler fuer unkomprimierte Zeichen
 * zu	: unkomprimiertes Zeichen
 * sek	: Sektorzaehler
 */
	k=0;
	zu=0;
	zc=0;
	rb=0;
	rl=0;
	hz=0;
	m=0;
	sek = 0;
	flag = 'n';
	bz=0;
	cc=0;
	test=0;

	nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
	if(arttest(&zc))
	{
		printk("Komprimierung nicht erkannt !\n");
		return;
	}
	zc=0;
	bz=0;
	nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);


	for(;sek<sekmax;)
	{
		switch(zc&0x03)
		{
			case 2:		/* 0 - 127 */
				zc>>=2;
				zu = (unsigned char)zc & 0x7f;
				zc>>=7;
				bz -=9;
				(tbf->data[k/512])[k%512] = zu;
				k++;
				if(bz<17)
					nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
				break;
			case 1:		/* 128 - 255 */
				zc>>=2;
				zu = (unsigned char)(zc & 0x7f)|128;
				zc>>=7;
				bz -=9;
				(tbf->data[k/512])[k%512] = zu;
				k++;
				if(bz<17)
					nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
				break;
			case 0:		/* 6 Bit Rueckbezug */
				zc>>=2;
				rb = zc & 0x3f;
				zc>>=6;
				bz -=8;
				if(bz<17)
					nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
				hz=0;
				for(;!(zc&0x01);zc>>=1,hz++);
				zc>>=1;
				bz-=(hz+1);
				rl = (zc & ((1<<hz)-1)) + (1<<hz)+1;
				zc>>=hz;
				bz -=hz;
				if(bz<17)
					nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
				for(hz=0;hz<rl;hz++)
				{
					(tbf->data[k/512])[k%512] = (tbf->data[(k-rb)/512])[(k-rb)%512];
					k++;
				}
				break;
			case 3:		/* Rueckbezug auf 65+ oder 320+ Zeichen */
				switch(zc&0x07)
				{
					case 3: /* 65+ Zeichen */
						zc>>=3;
						rb = (zc & 0xff) + 64;
						zc>>=8;
						bz -=11;
						break;
					case 7: /* 320+ Zeichen */
						zc>>=3;
						rb = (zc & 0xfff);
						if(rb == 0xfff)
							test=1;
						rb+=320;
						zc>>=12;
						bz -=15;
						break;
				}
				if(bz<17)
					nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
				if(test)
				{
					test=0;
					sek++;
					break;	/* Sonderfall 512 Byte Grenze */
				}
				hz=0;
				for(;!(zc&0x01);zc>>=1,hz++);
				zc>>=1;
				bz-=(hz+1);
				rl = (zc & ((1<<hz)-1)) + (1<<hz)+1;
				zc>>=hz;
				bz -=hz;
				if(bz<17)
					nextdata(&data,&bz,&cc,&zc,s,sektor,&bh);
				for(hz=0;hz<rl;hz++)
				{
					(tbf->data[k/512])[k%512] = (tbf->data[(k-rb)/512])[(k-rb)%512];
					k++;
				}
				break;
		}
	}
	if((cc%512))
	{
		brelse(bh);
	}
#ifdef DEBUG
	printk("decompress Ende\n");
#endif
	return;
}




