#ifndef XPKMASTER_XPKMASTER_H
#define XPKMASTER_XPKMASTER_H

/* Includeheader

	Name:		xpkmaster.h
	Main:		xpkmaster
	Versionstring:	$VER: xpkmaster.h 1.13 (21.02.1998)
	Author:		SDI
	Distribution:	Freeware
	Description:	Master library global definitions and declarations
			and prototypes

 1.0   05.10.96 : first real version
 1.1   27.12.96 : removed library protos - call now via library interface,
 	allows patching
 1.2   30.01.97 : change of cchecksum proto
 1.3   31.01.97 : checksum changed again
 1.4   01.03.97 : added new flags
 1.5   08.03.97 : changed XpkBuffer a bit
 1.6   31.03.97 : some little corrections
 1.7   02.04.97 : removed obsolete stuff
 1.8   12.04.97 : added DebugTagList
 1.9   14.08.97 : fixed defines
 1.10  20.12.97 : changed a lot in defines and structures
 1.11  09.01.98 : added better key-fields to xbuf
 1.12  24.01.98 : removed PP support --> done by xfdmaster now
 1.13  21.02.98 : added code independence
*/

/* To disable PowerPacker support comment out the next line. */
/* #define USE_POWERPACKER */

#ifdef __SASC
  #define ASM(arg)	arg __asm
#else
  #define ASM(arg)	arg
#endif

#ifdef __GNUC__
  #define REG(reg,arg)	arg __asm(#reg)
#else
  #define REG(reg,arg)	register __##reg arg
#endif

#ifdef SUPPORT_A4
  #define A4SUPP	,a4
  #define A4SUPP2	,xbuf->xb_regA4
  #define A4PROTO	,REG(a4, ULONG a4)
#else
  #define A4SUPP
  #define A4SUPP2
  #define A4PROTO
#endif

#ifndef XPK_ALLINONE /* This allows some optimizations, when All.c is used */
  #define XPK_ALLINONE
#endif

#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"

#include <xpk/xpk.h>
#include <xpk/xpksub.h>

typedef ASM(ULONG) (*regfunc) (REG(a0, struct Hook *),
			       REG(a1, APTR), REG(a2, APTR) A4PROTO);

#define ROUNDLONG(x)		(((x)+3)&(~3))	/* round to next longword */
#define DEFAULTCHUNKSIZE	0x8000

#ifndef Min
  #define Min(a,b) ((a) < (b) ? (a) : (b))
  #define max(a,b) ((a) > (b) ? (a) : (b))
#endif

/* The structure used for I/O, special master library version */
struct XpkMasterMsg {
  ULONG  xmm_Type;		/* Read/Write/Alloc/Free/Abort		*/
  STRPTR xmm_Ptr;		/* The mem area to read from/write to	*/
  LONG   xmm_Size;		/* The size of the read/write		*/
  ULONG  xmm_IOError;		/* The IoErr() that occurred		*/
  ULONG  xmm_Reserved;		/* Reserved for future use		*/
  STRPTR xmm_Buf;		/* Specific to the internal hooks	*/
  LONG   xmm_Error;		/* The XPKERR that occurred		*/
  ULONG  xmm_BufLen;
  ULONG  xmm_BufOfs;
  ULONG  xmm_Len;
  ULONG  xmm_Flags;
  ULONG  xmm_FH;
  ULONG  xmm_MemType;
  STRPTR xmm_FileName;
};

#define XIO_GETOUTBUF 1		/* flag for xmm_Flags - allocate buffer	*/

/* These structures define the file format for compressed streams */
struct XpkStreamHeader {
  ULONG xsh_Pack;
  ULONG xsh_CLen;
  ULONG xsh_Type;
  ULONG xsh_ULen;
  UBYTE xsh_Initial[16];
  UBYTE xsh_Flags;
  UBYTE xsh_HChk;
  UBYTE xsh_SubVrs;
  UBYTE xsh_MasVrs;
};

#define XPK_COOKIE	0x58504b46	/* 'XPKF' - ID for xsh_Pack */
#define ROW_OF_MINUS	0x2d2d2d2d	/* '----' */
#define PP_COOKIE	0x50503230	/* 'PP20' */
#define XFD_COOKIE	0x58464444	/* 'XFDD' */
#define USER_COOKIE	0x55534552	/* 'USER' */

#define XPKSTREAMF_LONGHEADERS  0x01	/* Use XpkLongLocHeaders	*/
#define XPKSTREAMF_PASSWORD     0x02	/* This file encoded		*/
#define XPKSTREAMF_EXTHEADER    0x04	/* Extended globhdr		*/

struct XpkChunkHdrWord {
  UBYTE xchw_Type;
  UBYTE xchw_HChk;
  UWORD xchw_CChk;
  UWORD xchw_CLen;
  UWORD xchw_ULen;
};

