/*
** startup.c
** 8th May 2000
** David McMinn
** Example startup and library table code for AmigaOS shared libraries
*/


#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <exec/execbase.h>
#include <exec/resident.h>
#include <exec/initializers.h>

#include <proto/exec.h>

#include "defs.h"
#include "libbase.h"
#include "libfuncs.h"
#include "libinit.h"
#include "semaphores.h"


#define VERSION     39                  /* Version of our plugin */
#define REVISION    01                  /* Revision of our plugin */
#define LIBNAME     "title_freepens"    /* Name of our plugin (must be the same as the executable filename minus the .plugin [gets added later]) */
#define LIBVER      " 39.01"            /* part of the version string for our plugin */


/* If someone tries to run a library or any other kind of shared resident thing,
** then we must return -1 immediately. This is what we do here, but because we are
** not linking any startup code, we must make sure that this file/function is linked
** first in the executable so that it is the first thing executed
*/
LONG ASM LibStart(void)
{
	return(-1);
}


/* Define some variables which get forward referenced
** at various points in the tables below.
*/
extern char             LibName[];
extern char             LibID[];
extern APTR             InitTab[];
extern APTR             FuncTab[];
extern struct MyDataTab DataTab;
extern APTR             EndResident;


/* This is where all the magic happens for the shared executables,
** as this is how the OS identifies the executable as a shared lib etc.
*/
struct Resident ROMTag =
{
	RTC_MATCHWORD,  /* 68k ILLEGAL instruction, used to identify this as a library */
	&ROMTag,        /* Pointer to the ROMTag for extra check that this is a library */
	&EndResident,   /* Pointer to the address to continue scanning for ROMTag, usually end of program, but can be anywhere after this ROMTag */
	RTF_AUTOINIT,   /* Tells loader that rt_Init field points to code to be initialised */
	VERSION,        /* Version of this library */
	NT_LIBRARY,     /* Type of module (library in this case) */
	0,              /* Initialization priority */
	LibName,        /* Pointer to node name */
	LibID,          /* Pointer to ID string */
	InitTab         /* Pointer to initialization table */
};


/* Some strings used in identifying and versioning this shared object */
char    LibName[] = LIBNAME ".plugin";
char    LibID[] = LIBNAME LIBVER;
char    Copyright[] = "(c)2000 by David McMinn";
char    VERString[] = "\0$VER: " LIBNAME LIBVER " (05.05.2000)";


/* Table of initialisation data for this module */
APTR   InitTab[] =
{
	(APTR)sizeof(struct myLibBase), /* Size of our library base */
	FuncTab,                        /* Pointer to table of functions in this library */
	&DataTab,                       /* Pointer to table of data used with InitResident to initialise libbase */
	(APTR)InitLib                   /* Pointer to initialisation routine of library, called when first loadseg'ed into memory */
};


/* Table of available functions in this library */
APTR    FuncTab[] =
{
	/* These standard library functions must always be here, in this order */
	(APTR)OpenLib,          /* Called each time on exec/OpenLibrary */
	(APTR)CloseLib,         /* Called each time on exec/CloseLibrary */
	(APTR)ExpungeLib,       /* Called when the library is to be flushed from memory */
	(APTR)ExtFuncLib,       /* Spare function, currently MUST return NULL */

	/* Your library functions go here */
	(APTR)GetClassInfo,

	/* List of functions terminated by -1 */
	(APTR)((LONG)-1)
};


/* Data table that exec.library/InitResident() uses to initialise parts of the library base */
/*UWORD   DataTab[] =
{
	INITBYTE(OFFSET(Node, ln_Type), NT_LIBRARY),
	INITLONG(OFFSET(Node, ln_Name), (ULONG)&LibName[0]),
	INITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED|LIBF_CHANGED),
	INITWORD(OFFSET(Library, lib_Version), VERSION),
	INITWORD(OFFSET(Library, lib_Revision), REVISION),
	INITLONG(OFFSET(Library, lib_IdString), (ULONG)&LibID[0]),
	0,0
};
*/


/* Argh! Horrible nasty way to do this, all the macros are set up to create
** a sequence of UWORDS, but I ain't got a bloody compiler that will take the
** data as constant. And VBCC doesn't even like the OFFSET macro...nnnnngh
*/
struct MyDataTab
{
	UWORD init_0; UWORD offset_0; UWORD content_0;
	UWORD init_1; UWORD offset_1; ULONG content_1;
	UWORD init_2; UWORD offset_2; UWORD content_2;
	UWORD init_3; UWORD offset_3; UWORD content_3;
	UWORD init_4; UWORD offset_4; UWORD content_4;
	UWORD init_5; UWORD offset_5; ULONG content_5;
	ULONG end;
} DataTab =
{
#ifdef __VBCC__
	0xe000, 8, NT_LIBRARY,
	0xc000, 10, (ULONG)&LibName[0],
	0xe000, 14, LIBF_SUMUSED|LIBF_CHANGED,
	0xd000, 20, VERSION,
	0xd000, 22, REVISION,
	0xc000, 24, (ULONG)&LibID[0],
#else
	INITBYTE(OFFSET(Node, ln_Type), NT_LIBRARY),
	0xc000, (UWORD)OFFSET(Node, ln_Name), (ULONG)&LibName[0],
	INITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED|LIBF_CHANGED),
	INITWORD(OFFSET(Library, lib_Version), VERSION),
	INITWORD(OFFSET(Library, lib_Revision), REVISION),
	0xc000, (UWORD)OFFSET(Library, lib_IdString), (ULONG)&LibID[0],
#endif
	0
};

APTR EndResident;

