
/*********************************************************************
----------------------------------------------------------------------

	global

----------------------------------------------------------------------
*********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>

#include <exec/memory.h>
#include <proto/exec.h>
#include <libraries/screennotify.h>


#include "defs.h"
#include "debug.h"


static void MemStats(LONG *numalloc, LONG *numbytes);


struct Library *GuiGFXBase = NULL;
struct Library *ScreenNotifyBase = NULL;
struct Library *IconBase = NULL;


static APTR MainPool = NULL;
static char versionstring[] = "$VER: " PROGNAME " " __VERSION__ "";


/*********************************************************************
----------------------------------------------------------------------

	InitGlobal()
	CloseGlobal()

----------------------------------------------------------------------
*********************************************************************/

void CloseGlobal(void)
{
	CloseLibrary(IconBase);
	IconBase = NULL;

	CloseLibrary(GuiGFXBase);
	GuiGFXBase = NULL;
	
	CloseLibrary(ScreenNotifyBase);
	ScreenNotifyBase = NULL;


	if (MainPool)
	{
		LONG count, bytes;
		
		MemStats(&count, &bytes);

		if (count > 0 && bytes > 0)
		{
			printf("*** internal memory leak detected - %ld allocations (%ld bytes) pending.\n", count, bytes);
			printf("*** don't worry: the memory will be returned to the system.\n");
		}
		else if (count < 0 || bytes < 0)
		{
			printf("*** warning: pool memory structure might be corrupt.\n");
			if (count < 0 && bytes < 0)
			{
				printf("*** more memory has been freed than allocated (%ld allocations, %ld bytes).\n", -count, -bytes);
			}
		}

		DeletePool(MainPool);
		MainPool = NULL;

	}
}



BOOL InitGlobal(void)
{
	BOOL success = FALSE;

	MainPool = CreatePool(MEMF_FAST, POOLPUDSIZE, POOLTHRESHOLD);
	if (!MainPool)
	{
		MainPool = CreatePool(MEMF_ANY, POOLPUDSIZE, POOLTHRESHOLD);
	}

	ScreenNotifyBase = OpenLibrary("screennotify.library", 0);
	IconBase = OpenLibrary("icon.library", 37);

	GuiGFXBase = OpenLibrary("progdir:libs/guigfx.library", GUIGFX_VERSION);
	if (!GuiGFXBase)
	{
		GuiGFXBase = OpenLibrary("guigfx.library", GUIGFX_VERSION);
	}
	if (!GuiGFXBase)
	{
		printf("*** could not open guigfx.library v%d.\n", GUIGFX_VERSION);	
	}


	if (GuiGFXBase && MainPool && IconBase)
	{
		srand48(time(NULL));
		success = TRUE;
	}


	if (!success)
	{
		CloseGlobal();
	}

	return success;	
}



/*********************************************************************
----------------------------------------------------------------------

	custom memory management
	
	Malloc()
	Malloclear()
	Free()

----------------------------------------------------------------------
*********************************************************************/

static LONG alloccount = 0;
static LONG allocbytes = 0;


void *Malloc(unsigned long size)
{
	ULONG *buf;
	
	if (buf = AllocPooled(MainPool, size + sizeof(ULONG)))
	{
		*buf++ = size;

		alloccount++;
		allocbytes += size + sizeof(ULONG);
	}
	
	return (void *) buf;
}


void *Malloclear(unsigned long size)
{
	ULONG *buf;
	
	if (buf = AllocPooled(MainPool, size + sizeof(ULONG)))
	{
		*buf++ = size;

		memset(buf, 0, size);

		alloccount++;
		allocbytes += size + sizeof(ULONG);
	}
	
	return (void *) buf;
}


void Free(void *mem)
{
	if (mem)
	{
		ULONG *buf = (ULONG *) mem;

		--buf;

		alloccount--;
		allocbytes -= *buf + sizeof(ULONG);
		
		FreePooled(MainPool, buf, *buf + sizeof(ULONG));
	}
}


static void MemStats(LONG *numalloc, LONG *numbytes)
{
	if (numalloc)
	{
		*numalloc = alloccount;
	}

	if (numbytes)
	{
		*numbytes = allocbytes;
	}
}
