#include <stdio.h>
#include <msdos.cf>
#include <concorde.h>
#include <tornado.h>
#include <ysmaze2.h>



void MazePutBmpCenter
      (PAGE *tmp,char *bm,int bx,int by,int blx,int bly,int tcx,int tcy);
void MazeConstrainBmp
      (PAGE *tmp,MAZEZBUF *zb,int tlx,int tly,int tcx,int tcy,int cx,int z);


#define BITMAP_NUM_MAX 16
#define INT_MAX  0x7fffffff
#define INT_MIN -0x80000000

#define Yabs(x) ((x)>=0 ? (x) : -(x))
#define Ylarge(a,b) ((a)>=(b) ? (a) : (b))
#define Ysmall(a,b) ((a)<=(b) ? (a) : (b))

typedef struct objindex {
	int x,z;           /* 視野座標系の(x,z)の値 */
	int lx,ly;         /* ビットマップの実際の寸法 */
	int bx,by;         /* ビットマップの横,縦Pixel数 */
	char *bmp;         /* ビットマップデータ */
	struct objindex *prev;
	struct objindex *next;
} BMPBUF;


static int nbmp,vx,vz,vdir,vlen;
static BMPBUF bmp[BITMAP_NUM_MAX],*top;
static MAZESCREEN ms;




void MazePrepareInsertBitmap(int x,int z,int dir,int len,MAZESCREEN *ims)
{
	bmp[0].z=INT_MIN;
	bmp[0].bmp=NULL;
	bmp[0].prev=NULL;
	bmp[0].next=NULL;

	top=&bmp[0];
	nbmp=1;

	vx=x;
	vz=z;
	vdir=dir;
	vlen=len;

	ms=(*ims);
}



void MazeInsertBitmap(char *bm,int bx,int by,int lx,int ly,int x,int z)
{
	BMPBUF *tmp,*prv,*app;

	x=x-vx;
	z=vz-z;  /* 迷路座標系は,Z軸が北を向いちゃった(失策.無念.) */
	Rot2Hq(&x,&z,-vdir);

	if(Yabs(x)>vlen || z>vlen || z<=0)
	{
		return;
	}


	if(nbmp>=BITMAP_NUM_MAX)
	{
		if(top->z > z)
		{
			tmp=top;
			top=top->next;
			top->prev=NULL;
			nbmp=BITMAP_NUM_MAX-1;
		}
		else
		{
			return;
		}
	}
	else
	{
		tmp=&bmp[nbmp];
	}


	tmp->x=x;
	tmp->z=z;
	tmp->lx=lx;
	tmp->ly=ly;
	tmp->bx=bx;
	tmp->by=by;
	tmp->bmp=bm;
	tmp->prev=NULL;
	tmp->next=NULL;


	for(app=top; (app->z)>z; app=(app->next));
	prv=app->prev;
	if(prv!=NULL)
	{
		prv->next=tmp;
	}
	else
	{
		top=tmp;
	}
	app->prev=tmp;


	tmp->prev=prv;
	tmp->next=app;
	nbmp++;
}


void MazeFlushBitmap(PAGE *wp,MAZEZBUF *zb,char *buf)
{
	int blx,bly; /* ビットマップの見えるべき大きさ */
	int tlx,tly,tcx,tcy; /* ビットマップ展開PAGEの大きさと中心 */
	int cx; /* ビットマップをwpに書くときの中心 */
	int x1,y1,x2,y2;
	PAGE tmp;
	BMPBUF *ptr;

	for(ptr=top; ptr->z >0; ptr=ptr->next)
	{
		blx=(ptr->lx)*ms.mag/(ptr->z);
		bly=(ptr->ly)*ms.mag/(ptr->z);

		tlx=Ysmall(blx,ms.x1-ms.x0);
		tly=Ysmall(bly,ms.y1-ms.y0);
		tcx=tlx/2;
		tcy=tly/2;
		YGH_initPage(&tmp,SEG_VIRTU,(int)buf,tlx,tly);
		YGH_clearPage(&tmp,0);

		MazePutBmpCenter(&tmp,ptr->bmp,ptr->bx,ptr->by,blx,bly,tcx,tcy);
		cx=ms.cx+(ptr->x)*ms.mag/(ptr->z);
		MazeConstrainBmp(&tmp,zb,tlx,tly,tcx,tcy,cx,ptr->z);

		x1=      cx-tcx;
		y1=ms.cy   -tcy;
		x2=x1+tlx-1;
		y2=y1+tly-1;
		YGH_put(wp,buf,x1,y1,x2,y2);
	}
}


static void MazePutBmpCenter
       (PAGE *tmp,char *bm,int bx,int by,int blx,int bly,int tcx,int tcy)
{
	int tx1,ty1,tx2,ty2;

	tx1=tcx-blx/2;
	ty1=tcy-bly/2;
	tx2=tx1+blx-1;
	ty2=ty1+bly-1;

	YGH_putZoom(tmp,bm,bx,by,tx1,ty1,tx2,ty2);
}

#define MODE_NONE  0
#define MODE_ERASE 1
static void MazeConstrainBmp
        (PAGE *tmp,MAZEZBUF *zb,int tlx,int tly,int tcx,int tcy,int cx,int z)
{
	int x,zbx,stx,edx,dif;
	int mod,erx;

	stx=Ylarge(  0  ,tcx-cx+ms.x0); /* 書き出しx(tmp座標) */
	edx=Ysmall( tlx ,tcx+ms.x1-cx); /* 終了x(tmp座標) */
	dif=cx-tcx-ms.x0; /* tmp座標からzb座標へのオフセット */

	mod=MODE_NONE;
	erx=0;
	YGH_color(tmp,0);
	for(x=stx; x<=edx; x++)
	{
		zbx=x+dif;

		if(zb[zbx].viewz>z)
		{
			if(mod==MODE_ERASE)
			{
				YGH_filledBox(tmp,erx,0,x,tly);
				mod=MODE_NONE;
			}
			zb[zbx].viewz=z;
		}
		else
		{
			if(mod==MODE_NONE)
			{
				erx=x;
				mod=MODE_ERASE;
			}
		}
	}

	if(mod==MODE_ERASE)
	{
		YGH_filledBox(tmp,erx,0,edx,tly);
	}
}