struct XpkChunkHdrLong {
  UBYTE xchl_Type;
  UBYTE xchl_HChk;
  UWORD xchl_CChk;
  ULONG xchl_CLen;
  ULONG xchl_ULen;
};

typedef union {
  struct XpkChunkHdrLong xch_Long;
  struct XpkChunkHdrWord xch_Word;
} XpkChunkHeader;

#define XPKCHUNK_RAW		0x00 /* raw copy of source */
#define XPKCHUNK_PACKED		0x01 /* packed data */
#define XPKCHUNK_END		0x0F /* empty end Chunk */

struct Headers {
  struct XpkStreamHeader h_Glob;
  XpkChunkHeader	 h_Loc;
  ULONG			 h_LocSize;
};

#define XPKMODE_UPUP    1
#define XPKMODE_UPSTD   2
#define XPKMODE_UPPP    3
#define XPKMODE_UPXFD	4
#define XPKMODE_PKSTD  20

#define AUTO_PASS_SIZE	50

/* This is what XPK "handles" really point to */
struct XpkBuffer {
  struct XpkFib	xb_Fib;		/* file info about this file		*/
  UWORD   xb_PackingMode;	/* desired packing efficiency, 0..100   */
  struct Headers xb_Headers;	/* global and local file header 	*/
  ULONG   xb_Format;		/* type of file				*/
  LONG    xb_Result;		/* error code from last call		*/
  STRPTR  xb_ErrBuf;		/* Where user wants the error		*/
  STRPTR *xb_GetOutBuf;		/* Where user wants the out buf addr	*/
  ULONG  *xb_GetOutLen;		/* Where user wants the output len	*/
  ULONG  *xb_GetOutBufLen;	/* Where user wants the out buf len	*/
  ULONG   xb_Secs;		/* Start time, the seconds		*/
  ULONG   xb_Mics;		/* Start time, the micros		*/
  struct Hook * xb_RHook;	/* input data hook			*/
  struct Hook * xb_WHook;	/* output data hook			*/
  struct Hook * xb_ChunkHook;	/* Hook to call between chunks		*/
  STRPTR  xb_Password;		/* password for de/encoding		*/
  ULONG   xb_PasswordSize;	/* password buffer size for own password*/
  ULONG   xb_PassKey32;		/* password key, 32 bit			*/
  UWORD   xb_PassKey16;		/* password key, 16 bit			*/
  WORD    xb_Priority;		/* task pri during packing		*/
  ULONG   xb_SubID;		/* currently active sub ID		*/
  ULONG   xb_ChunkSize;		/* Chunk size to use for packing	*/
  ULONG   xb_FirstChunk;	/* First chunk size - largest chunk	*/
  ULONG   xb_Flags;		/* private for xpkmaster		*/
  LONG    xb_InLen;		/* Number of bytes to (un)pack		*/
  STRPTR  xb_LastMsg;		/* The last progress message		*/
  struct xfdBufferInfo * xb_xfd;/* xfdBufferInfo			*/
  struct XpkInfo * xb_SubInfo;	/* Info of current open sub-lib		*/
  struct Library * xb_SubBase;	/* Currently open sub-library		*/
  struct XpkMasterMsg xb_RMsg;	/* Parameters for reading		*/
  struct XpkMasterMsg xb_WMsg;	/* Parameters for writing		*/
  struct XpkSubParams xb_PackParam;/* Parameters to (Un)PackChunk()	*/
  struct XpkProgress  xb_Prog;	/* Parameters to progress report	*/
#ifdef SUPPORT_A4
  ULONG	  xb_regA4;
#endif
};

/* Values for MasterFlags */
#define XMF_PRIVFH	(1<< 0)	/* We opened the FH, so we close it.	*/
#define XMF_PACKING	(1<< 1)	/* This is a packing operation.		*/
#define XMF_PASSTHRU	(1<< 2)	/* Pass uncompressed data through	*/
#define XMF_GETOUTBUF	(1<< 3)	/* Get output buffer when size known	*/
#define XMF_NOCLOBBER	(1<< 4)	/* Don't overwrite			*/
#define XMF_EOF		(1<< 5)	/* End of file				*/
#define XMF_INITED	(1<< 6)	/* Sublib buffers have been allocted	*/
#define XMF_GLOBHDR	(1<< 7)	/* GlobHdr is already written		*/
#define XMF_LOSSYOK	(1<< 8)	/* Lossy compression permitted		*/
#define XMF_OWNTASKPRI	(1<< 9) /* Altered task pri, restore		*/
#define XMF_NOCRC	(1<<10)	/* Do not check the checksum on decomp	*/
#define XMF_NOPREFS	(1<<11) /* Are prefs allowed ?			*/
#define XMF_XFD		(1<<12) /* Is XFD unpacking allowed ?		*/
#define XMF_EXTERNALS	(1<<13) /* Is extern allowed ?			*/
#define XMF_AUTOPASSWD	(1<<14) /* Automatic password			*/
#define XMF_AUTOPRHOOK  (1<<15) /* Automatic Progress hook		*/
#define XMF_NOPACK	(1<<16) /* destination file equals source	*/
#define XMF_OWNPASSWORD (1<<17) /* free password buffer later !!!	*/
#define XMF_KEY16	(1<<18) /* got a 16 bit key (needed, as key may */
#define XMF_KEY32	(1<<19) /* got a 32 bit key  be 0 - no check)   */

