/*
 *					MAG & MAKI Library 'Mag.c'		for FM-TOWNS
 *
 *				- MAKIchan Graphic loader is not 鮪だ！ -
 *
 *							programmed by MALOR
 */

#include <egb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wild.h"
#include "mag.h"
#include "pixel.h"

#define tolower(x) (((x)<='Z')&&((x)>='A')?((x)-'A'+'a'):(x))

/* Global Vari. */

MAGHEADER	maghead;					/* MAGのヘッダ */
MKIHEADER	mkihead;					/* MAKIのベッダ */
int			sizp;						/* MAKIのピクセルサイズ */
int			siza;						/* MAGのflag aのサイズ */
int			headtop;					/* MAGのヘッダのオフセット */
char		pal[768];					/* 現在のパレット情報 */
char		*flga,*flgb,*flg,*pix;		/* flag&pixel格納アドレス */
int			xpixel;						/* 横方向のピクセル数の半分 */
/* 現在メモリに存在するイメージ情報 */
char		*vram=NULL;					/* イメージ格納アドレス */
int			screen_mode;				/* スクリーンモード(MAG互換) */
int			image_mode;					/* メモリ上のデータのモード */
int			lx,ly;						/* 左上座標 */
int			rx,ry;						/* 右下座標 */
char		comment[81];				/* コメント */

/* Prototype declaration */

int		stringcmp(char *s,char *d);
void	flag_write(void);

/* Main program */

void	flag_write(void)
{
	FILE	*fp;

	fp=fopen("flagdump","wb");
	fwrite(flg,1,siza*8,fp);
	fclose(fp);

}

int		stringcmp(char *s,char *d)
{
	for (;*s!='\0';s++,d++)
		if ((tolower(*s))!=(tolower(*d)))
			return FALSE;
	return TRUE;
}

int		mag_get_head(FILE *fp)
{
	char buf[10],*p;
	int i;
	
	fseek(fp,0,0);
	fread(buf,1,8,fp);
	if (!stringcmp("MAKI02",buf))
		return FALSE;

	fseek(fp,0,0);

	for(i=0,p=comment,headtop=0;;i++,headtop++) {
		if (fread(buf,1,1,fp)!=1)
			return FALSE;
		if (*buf==EOC) {
			*p = '\0';
			headtop++;
			break;
		}
		if (*buf==0x0d||*buf==0x0a)
			i = 80;
		if (i<80) 
			*p++ = *buf;
	}
	
	if (fread((char *)&maghead,1,sizeof(MAGHEADER),fp)<sizeof(MAGHEADER))
		return FALSE;

	/* flag a size */
	xpixel = (maghead.screen&COL256)?(maghead.rx/4-maghead.lx/4+1)
									:(maghead.rx/8-maghead.lx/8+1);
	siza = (xpixel*(maghead.ry-maghead.ly+1)+7) / 8;

	/*
	printf(
		"---------------------------------------------------------\n"
		"ヘッダ情報\n"
		"機種コード : %d  機種依存フラグ : %d  画面モード : %d\n"
		"位置 : (%3d,%3d)-(%3d,%3d)\n"
		"---------------------------------------------------------\n"
		"         |  offset | size\n"
		"---------------------------------------------------------\n"
		"comment  |      0  | %5d \n"
		"header   |  %5d  |    32 \n"
		"palette  |  %5d  | %5d \n"
		"flag a   |  %5d  | %5d \n"
		"flag b   |  %5d  | %5d \n"
		"pixcel   |  %5d  | %5d \n"
		"---------------------------------------------------------\n\n"
		,maghead.machine,maghead.rflg,maghead.screen
		,maghead.lx,maghead.ly,maghead.rx,maghead.ry
		,headtop,headtop,(headtop+32),(maghead.screen&COL256)?768:48
		,headtop+maghead.offa,siza
		,headtop+maghead.offb,maghead.sizb
		,headtop+maghead.offp,maghead.sizp);
	*/

	rx = maghead.rx;
	ry = maghead.ry;
	lx = maghead.lx;
	ly = maghead.ly;
	screen_mode = maghead.screen;
	image_mode = maghead.screen;

	fread(pal,1,(image_mode&COL256)?768:48,fp);		/* palette read */

	return TRUE;
}

