//
// customized version of my dbp_image (because glyphix needs specific features)
// one day I will release a second version of dbp_image which may include lots
// of features from this release ...
//
// (C)2001 Wauters Kris
//
// For more information, check out http://www.snoozys-dc-stuff.be.tf
//
// To KOS - 2010 Indiket

#include <kos.h>
#include "glyphix_image.h"

#define RGB565(r, g, b) ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);

struct dbp_hdr 
{
	char   version[2];        /* version code of DBP file, currently 1A */
	char   creationdate[8];   /* filecreationdate (format mmddyyyy)     */
	char   creator[48];       /* copyright notification                 */
	char   xmax1;             /* byte 1 of width of picture             */
	char   xmax2;             /* byte 2 of width of picture             */
	char   xmax3;             /* byte 3 of width of picture             */
	char   ymax1;             /* byte 1 of height of picture            */
	char   ymax2;             /* byte 2 of height of picture            */
	char   ymax3;             /* byte 3 of height of picture            */
};

unsigned short *mempos;

//---------------------------------------------------------------------
// this will clear the menu and other regions on screen
// used to prevent "garbage" on screen
//---------------------------------------------------------------------
void clear_rectangle(int x,int y,int width, int height, int r,int g,int b)
{
int xmax;
int ymax;
int ytmp;

	//--- defines bottomright coördinates of rectangle ---
	xmax = x+width;
	ymax = y+height;
	ytmp = y;

	while (x!=xmax)
		{
		x++;
		y=ytmp;
		while (y!=ymax)
			{
			y++;
			vram_s[x + (640*y)] = RGB565(r,g,b);
			}
		}
	return;
}

//--- colorfilter for RED transparancy (if view = TRANSPARANT_RED) ---/
int check_red_transparant(int r,int g,int b)
{
	if ((r>175) && (g<80) && (b<80))
		return 0;

	return 1;
}

//--- colorfilter for BLACK transparancy (if view = TRANSPARANT_BLACK) ---/
int check_black_transparant(int r,int g,int b)
{
	if ((r<8) && (g<8) && (b<8))
		return 0;

	return 1;
}


//--- little routine to do some shifting of bytes ---
int shift_add(char c, int r)
{
  int result = r;

  result *= 10;
  result += (int)c - (int)'0';
  
  return result;
}

