#include "libinit.h"

/* Reserved library-function and dummy entrypoint */
LONG LIB_Reserved(void)
{
	return 0;
}

struct ExecBase    *SysBase;

ULONG LibVectors[] = {
	FUNCARRAY_32BIT_NATIVE,
	(ULONG) &LIB_Open,
	(ULONG) &LIB_Close,
	(ULONG) &LIB_Expunge,
	(ULONG) &LIB_Reserved,

	(ULONG) &LIBXpksPackerInfo,
	(ULONG) &LIBXpksPackChunk,
	(ULONG) &LIBXpksPackFree,
	(ULONG) &LIBXpksPackReset,
	(ULONG) &LIBXpksUnpackChunk,
	(ULONG) &LIBXpksUnpackFree,
	0xFFFFFFFF
};

struct LibInitStruct
{
	ULONG	LibSize;
	void	*FuncTable;
	void	*DataTable;
	void	(*InitFunc)(void);
};

struct LibInitStruct LibInitStruct = {
	sizeof(struct XpkSubBase),
	LibVectors,
	NULL,
	(void (*)(void)) &LibInit
};

static const char LibVersion[] = "$VER: " LIBID;

static const struct Resident RomTag = {
	RTC_MATCHWORD,
	&RomTag,
	&RomTag + 1,
	RTF_PPC | RTF_AUTOINIT,
	LIBVER,
	NT_LIBRARY,
	0,
	LIBNAME,
	&LibVersion[6],
	&LibInitStruct
};


ULONG __amigappc__ = 1;

BPTR LibExpunge(struct XpkSubBase *XpkSubBase)
{
	if ((XpkSubBase->xsb_Lib.lib_OpenCnt == 0))
	{
		BPTR seglist;

		seglist = XpkSubBase->xsb_SegList;
		Remove(&XpkSubBase->xsb_Lib.lib_Node);

		FreeMem((APTR)((ULONG)(XpkSubBase) - (ULONG)(XpkSubBase->xsb_Lib.lib_NegSize)),
				XpkSubBase->xsb_Lib.lib_NegSize + XpkSubBase->xsb_Lib.lib_PosSize);

		return seglist;
	} else XpkSubBase->xsb_Lib.lib_Flags |= LIBF_DELEXP;

	return 0L;
}

struct Library *LibInit(struct XpkSubBase *XpkSubBase, BPTR SegList, struct ExecBase *sysbase)
{
	SysBase = sysbase;

	XpkSubBase->xsb_Lib.lib_Revision     = LIBREV;
	XpkSubBase->xsb_SegList              = SegList;
	XpkSubBase->xsb_SysBase              = SysBase;

	return &XpkSubBase->xsb_Lib;
}

struct Library *LIB_Open(void)
{
	struct XpkSubBase *XpkSubBase = (struct XpkSubBase *)REG_A6;

	XpkSubBase->xsb_Lib.lib_Flags &= ~LIBF_DELEXP;
	XpkSubBase->xsb_Lib.lib_OpenCnt++;

	return &XpkSubBase->xsb_Lib;
}

BPTR LIB_Close(void)
{
	struct XpkSubBase *XpkSubBase = (struct XpkSubBase *)REG_A6;

	if (XpkSubBase->xsb_Lib.lib_OpenCnt > 0) XpkSubBase->xsb_Lib.lib_OpenCnt--;

	if ((XpkSubBase->xsb_Lib.lib_OpenCnt == 0) && (XpkSubBase->xsb_Lib.lib_Flags & LIBF_DELEXP))
		return LibExpunge(XpkSubBase);

	return 0L;
}

BPTR LIB_Expunge(void)
{
	struct XpkSubBase *XpkSubBase = (struct XpkSubBase *)REG_A6;

	return LibExpunge(XpkSubBase);
}

