/****************************************************************************/
/*																			*/
/*		｢乙女座｣用プラグインツールサンプル									*/
/*																			*/
/*		通信で､16と256(?)のほぼ標準となっているMAG画像ﾌｫｰﾏｯﾄ(拡張子MAG)の	*/
/*		ファイルを読み込むモジュールです。16色､256色に対応しています。		*/
/*																			*/
/*		※まぁ、大したソースではないので、流用したければ御事由にお使い		*/
/*		  下さい｡															*/
/****************************************************************************/

/*--------------------------------------------------------------------------*/
/*		乙女座用画像ローダーの作成方法										*/
/*																			*/
/*	○大まかな流れ															*/
/*	  乙女座本体からファイル名を貰い､展開した画像のバッファのポインタ色数	*/
/*	  (16色 = 4/256色 = 8)､XYサイズを返します。								*/
/*																			*/
/*	○注意事項																*/
/*	  tpspin.hをincludeして下さい｡											*/
/*	  マロックは(char *)pi_data->func1を使用して下さい｡						*/
/*	  エラーはヘッダーにあるPI_ERROR_XXXXXをセットして返して下さい｡			*/
/*	  展開等に使うローカルﾊﾞｯﾌｧのﾎﾟｲﾝﾀｰはﾌﾟﾗｸﾞｲﾝﾂｰﾙ内で宣言して下さい｡		*/
/*	  また、使い終わったら必ず開放して下さい｡								*/
/*	  ただし、展開したイメージ本体は開放しないで下さい。開放すると乙女座	*/
/*	　では参照できません。													*/
/*																			*/
/*	○本体に返すパラメーター												*/
/*	  pi_imge->size.x		：画像の横ｻｲｽﾞ(POINT)							*/
/*	  pi_imge->size.y		：画像の縦ｻｲｽﾞ(POINT)							*/
/*	  pi_imge->pix			：画像の色ﾓｰﾄﾞ(int)								*/
/*	  pi_imge->scrn_buff	：展開したﾊﾞｯﾌｧのﾎﾟｲﾝﾀ(char*)					*/
/*	  pi_imge->clut			：作成したﾊﾟﾚｯﾄのﾎﾟｲﾝﾀ(char*)					*/
/*																			*/
/*--------------------------------------------------------------------------*/
#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();
/****************************************************************************/

/*	longname[]がプラグインメニューに表示される名称になります			*/
const char longname[] = "MAG形式ﾛｰﾀﾞｰ for OTOMEZA";		//	ﾌﾟﾗｸﾞｲﾝﾂｰﾙ名
/*	どのアプリ用のプラグインかの判定です。乙女座はOT					*/
const char shortname[] = "OT";							//	乙女座認識文字
/*	画像形式を自動認識する為に設定します。これがないと､どの拡張子のﾌｧｲﾙか	*/
/*	乙女座の方で認識できないため､実行できなくなります。						*/
const char extend[] = "MAG";							//	画像拡張子
PI_TYPE		*pi_type;									//	ﾓｼﾞｭｰﾙ認識
PI_DATA		*pi_data;									//	設定値
PI_IMAGE	*pi_imge;									//	仮想画面
PI_PARA		*pi_para;									//	描画座標系


