/*
 * This library is mainly intended to demonstrate how to program a sub
 * library.
 $VER: xpkELZX.c 1.0 (09/02/96) 
 */

#define NO_SUB_PRAGMAS
#define MaksymalnyC 0x60000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libraries/xpksub.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <exec/exec.h>

#define A3000 XPKMF_A3000SPEED

XMINFO RlenMode4 = {
	NULL,    	// next
	100,     	// upto
	A3000,   	// flags
	0,       	// packmem
	0,       	// unpackmem
	30,     	// packspeed,   K/sec
	150,    	// unpackspeed, K/sec
	500,      	// ratio,      *0.1%
	0,       	// reserved
	"best" 		// description
};
XMINFO RlenMode3 = {
	&RlenMode4,  // next
	80,     	// upto
	A3000,   	// flags
	0,       	// packmem
	0,       	// unpackmem
	31,     	// packspeed,   K/sec
	150,    	// unpackspeed, K/sec
	480,      	// ratio,      *0.1%
	0,       	// reserved
	"better" 	// description
};
XMINFO RlenMode2 = {
	&RlenMode3,  // next
	60,     	// upto
	A3000,   	// flags
	0,       	// packmem
	0,       	// unpackmem
	32,     	// packspeed,   K/sec
	150,    	// unpackspeed, K/sec
	460,      	// ratio,      *0.1%
	0,       	// reserved
	"good" 		// description
};
XMINFO RlenMode1 = {
	&RlenMode2,  // next
	40,     	// upto
	A3000,   	// flags
	0,       	// packmem
	0,       	// unpackmem
	33,     	// packspeed,   K/sec
	150,    	// unpackspeed, K/sec
	440,      	// ratio,      *0.1%
	0,       	// reserved
	"poor" 		// description
};
XMINFO RlenMode = {
	&RlenMode1,	// next
	20,     	// upto
	A3000,   	// flags
	0,       	// packmem
	0,       	// unpackmem
	34,     	// packspeed,   K/sec
	150,    	// unpackspeed, K/sec
	10,      	// ratio,      *0.1%
	0,       	// reserved
	"none" 		// description
};
#ifndef WERSJA_OKROJONA
char *mody="012399";
#else
char *mody="012333";
#endif
static struct XpkInfo RlenInfo = {
		1,               /* info version */
		0,               /* lib  version */
		0,               /* master vers  */
		0,               /* pad          */
#ifndef KOD_DELTA
		"ELZX",          /* short name   */
		"External LZX  ",/* long name    */
		"very good compression library      middle speed   ", /* description*/
		'ELZX',          /* 4 letter ID  */
#else
		"SLZX",          /* short name   */
		"LZX with delta",/* long name    */
		"External LZX compression for samples and mods     ", /* description*/
		'SLZX',          /* 4 letter ID  */
#endif
		XPKIF_PK_CHUNK | /* flags        */
		XPKIF_UP_CHUNK |
		XPKIF_MODES,
		MaksymalnyC,     /* max in chunk */
		1,               /* min in chunk */
		MaksymalnyC,     /* def in chunk */
		NULL,            /* pk message   */
		NULL,            /* up message   */
		NULL,            /* pk past msg  */
		NULL,            /* up past msg  */
		80,              /* def mode     */
		0,               /* pad          */
		&RlenMode        /* modes        */
};

/*
 * Returns an info structure about our packer
 */
struct XpkInfo * __saveds __asm
XpksPackerInfo( void )
{
	return &RlenInfo;
}


void __saveds __asm
XpksPackFree( REG __a0 XPARAMS* xpar )
{
}

/*
 * This forces the next chunk to be uncompressable independent from the
 * previous one. This is always the case in RLEN.
 */
long __saveds __asm
XpksPackReset( REG __a0 XPARAMS* xpar )
{
	return 0;
}


void __saveds __asm
XpksUnpackFree( REG __a0 XPARAMS* xpar )
{
}
/*
 * Pack a chunk
 */
