//
// TinyPTC by Gaffer
// www.gaffer.org/tinyptc
//
extern "C" {
#include "tinyptc.h"
}
#include "windows.h"
#include "stdio.h"
#include "conio.h"
//////////////////////////////

#define USEFMOD true
//#define USEMEMLOAD
//#define USEMEMLOADRESOURCE

#include "fmod/lib/minifmod.h"

#ifndef USEMEMLOAD

unsigned int fileopen(char *name)
{
	return (unsigned int)fopen(name, "rb");
}

void fileclose(unsigned int handle)
{
	fclose((FILE *)handle);
}

int fileread(void *buffer, int size, unsigned int handle)
{
	return fread(buffer, 1, size, (FILE *)handle);
}

void fileseek(unsigned int handle, int pos, signed char mode)
{
	fseek((FILE *)handle, pos, mode);
}

int filetell(unsigned int handle)
{
	return ftell((FILE *)handle);
}

#else

typedef struct 
{
	int length;
	int pos;
	void *data;
} MEMFILE;


unsigned int memopen(char *name)
{
	MEMFILE *memfile;

	memfile = (MEMFILE *)calloc(sizeof(MEMFILE),1);

#ifndef USEMEMLOADRESOURCE
	{	// load an external file and read it
		FILE *fp;
		fp = fopen(name, "rb");
		if (fp)
		{
			fseek(fp, 0, SEEK_END);
			memfile->length = ftell(fp);
			memfile->data = calloc(memfile->length,1);
			memfile->pos = 0;

			fseek(fp, 0, SEEK_SET);
			fread(memfile->data, 1, memfile->length, fp);
			fclose(fp);
		}
	}
#else
	{	// hey look some load from resource code!
		HRSRC		rec;
		HGLOBAL		handle;

		rec = FindResource(NULL, name, RT_RCDATA);
		handle = LoadResource(NULL, rec);
		
		memfile->data = LockResource(handle);
		memfile->length = SizeofResource(NULL, rec);
		memfile->pos = 0;
	}
#endif

	return (unsigned int)memfile;
}

void memclose(unsigned int handle)
{
	MEMFILE *memfile = (MEMFILE *)handle;

#ifndef USEMEMLOADRESOURCE
	free(memfile->data);			// dont free it if it was initialized with LockResource
#endif

	free(memfile);
}

int memread(void *buffer, int size, unsigned int handle)
{
	MEMFILE *memfile = (MEMFILE *)handle;

	if (memfile->pos + size >= memfile->length)
		size = memfile->length - memfile->pos;

	memcpy(buffer, (char *)memfile->data+memfile->pos, size);
	memfile->pos += size;
	
	return size;
}

void memseek(unsigned int handle, int pos, signed char mode)
{
	MEMFILE *memfile = (MEMFILE *)handle;

	if (mode == SEEK_SET) 
		memfile->pos = pos;
	else if (mode == SEEK_CUR) 
		memfile->pos += pos;
	else if (mode == SEEK_END)
		memfile->pos = memfile->length + pos;

	if (memfile->pos > memfile->length)
		memfile->pos = memfile->length;
}

int memtell(unsigned int handle)
{
	MEMFILE *memfile = (MEMFILE *)handle;

	return memfile->pos;
}
#endif

/*
void songcallback(FMUSIC_MODULE *mod, unsigned char param)
{
	printf("order = %d, row = %d      \r", FMUSIC_GetOrder(mod), FMUSIC_GetRow(mod));
}
*/

/*
[
	[DESCRIPTION]

	[PARAMETERS]
 
	[RETURN_VALUE]

	[REMARKS]

	[SEE_ALSO]
]
*/

	FMUSIC_MODULE *mod;

	void InitFMOD()
	{
		
	

#ifndef USEMEMLOAD
	FSOUND_File_SetCallbacks(fileopen, fileclose, fileread, fileseek, filetell);
#else
	FSOUND_File_SetCallbacks(memopen, memclose, memread, memseek, memtell);
#endif


	// ==========================================================================================
	// INITIALIZE
	// ==========================================================================================
	if (!FSOUND_Init(44100, 0))
	{
		printf("Error upon initialization\n");
		return;
	}

	// ==========================================================================================
	// LOAD SONG
	// ==========================================================================================
	mod = FMUSIC_LoadSong("C:/squademo.xm", NULL); //sampleloadcallback);
	if (!mod)
	{
		printf("Error loading song\n");
		return;
	}

	}

	void CloseFMOD()
	{
		
	FMUSIC_FreeSong(mod);
	FSOUND_Close();

	}

	void PlaySong()
	{
			FMUSIC_PlaySong(mod);

/*
	
	printf("Press any key to quit\n");
	printf("=========================================================================\n");
	printf("Playing song...\n");

	{
		char key = 0;
		do
		{
			int		ord = 0, row = 0;
			float	mytime = 0;
			if (kbhit())
			{
				key = getch();
			}

#ifdef USEFMOD
			ord = FMUSIC_GetOrder(mod);
			row = FMUSIC_GetRow(mod);
			mytime = (float)FMUSIC_GetTime(mod) / 1000.0f;
#endif

			printf("ord %2d row %2d seconds %5.02f %s      \r", ord, row, mytime, (row % 8 ? "    " : "TICK"));

		} while (key != 27);
	}


	printf("\n");
*/
	}

/////////////////////////////////

#define WIDTH 640
#define HEIGHT 480
#define SIZE WIDTH*HEIGHT
   
static int noise;
static int carry;
static int index;
static int seed = 0x12345;
static int pixel[SIZE*2];

int main()
{
#ifndef _DEBUG
	int r = MessageBox(NULL,"Run Fullscreen?","Please choose",MB_YESNOCANCEL);
	if (r==IDCANCEL) return 0;
	if (r==IDYES) windowed=0;
	if (r==IDNO) windowed=1;
#else
	windowed=1;
#endif

	if (!ptc_open("test",WIDTH,HEIGHT)) return 1;
	InitFMOD();
	PlaySong();
    
    while (1)
    {
		static int coww=32;
        for (index=0; index<SIZE; index+=rand()%5)
        {
			coww++;
            noise = seed;
            noise >>= 3;
            noise ^= seed;
            carry = noise & 13;
            noise >>= 1;
            seed >>= 1;
            seed |= (carry << 30);
            noise &= 0xFF;
			switch (rand()&15)
			{
			case 0:			
				pixel[index] -=  + (index%WIDTH) * (index/HEIGHT) - 0;
				break;
			case 1:
				pixel[index] +=  + (index%WIDTH) * (index/HEIGHT) - 0;
				break;
			case 2:
			case 3:
			default:
				pixel[index] = (pixel[index]+pixel[index+1]+pixel[index+2]+pixel[index+3])/4;
				break;
			}
			pixel[index] |= 1;
        }
        ptc_update(pixel);
    }
	CloseFMOD();
}