#ifdef DEBUG
void 	DebugError(STRPTR, ...);			/* debug.c */
void 	DebugRunTime(STRPTR, ...);			/* debug.c */
void    DebugTagList(STRPTR, struct TagItem *);		/* debug.c */
#endif

extern struct DosLibrary       *DOSBase;		/* libinit.a */
extern struct Hook		fhinhook;		/* hook_fh.c */
extern struct Hook		fhouthook;		/* hook_fh.c */
extern struct IntuitionBase    *IntuitionBase;		/* libinit.a */
extern struct Hook		meminhook;		/* hook_mem.c */
extern struct Hook		memouthook;		/* hook_mem.c */
extern struct ExecBase         *SysBase;		/* libinit.a */
extern struct UtilityBase      *UtilityBase;		/* libinit.a */
extern struct Library	       *XpkBase;		/* libinit.a */

XPK_ALLINONE LONG	callprogress(struct XpkBuffer *);			/* progress.c */
XPK_ALLINONE UWORD	cchecksum(ULONG *, ULONG);				/* checksum.c */
XPK_ALLINONE void	closesub(struct XpkBuffer *);				/* sublibs.c */
XPK_ALLINONE LONG	freebufs(struct XpkBuffer *);				/* xbuf.h */
XPK_ALLINONE struct XpkPrefsSemaphore *	GetPrefsSem(void);			/* objects.c */
XPK_ALLINONE UBYTE	hchecksum(STRPTR, ULONG);				/* checksum.c */
XPK_ALLINONE APTR	hookread(struct XpkBuffer *, ULONG, APTR, ULONG);	/* hook.c */
XPK_ALLINONE APTR	hookwrite(struct XpkBuffer *, ULONG, APTR, ULONG);	/* hook.c */
XPK_ALLINONE ULONG	idfromname(STRPTR);					/* sublibs.c */
XPK_ALLINONE struct XpkBuffer *		initxbuf(void);				/* xbuf.h */
XPK_ALLINONE struct Library *		opensub(struct XpkBuffer *, ULONG);	/* sublibs.c */
XPK_ALLINONE LONG	parsebuftags(struct XpkBuffer*, struct TagItem*);	/* tags.c */
XPK_ALLINONE LONG	parseerrortags(struct TagItem *, LONG);			/* tags.c */
XPK_ALLINONE void	parsegettags(struct XpkBuffer *);			/* tags.c */
XPK_ALLINONE void	percentages(struct XpkFib *);				/* fib.c */
XPK_ALLINONE void	updatefib(struct XpkBuffer *);				/* fib.c */
XPK_ALLINONE ASM(LONG)	xpkopen(REG(a0, struct XpkBuffer **),
			REG(a1, struct TagItem *), REG(d2,ULONG) A4PROTO);	/* open.c */

ASM(LONG)  LIBXpkExamine(REG(a0, struct XpkFib *), REG(a1, struct TagItem *) A4PROTO);
ASM(LONG)  LIBXpkPack(REG(a0, struct TagItem *) A4PROTO);
ASM(LONG)  LIBXpkUnpack(REG(a0, struct TagItem *) A4PROTO);
ASM(LONG)  LIBXpkOpen(REG(a0, struct XpkBuffer **), REG(a1, struct TagItem *) A4PROTO);
ASM(LONG)  LIBXpkRead(REG(a0, struct XpkBuffer *), REG(a1, STRPTR), REG(d0, ULONG));
ASM(LONG)  LIBXpkWrite(REG(a0, struct XpkBuffer *), REG(a1, STRPTR), REG(d0, ULONG));
ASM(LONG)  LIBXpkSeek(REG(a0, struct XpkBuffer *), REG(d0, LONG), REG(d1, ULONG));
ASM(LONG)  LIBXpkClose(REG(a0, struct XpkBuffer *));
ASM(LONG)  LIBXpkQuery(REG(a0, struct TagItem *));
ASM(APTR)  LIBXpkAllocObject(REG(d0, ULONG), REG(a0, struct TagItem *));
ASM(void)  LIBXpkFreeObject(REG(d0, ULONG), REG(a0, APTR));
ASM(BOOL)  LIBXpkPrintFault(REG(d0, LONG), REG(a0, STRPTR));
ASM(ULONG) LIBXpkFault(REG(d0, LONG), REG(a0, STRPTR), REG(a1, STRPTR), REG(d1, ULONG));
ASM(LONG)  LIBXpkPassRequest(REG(a0, struct TagItem *));

#endif /* XPKMASTER_XPKMASTER_H */
