// Convert windows bitmap picture to gba bitmap picture
//

#include "stdafx.h"
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "utilities.h"

struct RGB{
	byte blue;
	byte green;
	byte red;
};

static byte *pstack;
static DWORD capacity;
static DWORD index;

int stack_init(unsigned int cap)
{
	pstack = (byte*)malloc(cap);
	memset(pstack, 0, cap);
	capacity = cap;
	index = 0;
	
	return 0;
}

int stack_push(void* ele_addr, unsigned int len)
{
	if( index + len > capacity ) return -1;
	
	memcpy(pstack+index, ele_addr, len);
	index = index + len;
	
	return 0;
}

int stack_pop (void* ele_addr, unsigned int len)
{
	if( index == 0 ) return -1;
	if( len > index ) return -2;
	
	memcpy(ele_addr, pstack + index - len, len);
	index = index - len;
	
	return 0;
}

int bmp2gba(const char *fname)
{
	int fdr, fdw;
	byte ch;
	WORD wd;
	DWORD dwd;
	struct RGB pixel;
	DWORD bmpoff;
	DWORD width, d_width;
	DWORD height, d_height;
	WORD planes;
	DWORD compression;
	
	DWORD i, j, k;
	byte *line;
	
	fdr = open(fname, O_RDONLY|O_BINARY);
	
	read(fdr, &wd, 2);
	if( wd != 0x4D42) return errmsg("not bitmap picture for windows", -1);
	
	for(k=0;k<0x09-0x01;k++) read(fdr, &ch, 1);
	
	read(fdr, &bmpoff, 4); //fprintf(stderr, "bmpoff = %xh\n", bmpoff);
	
	read(fdr, &dwd, 4); //fprintf(stderr, "header length = %xh\n", dwd);
	if(dwd != 0x0028) return errmsg("header length invalid", -1);
	
	read(fdr, &width, 4); //fprintf(stderr, "width = %d\n", width);
	read(fdr, &height, 4); //fprintf(stderr, "height = %d\n", height);
	read(fdr, &planes, 2); //fprintf(stderr, "planes = %d\n", planes);
	
	read(fdr, &wd, 2); //fprintf(stderr, "bit for color = %d\n", wd);
	if(wd != 24) return errmsg("not 24-bit true color", -1);
	
	read(fdr, &compression, 4); //fprintf(stderr, "compression = %d\n", compression);
	if(compression != 0) errmsg("not bi_rgb", -1);
	
	read(fdr, &dwd, 4); //fprintf(stderr, "bitmap data size = %xh\n", dwd);
	for(k=0;k<4;k++) read(fdr, &dwd, 4);
	
	for(k=0;k<bmpoff - 0x0036;k++) read(fdr, &ch, 1);

	char *gba_img = changeExtName(fname, "imb");
	FILE *fstr = fopen(gba_img, "w");	// O_CREAT|O_TRUNC
	if( fstr ) fclose(fstr);
	fdw = open(gba_img, O_WRONLY|O_BINARY);
	if( fdw <= 0 )
	{
		close(fdr);
		return 1;
	}
	if( width > 480 ) d_width = 480;
	else d_width = width;
	write(fdw, &d_width, 2);
	if( height > 320) d_height = 320;
	else d_height = height;
	write(fdw, &d_height, 2);
	
	stack_init(d_width * d_height * 2);
	for(j=0;j<d_height;j++)
	{
		for(i=0;i<d_width;i++)
		{
		//	memset(&pixel, 0, sizeof(pixel));
			read(fdr, &pixel, sizeof(pixel));
			wd = 0;
			wd = pixel.blue >> 3;
			wd = wd << 5 | pixel.green >> 3;
			wd = wd << 5 | pixel.red >> 3;
			if( stack_push(&wd, 2) ) return 1;
		}
		
		for(k=0;k<width-d_width;k++) read(fdr, &pixel, sizeof(pixel));
		for(k=0;k<(width % 4);k++) read(fdr, &ch, 1);
	}
	
	line = (byte*)malloc(d_width*2);
	for(j=0;j<d_height;j++)
	{
		if( stack_pop(line, d_width*2) ) return 1;
		if( write(fdw, line, d_width*2) < d_width*2 ) return 1;
	}
	
	close(fdr);
	close(fdw);
	//fprintf(stderr, "Success!\n");
	return 0;
}