int		mag_decode(FILE *fp,int mode,int x,int y)
{
	/* flag a size */
	xpixel = (maghead.screen&COL256)?(maghead.rx/4-maghead.lx/4+1)
									:(maghead.rx/8-maghead.lx/8+1);
	siza = (xpixel*(maghead.ry-maghead.ly+1)+7) / 8;
			/* xpixel = 横方向のピクセル数の半分 */

	if ((flga=(char *)malloc(siza))==NULL) {
		printf("magl : can't allocate memory ( flag a )\n");
		goto Exit;
	}

	if ((flgb=(char *)malloc(maghead.sizb))==NULL) {
		printf("magl : can't allocate memory ( flag b )\n");
		goto Exit;
	}

	if ((pix=(char *)malloc(maghead.sizp))==NULL) {
		printf("magl : can't allocate memory ( pixcel )\n");
		goto Exit;
	}

	if ((flg=(char *)malloc(siza*8))==NULL) {
		printf("magl : can't allocate memory ( flag )\n");
		goto Exit;
	}

	if(!(mode&VRAM)) {
		vram=(char *)calloc(1,siza*32+(xpixel*8*32));
									/* ↑モザイクのために8ライン余分に確保！ */
		if (vram==NULL) printf("magl : memory allocate error (vram)\n");
		}

	fseek(fp,headtop+maghead.offa,0);				/* flag a read */
	if (fread(flga,1,siza,fp)!=siza)
		printf("magl : inproper size ( flag a )\n");

	fseek(fp,headtop+maghead.offb,0);				/* flag b read */
	if (fread(flgb,1,maghead.sizb,fp)!=maghead.sizb)
		printf("magl : inproper size ( flag b )\n");

	fseek(fp,headtop+maghead.offp,0);				/* pixcel read */
	if (fread(pix,1,maghead.sizp,fp)!=maghead.sizp)
		printf("magl : inproper size ( pixcel )\n");

	if ((vram!=NULL)&&(!(mode&VRAM)))
		Lineofs = (unsigned int)xpixel*8;
	else if (mode&DOS)
		Lineofs = (unsigned int)640;
	else
		Lineofs = (unsigned int)1024*((maghead.screen&COL256)?2:1);
	Mofs[0]  = -(int)(( 0+ 0*Lineofs)/2);
	Mofs[1]  = -(int)(( 4+ 0*Lineofs)/2);
	Mofs[2]  = -(int)(( 8+ 0*Lineofs)/2);
	Mofs[3]  = -(int)((16+ 0*Lineofs)/2);
	Mofs[4]  = -(int)(( 0+ 1*Lineofs)/2);
	Mofs[5]  = -(int)(( 4+ 1*Lineofs)/2);
	Mofs[6]  = -(int)(( 0+ 2*Lineofs)/2);
	Mofs[7]  = -(int)(( 4+ 2*Lineofs)/2);
	Mofs[8]  = -(int)(( 8+ 2*Lineofs)/2);
	Mofs[9]  = -(int)(( 0+ 4*Lineofs)/2);
	Mofs[10] = -(int)(( 4+ 4*Lineofs)/2);
	Mofs[11] = -(int)(( 8+ 4*Lineofs)/2);
	Mofs[12] = -(int)(( 0+ 8*Lineofs)/2);
	Mofs[13] = -(int)(( 4+ 8*Lineofs)/2);
	Mofs[14] = -(int)(( 8+ 8*Lineofs)/2);
	Mofs[15] = -(int)(( 0+16*Lineofs)/2);

	Lineofs /= 2;

	if ((vram!=NULL)&&(!(mode&VRAM))) {			/* メインメモリに展開 */
		/* printf("magl : pixel decode to main memory\n"); */
		mag((char *)(&maghead),mode|(!vram),0,xpixel);
	} else if (!(mode&DOS)) {					/* 16/256色モード */
		vram = NULL;
		if ((maghead.rx-maghead.lx)>1023) {
			printf("magl : picture is too wide \n");
			goto Exit;
		}
		if ((maghead.ry-maghead.ly)>511) {
			maghead.ly = 0;
			maghead.ry = 511;
			y = 0;
		}
		if ((maghead.rx+x)>1023||(maghead.ry+y)>511
					||(maghead.lx+x)<0||(maghead.ly+y)<0) {
			x = 0;
			y = 0;
		}
		/* printf("magl : pixcel decode to vram (16/256)\n"); */
		mag((char *)(&maghead),mode|VRAM
			,(x+y*1024)/((maghead.screen&COL256)?1:2),xpixel);
		/* printf("magl : pixcel decode end \n"); */
	} else {									/* DOS互換モード */
		vram = NULL;
		if (maghead.screen&COL256) {
			printf("magl : irregal screen mode\n");
			goto Exit;
		}
		if ((maghead.rx-maghead.lx)>639) {
			printf("magl : picture is too wide \n");
			goto Exit;
		}
		if ((maghead.ry-maghead.ly)>399) {
			maghead.ly = 0;
			maghead.ry = 399;
			y = 0;
		}
		if ((maghead.rx+x)>639||(maghead.ry+y)>399
					||(maghead.lx+x)<0||(maghead.ly+y)<0) {
			x = 0;
			y = 0;
		}
		/* printf("magl : pixcel decode to vram (MS-DOS)\n"); */
		mag((char *)(&maghead),mode|VRAM,(x+y*640)/2,xpixel);
		/* printf("magl : pixcel decode end\n"); */
	}

	/* flag_write(); */

	free(flg);
	free(pix);
	free(flgb);
	free(flga);

	flg = NULL; pix = NULL; flgb = NULL; flga = NULL;

	return TRUE;

Exit:
	if (flg!=NULL)
		free(flg);
	if (pix!=NULL)
		free(pix);
	if (flgb!=NULL)
		free(flgb);
	if (flga!=NULL)
		free(flga);

	flg = NULL; pix = NULL; flgb = NULL; flga = NULL;

	return FALSE;
}