//--- this function will load a DBP file and returns it ---
unsigned char *img_load(char *fn)
{
	int fd;
	int numbytes;
	unsigned char *tmpfile;

	//--- load file from disc ---
	fd = fs_open(fn, O_RDONLY);
	fs_seek(fd,0,SEEK_END);
	numbytes = fs_tell(fd);
	fs_seek(fd,0,SEEK_SET);
	tmpfile = (unsigned char*)malloc(numbytes);
	fs_read(fd,tmpfile,numbytes);
	fs_close(fd);

	return tmpfile;
}
//--- this function will place the given image on the specified location on screen ---
int img_place(unsigned char *img,int xpos,int ypos,int size,int display,int view)
{
	int x;
	int y;
	int r;
	int g;
	int b;
	int color=1;
	int xmax;
	int ymax;
	struct dbp_hdr dbphdr;

	//--- analyse picture header and do some calculations ---
	memcpy(&dbphdr, img, sizeof(dbphdr)); img += sizeof(dbphdr);
	xmax=0;
	ymax=0;
	xmax = shift_add(dbphdr.xmax1,0);
	xmax = shift_add(dbphdr.xmax2,xmax);
	xmax = shift_add(dbphdr.xmax3,xmax);
	ymax = shift_add(dbphdr.ymax1,0);
	ymax = shift_add(dbphdr.ymax2,ymax);
	ymax = shift_add(dbphdr.ymax3,ymax);

	//--- display picture on specified location ---
	y = 0;
	while (y !=ymax) 
		{
		x = 0;
		y++;
		while (x !=xmax) 
			{
			x++;
			r = *img++;
			g = *img++;
			b = *img++;
			if (view == TRANSPARANT_RED)
				{
				color=check_red_transparant(r,g,b);
				}
			if (view == TRANSPARANT_BLACK)
				{
				color=check_black_transparant(r,g,b);
				}
			if (color==1)
			{
			if ((x!=1) && (x!=xmax) && (y!=1) && (y!=ymax))
				 {
				 if (size==1)
					{ 
					if (display==SCREEN)
						{
						vram_s[(x+xpos) + (640*(y+ypos))] = RGB565(r,g,b);
						}
					if (display==BUFFER)
						{
						mempos[(x+xpos) + (640*(y+ypos))] = RGB565(r,g,b);
						}
					}
				 if (size==2)
					{ 
					if (display==SCREEN)
						{
						vram_s[((x*2)+xpos) + (640*((y*2)+ypos))] = RGB565(r,g,b);
						vram_s[((x*2)+xpos+1) + (640*((y*2)+ypos+1))] = RGB565(r,g,b);
						}
					if (display==BUFFER)
						{
						mempos[((x*2)+xpos) + (640*((y*2)+ypos))] = RGB565(r,g,b);
						mempos[((x*2)+xpos+1) + (640*((y*2)+ypos+1))] = RGB565(r,g,b);
						//mempos[((x*2)+xpos+1) + (640*((y*2)+ypos))] = vram_s[((x*2)+xpos+1) + (640*((y*2)+ypos))];
						//mempos[((x*2)+xpos) + (640*((y*2)+ypos+1))] = vram_s[((x*2)+xpos) + (640*((y*2)+ypos+1))];
						}
					}

				 }
			}
			}
		}
	return 1;
}
//--- this function will return the width in pixels of the given image ---
int img_width(char *img)
{
	int xmax=0;
	int ymax=0;
	struct dbp_hdr dbphdr;

	memcpy(&dbphdr, img, sizeof(dbphdr)); 
	xmax = shift_add(dbphdr.xmax1,0);
	xmax = shift_add(dbphdr.xmax2,xmax);
	xmax = shift_add(dbphdr.xmax3,xmax);
	ymax = shift_add(dbphdr.ymax1,0);
	ymax = shift_add(dbphdr.ymax2,ymax);
	ymax = shift_add(dbphdr.ymax3,ymax);

	return xmax;
}

//--- this function will return the height in pixels of the given image ---
int img_height(char *img)
{
	int xmax=0;
	int ymax=0;
	struct dbp_hdr dbphdr;

	memcpy(&dbphdr, img, sizeof(dbphdr));
	xmax = shift_add(dbphdr.xmax1,0);
	xmax = shift_add(dbphdr.xmax2,xmax);
	xmax = shift_add(dbphdr.xmax3,xmax);
	ymax = shift_add(dbphdr.ymax1,0);
	ymax = shift_add(dbphdr.ymax2,ymax);
	ymax = shift_add(dbphdr.ymax3,ymax);

	return ymax;
}
//--- this function will return the date of creation of the given image ---
//--- format mmddyyyy                                                   ---
unsigned char *img_creationdate(char *img)
{
	struct dbp_hdr dbphdr;
	unsigned char *tmp;

	tmp = (unsigned char*)malloc(8);
	memcpy(&dbphdr, img, sizeof(dbphdr));
	memcpy(tmp,dbphdr.creationdate,8);

	return tmp;
}

//--- this function will return the copyright string of the given image ---
//--- 48 chars                                                          ---
unsigned char *img_copyright(char *img)
{
	struct dbp_hdr dbphdr;
	unsigned char *tmp;

	tmp = (unsigned char*)malloc(48);
	memcpy(&dbphdr, img, sizeof(dbphdr));
	memcpy(tmp,dbphdr.creator,48);

	return tmp;
}

//--- this function will place the image which is created in the buffer ---
//--- onto the actual screen                                            ---
int flush_buffer()
{
	int x=0;
	int y=0;

	while (y <480) 
		{
		x = 0;
		y++;
		while (x <640) 
			{
			x++;
			if ((x!=1) && (x!=640) && (y!=1) && (y!=480))
				 {
				 vram_s[x + (640*y)] = mempos[x + (640*y)];
				 }
			}
		}

	return 1;
}