/*<Func>================================================================
*	int			pinHead(service, arg1, arg2, arg3, arg4)
*	int			service;
*	void	   *arg1;
*	void	   *arg2;
*	void	   *arg3;
*	void	   *arg4;
*	【概  要】	プラグインモジュール
*	【機  能】	本体側からの各種リクエストに答える
*	【入  力】	service	: サービス番号
*				arg1	: パラメタ１
*				arg2	: パラメタ２
*				arg3	: パラメタ３
*				arg4	: パラメタ４
*	【出  力】			:
*	【関数値】	== 0	: 正常終了
*				== -1	: 異常終了
*	【注  意】	ローダーを作成する場合この関数は変更の必要はありません
*	【参  照】			:
*</Func>================================================================*/
int pinHead(int service, void *arg1, void *arg2, void *arg3, void *arg4)
{
	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_LOAD;					/* Type				*/
		(* pi_type).env1 = 0;						/* 環境設定フラグ	*/
		(* pi_type).env2 = (int )&extend;			/* リザーブフラグ	*/
		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_LOAD)	/*	タイプの確認			*/
			break;
		/*--------------------------------------------------------------*/
		/* 実行部の呼び出し(パラメタ形式は自由)							*/
		/*--------------------------------------------------------------*/
		ret = APL_exec();
		if( ret < 0 ){
			return( -1 );
		}
		break;
	case 4:											/* 終了				*/
		break ;
	case 5:											/* データ			*/
		break;
	}
	return ret;
}

/****************************************************************************/
/*		MAG形式ファイルの展開ルーチン										*/
/****************************************************************************/