int		mki_get_head(FILE *fp)
{
	int	i;
	unsigned char tmp;
	headtop = 0;

	fseek(fp,0,0);
	if (fread((char *)&mkihead,1,sizeof(MKIHEADER),fp)<sizeof(MKIHEADER))
		return FALSE;

	if ((!stringcmp("MAKI01A",mkihead.id))&&(!stringcmp("MAKI01B",mkihead.id)))
		return FALSE;

	for(i=0;i<23;i++)
		comment[i]=(mkihead.comment[i]<0x20)?' ':mkihead.comment[i];
	comment[23]='\0';

	/* モトローラ形式 -> インテル形式 */
	tmp              = mkihead.sizb.m.h ;
	mkihead.sizb.m.h = mkihead.sizb.m.l ;
	mkihead.sizb.m.l = tmp ;
	tmp               = mkihead.sizpa.m.h ;
	mkihead.sizpa.m.h = mkihead.sizpa.m.l ;
	mkihead.sizpa.m.l = tmp ;
	tmp               = mkihead.sizpb.m.h ;
	mkihead.sizpb.m.h = mkihead.sizpb.m.l ;
	mkihead.sizpb.m.l = tmp ;

	sizp = mkihead.sizpa.s + mkihead.sizpb.s;

	/*
	printf(
	"------------------------\n"
	"  Header Information    \n"
	"------------------------\n"
	"header size : 48\n"
	"palettesize : 48\n"
	"flag a size : 1000\n"
	"flag b size : %d\n"
	"pixcel size : %d\n"
	"------------------------\n"
	,mkihead.sizb.s,sizp);
	*/

	lx = 0;
	ly = 0;
	rx = 639;
	ry = 399;
	screen_mode = 0;
	image_mode = 0;

	fread(pal,1,48,fp);							/* palette read */

}

