#ifndef XPKMASTER_XPKMASTER_H
#define XPKMASTER_XPKMASTER_H

/* Includeheader

	Name:		xpkmaster.h
	Main:		xpkmaster
	Versionstring:	$VER: xpkmaster.h 1.0 (05.10.96)
	Author:		SDI
	Distribution:	PD
	Description:	Master library global definitions and declarations
			and prototypes

 1.0   05.10.96 : first real version
*/

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

#ifdef __SASC
  #define BUGGY_SASC  /* Try to hide unusual values from SASs switch() */
#endif

#ifndef __MAXON__
  #include <pragma/xpksub_lib.h>
  #ifdef USE_POWERPACKER
    #include <pragma/powerpacker_lib.h>
  #endif
#else
  #include "SDI_xpksub.h"	// Stubs for xpksub and powerpacker
  #define __asm
#endif

#ifdef SUPPORT_A4
  #define A4SUPP	,a4
  #define A4SUPP2	,xbuf->xb_regA4
  #define A4PROTO	,register __a4 ULONG a4
#else
  #define A4SUPP
  #define A4SUPP2
  #define A4PROTO
#endif


#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"

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

#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

#define CHUNKSIZE 50000

/* 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	*/
  ULONG  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;
};

#define XIO_GETOUTBUF 1

#define XPKMF_SEEKABLE	0x0001	/* ALL chunks (-dict) are independent	*/
#define XPKMF_DICTCHUNK	0x0002	/* First chunk is a global dictionary	*/
#define XPKMF_FIXSPEED	0x0004	/* Speed is for A3000/25MHz/SCRAM/2.04	*/
#define XPKMF_NOCLOBBER	0x0008	/* Don't overwrite			*/

/* 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 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_TYPE		0x0f
#define XPKCHUNK_RAW		0x00
#define XPKCHUNK_PACKED		0x01
#define XPKCHUNK_FDATA		0x02 /* Protection bits, file comment ... */
#define XPKCHUNK_END		0x0f

#define XPKCHUNKF_ENTRYPOINT	0x80 /* Stream can be seeked to at this point */

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_PKSTD  20

/* 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, 1..9	*/
  struct Headers	 xb_Headers;	/* global and local file header */
  ULONG   xb_Format;		/* type of file				*/
  ULONG   xb_ChunkLen;		/* compressed chunk len			*/
  LONG    xb_Result;		/* error code from last call		*/
  LONG    xb_Result2;		/* possible result from IoErr()		*/
  UBYTE   xb_ErrMsg[80];	/* ASCII error message			*/
  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	*/
  STRPTR  xb_PackerName;	/* lib name of the packer to be used	*/
  ULONG   xb_PackingFlags;	/* desired packing mode			*/
  ULONG   xb_ULen;		/* Uncompressed length of file		*/
  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_SubPackMode;	/* Packing mode to be used		*/
  ULONG   xb_SubID;		/* ID of currently open sub		*/
  ULONG   xb_ChunkSize;		/* Chunk size to use for packing	*/
  ULONG   xb_FirstChunk;	/* Smallest chunk so far		*/
  ULONG   xb_MinChunk;		/* Minimum size of a chunk		*/
  ULONG   xb_Flags;		/* private for xpkmaster		*/
  LONG    xb_Priority;		/* task pri during packing		*/
  struct XpkInfo	*xb_SubInfo; /* Info of current open sub-lib	*/
  struct Library	*xb_SubBase; /* Currently open sub-library	*/
  ULONG   xb_InLen;		/* Number of bytes to (un)pack		*/
  ULONG   xb_OutLen;		/* Number of bytes written		*/
  ULONG   xb_OutMemType;	/* Type of memory for output buffer	*/
  STRPTR  xb_OutName;		/* Output file name			*/
  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	*/
  STRPTR  xb_LastMsg;		/* The last progress message		*/
#ifdef SUPPORT_A4
  ULONG	  xb_regA4;
#endif
};