int APL_exec()
{
	int i,j,k,m;
	int x,y;
	int w,h;
	char *buf;
//	int h_off,m_typ,m_mod;
	int s_mod;
	int sx,sy,ex,ey;
	int l;
	int a_off,b_off,p_off;
	int a_siz;	//,b_siz,p_siz;
	char *pal;
	char *palt;
	char *flg_a,*flg_b,*pix;
	char *image;
	char *vram;
	int vc,pc,cpx,cpy;
	int vda,size;
	int bpp,cn,col;
	int c_mod;
	FILE *fp_g;
	unsigned char p;
	char Bit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
	unsigned char table[16][2] =	
						{{0,0},{1,0},{2,0},{4,0},
						 {0,1},{1,1},
						 {0,2},{1,2},{2,2},
						 {0,4},{1,4},{2,4},
						 {0,8},{1,8},{2,8},
						 {0,16}};
	int p0,p1;
	
	if( (fp_g = fopen( FNAME , "rb" )) == NULL ) return -1;

	fseek( fp_g, 0, SEEK_END );
	l = ftell( fp_g );
	fseek( fp_g, 0, SEEK_SET );
	if( l < 0 ) return -1;
	
	buf = (char *)PI_MALLOC( l );
	if( buf == NULL ) {
		fclose( fp_g );
		return -1;
	}
	fread( buf, 1, l, fp_g );
	fclose( fp_g );

	/*	タイプのーチェック	*/
	if( strncmp(&buf[0],"MAKI02  ",8) != 0 ) {
		PI_FREE( buf );
		return -1;
	}

	/*	ヘッダ−位置のサ−チ	*/
	i =0;
	for(;;) {
		if( buf[i] == 0x1a ) break;
		i++;
	}
	i++;
//	h_off = BYTE( buf + i     );
//	m_typ = BYTE( buf + i + 1 );
//	m_mod = BYTE( buf + i + 2 );
	s_mod = BYTE( buf + i + 3 );
	sx    = WORD( buf + i + 4 );
	sy    = WORD( buf + i + 6 );
	ex    = WORD( buf + i + 8 );
	ey    = WORD( buf + i +10 );
	a_off =DWORD( buf + i +12 );
	b_off =DWORD( buf + i +16 );
//	b_siz =DWORD( buf + i +20 );
	p_off =DWORD( buf + i +24 );
//	p_siz =DWORD( buf + i +28 );
	a_siz = b_off-a_off;
	bpp = 4;				/*	デフォルトは16色	*/
	cn = 1;
	col = 16;
	c_mod = s_mod&0x80;
	if( c_mod != 0 ) {
		bpp = 8;
		cn = 2;
		col = 256;
	}
	x = (ex-sx+1);
	if( x & 7 ) x += 8 - ( x & 7 );
	if( sx % 8 ) x += 8;
	y = (ey-sy+1);
	w = (x+31)/32*32;
	h = y;
	if( s_mod&0x01 != 0 ) h = y*2;
	
	/*	パレットデ−タのセット	*/
	pi_imge->clut = (char *)PI_MALLOC( col*8+4 );
	pal = pi_imge->clut;
	if( pal != NULL ) {
		palt = (char *)&buf[i+32];
		for(j=0;j<col;j++) {
			BYTE(pal + j*8     + 4 + 4 ) = BYTE( palt + j*3+2 );
			BYTE(pal + j*8 + 1 + 4 + 4 ) = BYTE( palt + j*3+1 );
			BYTE(pal + j*8 + 2 + 4 + 4 ) = BYTE( palt + j*3   );
		}
		DWORD( pal ) = col;		//	パレット数セット
	}
	flg_a = (char *)&buf[i+a_off];
	flg_b = (char *)&buf[i+b_off];
	pix   = (char *)&buf[i+p_off];

	/*	フラグデ−タの展開	 */
	image = (char *)PI_MALLOC( x/8*cn * y );
	if( image == NULL ) {
		PI_FREE( buf );
		return -1;
	}
	m = 0;
	for(j=0;j<a_siz;j++) {
		for(k=0;k<8;k++) {
			if( (BYTE(flg_a+j)&Bit[k]) == 0 ) {
				BYTE(image+j*8+k) = 0x00;
			} else {
				BYTE(image+j*8+k) = BYTE(flg_b+m);
				m++;
			}
		}
	}
	/*	XORを取る	*/
	for(j=1;j<y;j++) {
		for(k=0;k<(x/8)*cn;k++) {
			BYTE( image+j*(x/8)*cn+k ) ^= BYTE( image+(j-1)*(x/8)*cn+k);
		}
	}
	/*	画像デ−タの展開	*/
	if( bpp == 4 )	size = w/2*h;
	else			size = w*h;
	pi_imge->image = (char *)PI_MALLOC( size );
	vram = pi_imge->image;
	if( vram == NULL ) {
		PI_FREE( image );
		PI_FREE( buf );
		return -1;
	}
	vc = pc = 0;
	for(j=0;j<y;j++) {
		for(k=0;k<(x/4)*cn;k++) {
			if( k%2 == 0 )
				p = (BYTE(image+j*(x/8)*cn+k/2)&0xF0)>>4;
			else
				p =  BYTE(image+j*(x/8)*cn+k/2)&0x0F;
			vda = j*(w/2)*cn+k*2;
			if( p == 0 ) {
				memcpy(&vram[vda],&pix[pc],2);
				pc += 2;
			} else {
				cpx = k-table[p][0];
				if( cpx < 0 ) cpx = 0;
				cpy = j-table[p][1];
				if( cpy < 0 ) cpy = 0;
				vc = cpx*2 + cpy*(w/2)*cn;
				memcpy(&vram[vda],&vram[vc],2);
			}
		}
	}
	PI_FREE( image );
	PI_FREE( buf );

	pi_imge->pix = bpp;				//	色数
	pi_imge->size.x = x;			//	画像横幅
	pi_imge->size.y = h;			//	画像高さ
	
	//	画像が16色の場合､TOWNSに合った画像形式ではないので、
	//	ここで、上位4bitと下位4bitを入れ換える｡
	if( bpp == 4 ) {
		for(i=0;i<w/2*y;i++) {
			p0 = vram[i]&0x0F;
			p1 =(vram[i]&0xF0)>> 4;
			vram[i] = (p0<<4) + p1;
		}
	}
	//	MSX等で作成したMAG形式のﾌｧｲﾙは約2分の1の高さなので、
	//	2倍にのばしてやる。
	if( h != y ) {
		k = ( bpp = 4 ? w/2 : w );
		for(j=0;j<h;j++) {
			i = h-(1+j);
			p0 = k*(i/2);
			p1 = k*i;
			memcpy(&vram[p1],&vram[p0],k);
		}
	}
	//	vramは展開したイメージなので、開放しない事!!
	//	vramのイメージは乙女座本体で開放します。

	return 0;
}

void main(){}
