#include <stdio.h>
#include <egb.h>
#include "stdlib.h"
#include <msdos.cf>
#include "FMCFRB.H"

#define	 GBUF_SIZE16	(321 * 241 * 2)
#define	 GBUF_SIZE8	(640 * 480 * 1)

#define  BITR(p1)	( (p1 & 0x03e0) >>  5 )
#define  BITG(p1)	( (p1 & 0x7c00) >> 10 )
#define  BITB(p1)	(  p1 & 0x1f )

typedef	struct {
	char *ptr ;
	short ds ;
	short sx,sy,ex,ey ;
}EGBPARM ;

extern char gwork[];	/* T-BIOS EGB ワーク */
extern char palt[] ;	/* パレット */

/***********************************************************
	GVRAM -> 重ね合わせ用バッファ(32k色モ−ド)
*************************************************************/
int	GvramToBuf16( int aflg, int ovr, short int *kbuf, int ix, int iy )
{
	int bx,by;

	short int *gbuf;		/* EGB_get用バッファ */
	EGBPARM   egb_p ;
	unsigned int r,g,b;
	unsigned int vbeta, bbeta;
	unsigned int xflg, yflg;

	gbuf = malloc( GBUF_SIZE16 );
	if( gbuf == NULL ){
		printf("Fail to malloc gbuf\n");
		exit( -1 );
	}
	egb_p.ptr = (char *)gbuf;
	egb_p.ds  = getds() ;
	egb_p.sx  = 0;
	egb_p.sy  = 0;
	egb_p.ex  = 320;
	egb_p.ey  = 240;
	EGB_getBlock( gwork, (char *)&egb_p ) ;

	xflg = (ix%2 != 0);	/* 2で割り切れなければ1	*/
	yflg = (iy%2 != 0);	/* 2で割り切れなければ1	*/

	if (aflg != 0){
		for( by=yflg; by < 480-yflg; by += 2){
			for( bx=xflg; bx < 640-xflg; bx += 2){
				vbeta = *(gbuf + bx/2 + by/2 * 321);
				vbeta = vbeta & 0x7fff; /* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + bx + by*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx + by*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx+1 + by*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx+1 + by*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx   + (by+1)*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx   + (by+1)*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx+1   + (by+1)*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx+1 + (by+1)*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
			if(xflg){	/* X方向へ0.5Dot 移動有り	*/
				vbeta = *(gbuf + (by+1)/2 * 321);	/* 右端	*/
				vbeta = vbeta & 0x7fff; /* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + by*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf +  by    * 640) = 
					*(kbuf + (by+1) * 640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf +  319 + by*640);/* 左端	*/
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + 639 + by    * 640) = 
					*(kbuf + 639 +(by+1) * 640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
		}
		if(yflg){	/* Y方向へ0.5Dot 移動有り	*/
			for( bx=xflg; bx < 640-xflg; bx += 2){
				vbeta = *(gbuf + (bx+1)/2);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + bx);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx)     = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx + 1);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx + 1) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}

				vbeta = *(gbuf + (bx+1)/2 + 641/2 * 321);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + bx + 479*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx   + 479*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx+1 + 479*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx+1 + 479*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
		}
	}else{
	if (ovr == 256 ){
		for( by=yflg; by < 480-yflg; by += 2){
			for( bx=xflg; bx < 640-xflg; bx += 2){
				vbeta = *(gbuf + (bx+1)/2 + (by+1)/2 * 321);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					*(kbuf + bx   + by*640)     = 
					*(kbuf + bx+1 + by*640)     = 
					*(kbuf + bx   + (by+1)*640) = 
					*(kbuf + bx+1 + (by+1)*640) = vbeta;
				}
			}
			if(xflg){	/* X方向へ0.5Dot 移動有り	*/
				vbeta = *(gbuf + (by+1)/2 * 321);	/* 左端の処理	*/
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					*(kbuf + by*640)     = 
					*(kbuf + (by+1)*640) = vbeta;
				}
				vbeta = *(gbuf + 319 + (by+1)/2 * 321);/* 右端	*/
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					*(kbuf + 639 + by*640)     = 
					*(kbuf + 639 + (by+1)*640) = vbeta;
				}
			}
		}
		if(yflg){	/* Y方向へ0.5Dot 移動有り	*/
			for( bx=xflg; bx < 640-xflg; bx += 2){
				vbeta = *(gbuf + (bx+1)/2);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					*(kbuf + bx   )     = 
					*(kbuf + bx+1 )     = vbeta;
				}
				vbeta = *(gbuf + (bx+1)/2 + (by+1)/2 * 321);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					*(kbuf + bx   + 479*640)     = 
					*(kbuf + bx+1 + 479*640)     = vbeta;
				}
			}
		}
	}else{
		for( by=yflg; by < 480-yflg; by += 2){
			for( bx=xflg; bx < 640-xflg; bx += 2){
				vbeta = *(gbuf + bx/2 + by/2 * 321);
				vbeta = vbeta & 0x7fff; /* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + bx + by*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx + by*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx+1 + by*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx+1 + by*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx   + (by+1)*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx   + (by+1)*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx+1   + (by+1)*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx+1 + (by+1)*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
			if(xflg){	/* X方向へ0.5Dot 移動有り	*/
				vbeta = *(gbuf + (by+1)/2 * 321);	/* 右端	*/
				vbeta = vbeta & 0x7fff; /* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + by*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf +  by    * 640) = 
					*(kbuf + (by+1) * 640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf +  319 + by*640);/* 左端	*/
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + 639 + by    * 640) = 
					*(kbuf + 639 +(by+1) * 640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
		}
		if(yflg){	/* Y方向へ0.5Dot 移動有り	*/
			for( bx=xflg; bx < 640-xflg; bx += 2){
				vbeta = *(gbuf + (bx+1)/2);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + bx);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx)     = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx + 1);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx + 1) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}

				vbeta = *(gbuf + (bx+1)/2 + 641/2 * 321);
				vbeta = vbeta & 0x7fff;	/* ス−パ−インポ−ズbit off */
				if( vbeta != 0 ){	/* 黒以外なら書き込み */
					bbeta  = *(kbuf + bx + 479*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx   + 479*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));

					bbeta  = *(kbuf + bx+1 + 479*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx+1 + 479*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
		}
	}
	}
	free( gbuf );
	return 0;
}