int		mki_decode(FILE *fp,int mode,int x,int y)
{
	/* flag a size : 1000 = 320*400 / (4*4) / 8 */
	if ((flga=(char *)malloc(1000))==NULL) {
		printf("magl : can't allocate memory ( flag a )\n");
		goto Exit;
	}

	if ((flgb=(char *)malloc(mkihead.sizb.s))==NULL) {
		printf("magl : can't allocate memory ( flag b )\n");
		goto Exit;
	}

	if ((pix=(char *)malloc(sizp))==NULL) {
		printf("magl : can't allocate memory ( pixcel )\n");
		goto Exit;
	}

	/* flag size : 16000 = 320*400 / 8 */
	if ((flg=(char *)malloc(16000))==NULL) {
		printf("magl : can't allocate memory ( flag )\n");
		goto Exit;
	}

	/* vram : 128000 = 640 * 400 / 2 */
	if (!(mode&VRAM))
		vram = (char *)calloc(1,128000+((rx/8-lx/8+1)*4*32));

	fread(flga,1,1000,fp);								/* flag a read */
	fread(flgb,1,mkihead.sizb.s,fp);					/* flag b read */
	fread(pix,1,sizp,fp);								/* pixcel read */
	
	if ((vram!=NULL)&&(!(mode&VRAM))) {			/* メインメモリに展開 */
		/* printf("magl : mki decode to main memory\n"); */
		mki((char *)(&mkihead),mode|(!VRAM),0);
	} else if (!(mode&DOS)) {						/* 1024*512/16色モード */
		vram = NULL;
		if ((x+639)>1023||(y+399)>511||x<0||y<0) {
			x = 0;
			y = 0;
		}
		mki((char *)(&mkihead),mode|VRAM,(x+y*1024)/2);
		/* printf("magl : mki pixcel decode end \n"); */
	} else {									/* DOS互換モード */
		vram = NULL;
		mki((char *)(&mkihead),mode|VRAM,0);
		/* printf("magl : mki pixcel decode end\n"); */
	}

	free(flg);
	free(pix);
	free(flgb);
	free(flga);

	flg = NULL; pix = NULL; flgb = NULL; flga = NULL;

	return TRUE;

Exit:
	if (flg!=NULL)
		free(flg);
	if (pix!=NULL)
		free(pix);
	if (flgb!=NULL)
		free(flgb);
	if (flga!=NULL)
		free(flga);

	flg = NULL; pix = NULL; flgb = NULL; flga = NULL;

	return FALSE;
}

int		display(int slx,int sly,int ssx,int ssy,int dx,int dy)
{

	if (screen_mode&DOS)
		move(ssx/2,ssy,(int)vram+(lx%8+slx+sly*(rx/8-lx/8+1)*8)/2
			,(rx/8-lx/8+1)*8/2,0x0104,(dx+dy*640)/2,320);
	else if (screen_mode&COL256)
		move(ssx,ssy,(int)vram+(lx%4+slx+sly*(rx/4-lx/4+1)*4),(rx/4-lx/4+1)*4
			,0x010c,(dx+dy*1024),1024);
	else
		move(ssx/2,ssy,(int)vram+(lx%8+slx+sly*(rx/8-lx/8+1)*8)/2
			,(rx/8-lx/8+1)*8/2,0x0104,(dx+dy*1024)/2,512);

	return TRUE;
}

int		set_palette(void)
{
	unsigned char *p;
	int	i,r,g,b;
	
	if (image_mode&COL256)
		for (i=0,p=(unsigned char *)pal;i<256;i++) {
			g = (int)*p++;
			r = (int)*p++;
			b = (int)*p++;
			outpb(PALNO,i);
			outpb(PALB,b);
			outpb(PALR,r);
			outpb(PALG,g);
		}
	else 
		for (i=0,p=(unsigned char *)pal;i<16;i++) {
			g = ((int)*p++)&0xf0;
			r = ((int)*p++)&0xf0;
			b = ((int)*p++)&0xf0;
			outpb(PALNO,i);
			outpb(PALB,b);
			outpb(PALR,r);
			outpb(PALG,g);
		}

	return TRUE ;
}