/* Values for MasterFlags */
#define XMF_PRIVFH	0x0001	/* We opened the FH, so we close it.	*/
#define XMF_PACKING	0x0002	/* This is a packing operation.		*/
#define XMF_PASSTHRU	0x0004	/* Pass uncompressed data through	*/
#define XMF_GETOUTBUF	0x0008	/* Get output buffer when size known	*/
#define XMF_NOCLOBBER	0x0010	/* Don't overwrite			*/
#define XMF_EOF		0x0020	/* End of file				*/
#define XMF_IDSENT	0x0040	/* First four bytes of unpacked sent	*/
#define XMF_INITED	0x0080	/* Sublib buffers have been allocted	*/
#define XMF_GLOBHDR	0x0100	/* GlobHdr is already written		*/
#define XMF_SHORTERR	0x0200	/* Long error messages wanted		*/
#define XMF_LOSSYOK	0x0400	/* Lossy compression permitted		*/
#define XMF_OWNTASKPRI	0x0800	/* Altered task pri, restore		*/
#define XMF_NOCRC	0x1000	/* Do not check the checksum on decomp	*/
#define XMF_USECOMMENT	0x2000	/* Store FIB in file comment		*/

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

#ifndef XPK_MINOS_37
ULONG	findtag(struct TagItem *, ULONG);		// tags.c
struct TagItem *MyNextTagItem(struct TagItem **);	// tags.c
#else
#define findtag(a,b)		(FindTagItem(b,a)->ti_Data)
#define MyNextTagItem		NextTagItem
#endif

#if !defined(SUPPORT_A4) && defined(XPK_MINOS_37)
  #define MyCallHookPkt(a,b)	CallHook(a,0,b)
#else
  ULONG __asm MyCallHookPkt(register __a0 struct Hook *,
  register __a1 APTR A4PROTO);
#endif

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

STRPTR	basename(STRPTR);					// util.c
LONG	callprogress(struct XpkBuffer *);			// progress.c
UWORD	cchecksum(ULONG *, ULONG);				// checksum.c
void	closesub(struct XpkBuffer *);				// sublibs.c
LONG	copydata(struct XpkBuffer *, ULONG, ULONG);		// hook.c
LONG	freebufs(struct XpkBuffer *);				// xbuf.h
void	geterror (struct XpkBuffer *);				// geterror.c
UBYTE	hchecksum(STRPTR, ULONG);				// checksum.c
APTR	hookread(struct XpkBuffer *, ULONG, APTR, ULONG);	// hook.c
APTR	hookwrite(struct XpkBuffer *, ULONG, APTR, ULONG);	// hook.c
ULONG	idfromname(STRPTR);					// util.c
struct XpkBuffer	*initxbuf(void);			// xbuf.h
struct Library		*opensub(struct XpkBuffer *, ULONG);	// sublibs.c
LONG	parsebuftags(struct XpkBuffer*, struct TagItem*, ULONG);// tags.c
void	parseerrortags(struct TagItem *);			// tags.c
void	parsegettags(struct XpkBuffer *);			// tags.c
void	percentages(struct XpkFib *);				// fib.c
void	updatefib(struct XpkBuffer *);				// fib.c
LONG	__asm xpkopen(   register __a0 struct XpkBuffer **,
			 register __a1 struct TagItem *,
			 register __d2 ULONG
			 A4PROTO);				// open.c
LONG	xpkopenwrite(struct XpkBuffer **, struct TagItem *);	// open.c

#ifdef __cplusplus
  extern "C" {
#endif

LONG __asm XpkExamine   (register __a0 struct XpkFib *,
			 register __a1 struct TagItem * A4PROTO);
LONG __asm XpkPack      (register __a0 struct TagItem * A4PROTO);
LONG __asm XpkUnpack    (register __a0 struct TagItem * A4PROTO);
LONG __asm XpkOpen      (register __a0 struct XpkBuffer **,
			 register __a1 struct TagItem * A4PROTO);
LONG __asm XpkRead      (register __a0 struct XpkBuffer *,
			 register __a1 STRPTR,
			 register __d0 ULONG);
LONG __asm XpkSeek      (register __a0 struct XpkBuffer *,
			 register __d0 LONG,
			 register __d1 LONG);
LONG __asm XpkClose     (register __a0 struct XpkBuffer *);
LONG __asm XpkQuery     (register __a0 struct TagItem *);
LONG __asm XpkWrite	(register __a0 struct XpkBuffer *,
			 register __a1 STRPTR,
			 register __d0 ULONG);

#ifdef __cplusplus
  }
#endif
#endif /* XPKMASTER_XPKMASTER_H */
