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

	global

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

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

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

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


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


struct Library *GuiGFXBase = NULL;
struct Library *RenderBase = NULL;



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


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

	InitGlobal()
	CloseGlobal()

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

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

	CloseLibrary(GuiGFXBase);
	GuiGFXBase = 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);
	}

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

	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 && RenderBase && MainPool)
	{
		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;
	}
}
