/****************************************************************************/
/*																			*/
/*		｢乙女座｣用プラグインツールサンプル									*/
/*																			*/
/*		パレットを統合するプラグインツール(16色と256色専用)					*/
/*		似た値のパレット値のドットを統合します。							*/
/*																			*/
/*		※これは、エフェクト系ツールでイメージをEGB関数を使用する例です。	*/
/*		  また、環境設定値の使用例でもあります。							*/
/*		※まぁ、大したソースではないので、流用したければ御事由にお使い		*/
/*		  下さい｡															*/
/****************************************************************************/

/*--------------------------------------------------------------------------*/
/*		乙女座用画像エフェクターの作成方法									*/
/*																			*/
/*	○大まかな流れ															*/
/*	  乙女座本体からイメージのアドレスを貰い、指定した範囲にエフェクトを	*/
/*	  行います。															*/
/*																			*/
/*	○注意事項																*/
/*	  tpspin.hをincludeして下さい｡											*/
/*	  マロックは(char *)pi_data->func1を使用して下さい｡						*/
/*	  フリーは(void *)pi_data->func2を使用して下さい｡						*/
/*	  エラーはヘッダーにあるPI_ERROR_XXXXXをセットして返して下さい｡			*/
/*	  ワーク等に使うローカルﾊﾞｯﾌｧのﾎﾟｲﾝﾀｰはﾌﾟﾗｸﾞｲﾝﾂｰﾙ内で宣言して下さい｡	*/
/*	  また、使い終わったら必ず開放して下さい｡								*/
/*																			*/
/*	○本体に返すパラメーター												*/
/*	　特になし																*/
/*																			*/
/*--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <wgb.h>
#include <egb.h>
#include <mos.h>
#include "tpspin.h"


#define PI_MALLOC( size )	((char*)pi_data->func1(size))
#define PI_FREE( buf )		(pi_data->func2(buf))
#define FNAME				(pi_data->fname)

/****************************************************************************/
int		pinHead(int, void *, void *, void *, void *);
int		APL_exec();
void	main();
/****************************************************************************/

const char longname[] = "パレット統合 for OTOMEZA";
const char shortname[] = "OT";
int			cnfg_max = 3;
PI_CNFG		cnfg[3] = {
				{"赤レベル", 0, 255, 1, 1 },
				{"緑レベル", 0, 255, 1, 1 },
				{"青レベル", 0, 255, 1, 1 }
			};
PI_TYPE		*pi_type;
PI_DATA		*pi_data;
PI_IMAGE	*pi_imge;
PI_PARA		*pi_para;
PI_CNFG		*pi_cnfg;
FRAME		*ret_fr;						/* 画像転送範囲			*/
char		*guiEgbPtr;
char		*g_para;

int pinHead(int service, void *arg1, void *arg2, void *arg3, void *arg4)
{
	FRAME	fr;
	int		ret;
	
	ret = 0;
	switch (service) {
	case 0:											/* 正式名称			*/
		strcpy((char *)arg1, longname);
		break;
	case 1:											/* 省略名称			*/
		strcpy((char *)arg1, shortname);
		break;
	case 2:											/* 初期化			*/
		pi_type = (PI_TYPE *)arg1;
		strcpy((* pi_type).name, longname);			/* モジュール名		*/
	//	(* pi_type).type = PI_EFFC_ALL;				/* Type				*/
		(* pi_type).type = PI_EFFC_ALORSL;			/* Type				*/
		(* pi_type).env1 = PI_SET_ENV;				/* 環境設定フラグ	*/
		(* pi_type).env2 = 0;						/* リザーブフラグ	*/
		break;
	case 3:											/* 実行				*/
		/*--------------------------------------------------------------*/
		/* 必要なパラメータをコピーしておく								*/
		/*--------------------------------------------------------------*/
		pi_data = (PI_DATA *)arg1;
		pi_imge = (PI_IMAGE *)arg2;
		pi_para = (PI_PARA *)arg3;
		ret_fr  = (FRAME *)arg4;
		if( (* pi_para).type != PI_EFFC_ALORSL )	//  形式の確認
			break;
		g_para  = (* pi_para).gpara;
		fr.lupx = WORD(g_para + 0);				// 描画座標の退避
		fr.lupy = WORD(g_para + 2);
		fr.rdwx = WORD(g_para + 4);
		fr.rdwy = WORD(g_para + 6);
		guiEgbPtr = pi_imge->egbWork;			//	EGBワーク
		/*--------------------------------------------------------------*/
		/* 実行部の呼び出し(パラメータ形式は自由)						*/
		/*--------------------------------------------------------------*/
		ret = APL_exec(&fr);
		if( ret < 0 ){
			return( -1 );
		}
		break;
	case 4:											/* 終了				*/
		break ;
	case 5:											/* データ			*/
		*((int *)arg1) = cnfg_max;					//  データ数
		*((int *)arg2) = (int)cnfg;					//  データアドレス
		break;
	}
	return ret;
}

/****************************************************************************/
/*	近似パレットを統合する。												*/
/****************************************************************************/