long __saveds __asm
XpksPackChunk( REG __a0 XPARAMS *xpar )
{
	UBYTE *get =xpar->InBuf,*put=xpar->OutBuf;
#ifdef KOD_DELTA
	UBYTE *docel=xpar->OutBuf;
	int   i;
#endif

// Moje dodatki
	char temp1[100],temp2[100],sysus[100];
	struct Library *DOSBase;
	struct ExecBase *ExecBase=(void *)4;
	BPTR tmp; 
#ifdef	Z_PIPE
	BPTR we,wy;
#endif
	DOSBase=OpenLibrary("dos.library",37);
	sprintf(temp1,"t:ltf%8x",ExecBase->ThisTask);
#ifdef	Z_PIPE
	sprintf(temp2,"pipe:ltf%8x.lzx",ExecBase->ThisTask);
#else
	sprintf(temp2,"t:ltf%8x.lzx",ExecBase->ThisTask);
#endif
#ifndef WERSJA_OKROJONA
	sprintf(sysus,"lzx -Qf -%c af >nil: <nil: %s %s",mody[((xpar->Mode|1)-1)/20],temp2,temp1);
#else
	sprintf(sysus,"lzx -%c af >nil: <nil: %s %s",mody[((xpar->Mode|1)-1)/20],temp2,temp1);
#endif
#ifndef	Z_PIPE
	DeleteFile(temp2);
#endif
	tmp=Open(temp1,MODE_NEWFILE);
#ifdef 	KOD_DELTA
	for(i=0;docel<put+xpar->InLen;*docel++=*get-i,i=*get++) {};
	Write(tmp,put,xpar->InLen);
#else
	Write(tmp,get,xpar->InLen);
#endif
	Close(tmp);
#ifndef	Z_PIPE
	SystemTagList(sysus,(void *)0);
	tmp=Open(temp2,MODE_OLDFILE);
	Seek(tmp,0,OFFSET_END);
	if ( Seek(tmp,0,OFFSET_BEGINNING) < MaksymalnyC )
		xpar->OutLen=Read(tmp,put,MaksymalnyC);
	 else
#ifndef KOD_DELTA
		CopyMem(get,put,xpar->OutLen=xpar->InLen);
#else
		xpar->OutLen=MaksymalnyC;
#endif
#else
		we=Open("NIL:",MODE_READWRITE);
		wy=Open("NIL:",MODE_READWRITE);
		SystemTags(sysus,SYS_Asynch,1,SYS_Output,wy,SYS_Input,we,0);
		tmp=Open(temp2,MODE_OLDFILE);
		xpar->OutLen=Read(tmp,put,MaksymalnyC);
		xpar->OutLen+=Read(tmp,put+xpar->OutLen,MaksymalnyC);
		if ( xpar->OutLen==MaksymalnyC )
#ifndef KOD_DELTA
		CopyMem(get,put,xpar->OutLen=xpar->InLen);
#else
		{
		xpar->OutLen=MaksymalnyC;
		get=xpar->InBuf;
		docel=put;
		for(i=0;docel<put+xpar->InLen;*docel++=*get-i,i=*get++) {};
		}
#endif
#endif
	Close(tmp);
	DeleteFile(temp1);
#ifndef	Z_PIPE
	DeleteFile(temp2);
#endif
	CloseLibrary(DOSBase);
	return 0;
}

long __saveds __asm
XpksUnpackChunk( REG __a0 XPARAMS* xpar )
{
	char *get=xpar->InBuf, *put=xpar->OutBuf;
#ifdef KOD_DELTA
	int		x,i;
#endif
	char temp1[100],temp2[100],sysus[100];
	struct Library *DOSBase;
#ifndef	Z_PIPE
	struct ExecBase *ExecBase=(void *)4;
#endif
	BPTR tmp;
	if ( MaksymalnyC == xpar->InLen ) 
#ifndef KOD_DELTA
		CopyMem(get,put,MaksymalnyC);
#else
		for(x=0,i=MaksymalnyC;i--;*put+=x,x=*put++);
#endif
	 else {
		DOSBase=OpenLibrary("dos.library",37);
		strcpy(temp1,"t:");
		strncat(temp1,get+0x29,11);
#ifdef Z_PIPE
		sprintf(temp2,"mem:%d-%d",get,xpar->InLen);
#else
		sprintf(temp2,"t:ltf%8x.lzx",ExecBase->ThisTask);
		tmp=Open(temp2,MODE_NEWFILE);
		Write(tmp,get,xpar->InLen);
		Close(tmp);
#endif
		sprintf(sysus,"lzx x >nil: <nil: %s t:",temp2);
		SystemTagList(sysus,(void *)0);
		tmp=Open(temp1,MODE_OLDFILE);
#ifdef KOD_DELTA
		i=Read(tmp,put,MaksymalnyC);
		for(x=0;i--;*put+=x,x=*put++){};
#else
		Read(tmp,put,MaksymalnyC);
#endif
		Close(tmp);
		DeleteFile(temp1);
#ifndef Z_PIPE
		DeleteFile(temp2);
#endif
		CloseLibrary(DOSBase);
	}
	return 0;
}