//--- just initialise and reserve some memory for virtual screenbuffer ---
int img_mem_init()
{
	mempos = (unsigned short*)malloc(614400);
	return 1;
}

//--- clears buffer with specified color ---
int init_buffer(int r,int g,int b)
{
	int x=0;
	int y=0;

	while (y !=480) 
		{
		x = 0;
		y++;
		while (x !=640) 
			{
			x++;
			if ((x!=1) && (x!=640) && (y!=1) && (y!=480))
				 {
				 mempos[x + (640*y)] = RGB565(r,g,b);
				 }
			}
		}

	return 1;
}

//---------------------------------------------------------------------
// copy rectangle area from screen
//---------------------------------------------------------------------
Img *copy_rectangle(int xpos,int ypos,int rect_pixels)
{
	short x,y;
	Img *rv;
	int count=0;

	rv = (Img *)malloc(sizeof(Img));
	rv->rect_data = (unsigned short *)malloc(rect_pixels*rect_pixels*2);
	for (y = ypos+1;y < (ypos+rect_pixels+1);y++)
		{
		for (x = xpos+1;x < (xpos+rect_pixels+1);x++)
			{
			rv->rect_data[count]=vram_s[x + (640*y)];
			count++;
			}
		}
	return rv;
}

//---------------------------------------------------------------------
// place rectangle area on screen
//---------------------------------------------------------------------
void put_rectangle(Img *rect,int xpos,int ypos,int rect_pixels)
{
	short x,y;
	int count;
	count = 0;

	for (y = ypos+1;y < (ypos+rect_pixels+1);y++)
		{
		for (x = xpos+1;x < (xpos+rect_pixels+1);x++)
			{
			vram_s[x + (640*y)] = rect->rect_data[count];
			count++;
			//vram_s[x + (640*y)] = RGB565(255,0,0);

			}
		}
}
//--- this function will load and display DBP files on the screen.
//--- ARGUMENTS:
//--- fn = filename, path to file included
//--- xpos = most left position of the picture
//--- ypos = most top position of the picture
int dbp_load_from_disc(char *fn, int xpos, int ypos)
{
	int fd;
	int numbytes;
	int x;
	int y;
	int r;
	int g;
	int b;
	int xmax;
	int ymax;
	int pointer=0;
	struct dbp_hdr dbphdr;
	
	//NOTE 2010: Original function used malloc to read image data, but didn't use free...
	//One good solution is without dynamic allocation, just create the char :)

	//--- load file from disc ---
	fd = fs_open(fn,O_RDONLY);
	if (fd <0) {
		return -1;
	}

	fs_seek(fd,0,SEEK_END);
	numbytes = fs_tell(fd);
	//We know filesize, so just create the char array!
	unsigned char tmpfile[numbytes]; //Not dynamic allocation...
	fs_seek(fd,0,SEEK_SET);
	fs_read(fd,tmpfile,numbytes);
	fs_close(fd);

	//--- analyse picture header and do some calculations ---
	memcpy(&dbphdr, tmpfile, sizeof(dbphdr));
	pointer += sizeof(dbphdr);
	xmax=0;
	ymax=0;
	xmax = shift_add(dbphdr.xmax1,0);
	xmax = shift_add(dbphdr.xmax2,xmax);
	xmax = shift_add(dbphdr.xmax3,xmax);
	ymax = shift_add(dbphdr.ymax1,0);
	ymax = shift_add(dbphdr.ymax2,ymax);
	ymax = shift_add(dbphdr.ymax3,ymax);

	//--- display picture on specified location ---
	y = 0;
	while (y !=ymax) 
		{
		x = 0;
		y++;
		while (x !=xmax) 
			{
			x++;
			r = tmpfile[pointer++];
			g = tmpfile[pointer++];
			b = tmpfile[pointer++];
			if ((x!=1) && (x!=xmax) && (y!=1) && (y!=ymax))
				 {
				 vram_s[(x+xpos) + (640*(y+ypos))] = RGB565(r,g,b);
				 }
			}
		}
	return 0;
}