int APL_exec(FRAME *fr)
{
	int i,j,k;
	int bpp;
	int col,col0,col1,col_max;
	int x,y;
	int w,h;
	int	p;
	int flg[256][2];		// pix counter
	int pf[256],pa[256];
	int bo,ro,go;
	int bn,rn,gn;
	int bd,rd,gd;
	int n,m;
	int	s0,s1;
	int	rgb[3];
	char *palt;
	char *vram;
	char *buf;
	struct {
		unsigned int	p ;
		short	dseg;
		FRAME	fr;
	} getput ;
	
	bpp = pi_imge->pix;
	if( bpp != 4 &&
		bpp != 8 ) return -1;
	palt = pi_imge->clut;
	vram = pi_imge->image;
	if( vram == NULL ) return -1;
	
	col_max = ( bpp == 4 ? 16 : 256 );
	for(j=0;j<col_max;j++) {
		flg[j][0] = j;
		flg[j][1] = 0;
	}
	for(i=0;i<3;i++)
		rgb[i] = cnfg[i].val;
	
	x = pi_imge->size.x;
	y = pi_imge->size.y;
	w = (x+31)/32*32;
	h = y;
	k = ( bpp == 4 ? w/2 : w );
	buf = PI_MALLOC( k );
	if( buf == NULL )
		return -1;
	getput.dseg = pi_data->ds;
	getput.p = (int )buf;
	x = fr->rdwx-fr->lupx+1;
	y = fr->rdwy-fr->lupy+1;
	if( bpp == 4 ) {
		for(j=0;j<y;j++) {
			SetRect((Rect *)&getput.fr,
						fr->lupx,fr->lupy+j,fr->rdwx,fr->lupy+j);
			EGB_getBlock(guiEgbPtr,(char *)&getput);
			for(i=0;i<(x+1)/2;i++) {
				p = BYTE( buf + i );
				col = p&0x0f;
				flg[col][1]++;
				col = (p&0xf0)>>4;
				flg[col][1]++;
			}
		}
	} else {
		for(j=0;j<y;j++) {
			SetRect((Rect *)&getput.fr,
						fr->lupx,fr->lupy+j,fr->rdwx,fr->lupy+j);
			EGB_getBlock(guiEgbPtr,(char *)&getput);
			for(i=0;i<x;i++) {
				col = BYTE( buf + i );
				flg[col][1]++;
			}
		}
	}
	for(j=0;j<col_max-1;j++) {
		col = flg[j][1];
		for(i=j+1;i<col_max;i++) {
			if( col < flg[i][1] ) {
				s0 = flg[i][0];
				s1 = flg[i][1];
				flg[i][0] = flg[j][0];
				flg[i][1] = flg[j][1];
				flg[j][0] = s0;
				flg[j][1] = s1;
				col = flg[j][1];
			}
		}
	}

	for(i=0;i<col_max;i++) {
		pf[i] = -1;
	}
	for(i=0;i<col_max;i++) {
		col0 = flg[i][0];
		bo = palt[col0*8  +4+4]&0xFF;
		ro = palt[col0*8+1+4+4]&0xFF;
		go = palt[col0*8+2+4+4]&0xFF;
		n = 0;
		for(j=i+1;j<col_max;j++) {
			col1 = flg[j][0];
			if( pf[col1] < 0 ) {
				bn = palt[col1*8  +4+4]&0xFF;
				rn = palt[col1*8+1+4+4]&0xFF;
				gn = palt[col1*8+2+4+4]&0xFF;
				bd = bn-bo;
				if( bd < 0 ) bd *= (-1);
				rd = rn-ro;
				if( rd < 0 ) rd *= (-1);
				gd = gn-go;
				if( gd < 0 ) gd *= (-1);
				if( rd <= rgb[0] ) {
					if( gd <= rgb[1] ) {
						if( bd <= rgb[2] ) {
							pa[n] = col1;
							n++;
						}
					}
				}
			}
		}
		if( n > 0 ) {
			m = col0;
			for(j=0;j<n;j++) {
				pf[pa[j]] = m;
			}
		}
	}
	if( bpp == 4 ) {
		for(j=0;j<y;j++) {
			SetRect((Rect *)&getput.fr,
						fr->lupx,fr->lupy+j,fr->rdwx,fr->lupy+j);
			EGB_getBlock(guiEgbPtr,(char *)&getput);
			for(i=0;i<(x+1)/2;i++) {
				p = BYTE( buf + i );
				col = p&0x0f;
				if( pf[col] > -1 )
					BYTE(buf+i)= (p&0xf0) + (pf[col&0x0f]&0x0f);
				p = BYTE( buf + i );
				col = (p&0xf0)>>4;
				if( pf[col] > -1 )
					BYTE(buf+i)= (pf[col&0x0f]<<4)+(p&0x0f);
			}
			EGB_putBlock(guiEgbPtr,1,(char *)&getput);
		}
	} else {
		for(j=0;j<y;j++) {
			SetRect((Rect *)&getput.fr,
						fr->lupx,fr->lupy+j,fr->rdwx,fr->lupy+j);
			EGB_getBlock(guiEgbPtr,(char *)&getput);
			for(i=0;i<x;i++) {
				col = BYTE( buf + i );
				if( pf[col] > -1 )
					BYTE( buf + i ) = pf[col];
			}
			EGB_putBlock(guiEgbPtr,1,(char *)&getput);
		}
	}
	
	if( buf != NULL )
		PI_FREE( buf );
	return 0;
}

void main(){}