/***********************************************************
	GVRAM -> 重ね合わせ用バッファ(256色モ−ド)
*************************************************************/
int	GvramToBuf8( int aflg, int ovr, short int *kbuf )
{
	int	i;
	int bx,by;
	char	 *gbuf;		/* EGB_get用バッファ */
	EGBPARM   egb_p ;
	unsigned int r,g,b;
	unsigned int vbeta, bbeta;

	short int paltbl[256];	/* 32K色パレットテ−ブル*/
	unsigned int p_no;	/* パレット設定数	*/
	unsigned int p_color;	/* パレット番号		*/
	char	*p_ptr;		/* パレットのポインタ	*/

	/**********************************************************
			パレット表作成
	**********************************************************/
	_fill_char( paltbl, sizeof(paltbl), 0xffffffff ); /* 透明色で初期化 */

	p_ptr = palt;
	p_no = DWORD( p_ptr+0 );	/* 設定されているパレット数	*/
	p_ptr += 4;
	for( i=0; i<p_no; i++){
		p_color = DWORD( p_ptr );
		b = BYTE( p_ptr + 4 );
		r = BYTE( p_ptr + 5 );
		g = BYTE( p_ptr + 6 );
		p_ptr += 8;

		if( (b==0) && (r==0) && (g==0) ){
			continue;	/* 透明 */
		}

		paltbl[p_color] = ( ((g<<7)&0x7c00) + ((r<<2)&0x03e0) + ((b>>3)&0x001f) );
	}

	/**********************************************************
			画面GET	VRAM -> kbuf
	**********************************************************/
	gbuf = malloc( GBUF_SIZE8 );
	if( gbuf == NULL ){
		printf("Fail to malloc gbuf\n");
		exit( -1 );
	}
	egb_p.ptr = gbuf;
	egb_p.ds  = getds() ;
	egb_p.sx  = 0;
	egb_p.sy  = 0;
	egb_p.ex  = 639;
	egb_p.ey  = 479;
	EGB_getBlock( gwork, (char *)&egb_p ) ;

	if (aflg != 0){	/* 加算合成	*/
		for( by=0; by < 480; by ++){
			for( bx=0; bx < 640; bx ++){
				vbeta = paltbl[*(gbuf + bx + by * 640)];
				if( vbeta != 0xffffffff ){	/* 透明色以外なら書き込み */
					bbeta = *(kbuf + bx + by*640);
					r = _min( (BITR(bbeta)*256 + BITR(vbeta) * ovr), 31*256 )/256;
					g = _min( (BITG(bbeta)*256 + BITG(vbeta) * ovr), 31*256 )/256;
					b = _min( (BITB(bbeta)*256 + BITB(vbeta) * ovr), 31*256 )/256;
					*(kbuf + bx + by*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
		}
	}else{
	if (ovr == 256 ){
		for( by=0; by < 480; by ++){
			for( bx=0; bx < 640; bx ++){
				vbeta = paltbl[*(gbuf + bx + by * 640)];
				if( vbeta != 0xffffffff ){
					/* 透明色以外なら書き込み */
					*(kbuf + bx   + by*640)     = vbeta;
				}
			}
		}
	}else{
		for( by=0; by < 480; by ++){
			for( bx=0; bx < 640; bx ++){
				vbeta = paltbl[*(gbuf + bx + by * 640)];
				if( vbeta != 0xffffffff ){	/* 透明色以外なら書き込み */
					bbeta  = *(kbuf + bx + by*640);
					r = _min( ((BITR(vbeta) - BITR(bbeta) ) * ovr + BITR(bbeta)*256), 31*256 )/256;
					g = _min( ((BITG(vbeta) - BITG(bbeta) ) * ovr + BITG(bbeta)*256), 31*256 )/256;
					b = _min( ((BITB(vbeta) - BITB(bbeta) ) * ovr + BITB(bbeta)*256), 31*256 )/256;
					*(kbuf + bx + by*640) = ( ((r << 5)&0x3e0) | ((g << 10)&0x7c00) | (b&0x1f));
				}
			}
		}
	}
	}
	free( gbuf );
	return 0;
}