#include "mcount.h"

typedef unsigned long DWORD;
DWORD GetTickCount();

typedef struct _tagFILE FILE;

FILE *fopen(char *fname, char *mode);
int fwrite(void *buf, int size, int count, FILE *f);
int fclose(FILE*);

void *malloc(int size);
void free(void *buf);

struct mcountdata _mcountdata;

/*
 * ========== called to initialize profiling =================
 *
 * ndepth = max depth of profiled functions call stack
 * nentries = max nr of caller-callee pairs
 *
 */

void monstartup(int ndepth, int nentries)
{
	_mcountdata.mcountdataSize= sizeof(struct mcountdata);
	_mcountdata.statsEntrySize= sizeof(struct mstatdata);
	_mcountdata.stackEntrySize= sizeof(struct mstackentry);
    _mcountdata.ndepth= ndepth;
    _mcountdata.nentries= nentries;

    _mcountdata.mstackbottom= (struct mstackentry *)malloc(ndepth*sizeof(struct mstackentry));
    _mcountdata.mstackptr= &_mcountdata.mstackbottom[ndepth];

    _mcountdata.mhashtable= (struct mstatdata **)malloc(16384 * sizeof(struct mstatdata *));

    _mcountdata.mstattable= (struct mstatdata *)malloc(nentries*sizeof(struct mstatdata));
    _mcountdata.mstatend= &_mcountdata.mstattable[nentries];
    _mcountdata.mstatentry= &_mcountdata.mstattable[-1];

    _mcountdata.moverflow=0;
    _mcountdata.mentrycountL=0;
	_mcountdata.mentrycountH=0;

    _mcountdata.mleaveproc= &mcountleave;

	_mcountdata.mtotalticks= GetTickCount();
	_mcountdata.mtotalclocks= *(DWORD*)0xa9000010;
	//GetThreadTimes(GetCurrentThread(), &_mcountdata.tCreate0, &_mcountdata.tExit0, &_mcountdata.tKernel0, &_mcountdata.tUser0);
    _mcountdata.menabled= 123321;
}

void monexit()
{
    FILE *f;

	if (_mcountdata.menabled!=123321)
		return;

    _mcountdata.menabled= 0;

	if (_mcountdata.mstattable==0)
		return;

	_mcountdata.mtotalticks = GetTickCount() - _mcountdata.mtotalticks;
	_mcountdata.mtotalclocks = *(DWORD*)0xa9000010 - _mcountdata.mtotalclocks;

	f= fopen("\\gmon.out", "w+b");
	fwrite(&_mcountdata, sizeof(struct mcountdata), 1, f);
    fwrite(_mcountdata.mstattable, sizeof(struct mstatdata), _mcountdata.nentries, f);
	fwrite(_mcountdata.mhashtable, sizeof(struct mstatdata*), 16384, f);
	fwrite(_mcountdata.mstackbottom, sizeof(struct mstackentry), _mcountdata.ndepth, f);
    fclose(f);

	if(_mcountdata.mstattable)
		free(_mcountdata.mstattable);
	if(_mcountdata.mstackbottom)
		free(_mcountdata.mstackbottom);
	if(_mcountdata.mhashtable)
		free(_mcountdata.mhashtable);
}


