//--------------------------------------------------------------------------------------
//
// X-BASIC'
//	外部関数：iOS用 Sprite & BG
//
//--------------------------------------------------------------------------------------
// 外部関数の構造を持っている

#import	"RunViewController.h"
#import "Console+animation.h"
#import "sConsole.h"
#import "libs.h"
#include "XBiOSsp.h"
#include "fdef.h"

//---------------------------------------------------------------------------------------------
// 共通ワーク

static RunViewController *runView;	// <- これはインターフェースから
static sConsole  *sconsole;			// これは内部で設定

//---------------------------------------------------------------------------------------------

static RET_FUNC _F_version(SWord numFAC,FAC fac[])
// この外部関数のバージョンを返す
{
	printFunc();
	fac[0].dl.cp[LL]=VERSION_XBIOSFUNCSP;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 画面表示
//---------------------------------------------------------------------------------------------

static RET_FUNC _F_sp_init(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	[sconsole sp_init];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_disp(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int flag=basic2cYESNO(fac[0].dl.l[LL]);
	[sconsole setFspriteBGDisp:flag];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_halt(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int flag=basic2cYESNO(fac[0].dl.l[LL]);
	[sconsole setFhalt:flag];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_clr(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	BOOL fomitSp1=YES;
	int i=0;
	int sp1=0; // 省略時は0
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		sp1=(int)fac[i].dl.l[LL];
		fomitSp1=NO;
	}
	i++;
	int sp2=sp1; // sp1の設定があるときはsp2=sp1
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		sp2=(int)fac[i].dl.l[LL];
	} else {
		// sp2省略時
		if (fomitSp1) sp2=MAX_SPRITE_PATTERNS-1; // sp1も省略時はMAX_SPRITE_PATTERNS-1
	}
	//
	[sconsole sp_clr:sp1 sp2:sp2];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_on(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	BOOL fomitPl1=YES; // pl1は省略されているの印
	int pl1=0; // 省略時は0から
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pl1=(int)fac[i].dl.l[LL];
		fomitPl1=NO; // pl1は省略されていない
	}
	i++;
	int pl2=pl1; // 省略時はpl1のみ
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pl2=(int)fac[i].dl.l[LL];
	} else {
		if (fomitPl1) {
			// pl1/pl2ともに省略時
			pl2=MAX_SPRITE_PLANE-1;
		}
	}
	i++;
	int prw=SPRITE_PRW_SPBG0BG1; // デフォルトの優先順位はSP>BG0>BG1(X68でもそう処理されている;SP_ON.s)
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		prw=(int)fac[i].dl.l[LL];
	}
	//
	[sconsole sp_priority:prw pl1:pl1 pl2:pl2];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_off(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	BOOL fomitPl1=YES; // pl1は省略されているの印
	int pl1=0; // 省略時は0から
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pl1=(int)fac[i].dl.l[LL];
		fomitPl1=NO; // pl1は省略されていない
	}
	i++;
	int pl2=pl1; // 省略時はpl1のみ
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pl2=(int)fac[i].dl.l[LL];
	} else {
		if (fomitPl1) {
			// pl1/pl2ともに省略時
			pl2=MAX_SPRITE_PLANE-1;
		}
	}
	i++;
	//
	[sconsole sp_priority:SPRITE_PRW_HIDE pl1:pl1 pl2:pl2];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_def(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	int sp=(int)fac[i++].dl.l[LL];
	
	SWord size1;
	uwYouso youso;
	ULong *lp=(ULong *)getDim1FromFAC(fac,i,&size1,&youso);	// ここはARM対応してない；関数に渡してるだけだから
	if (lp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	printf("size1=%d/youso=%d\n",size1,youso);
	if (youso<SPRITE_ELEMENTS) {
		setExternalFuncErrmes("要素数が足りません","Elements are not enough.");
		return (RET_FUNC_ERR);
	} // 多い時は、超える分を無視するだけ
	
	char type;
	switch (size1) {
		case SZ_CHAR: // X68型
			type=SPRITE_X68;
			break;
		case SZ_INT:  // iOS型
		default: 	  // 念のため
			type=SPRITE_IOS;
			break;
	}
	[sconsole sp_def:sp ptn:lp type:type];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_pat(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int sp=(int)fac[i++].dl.l[LL];
	
	SWord size1;
	uwYouso youso;
	ULong *lp=(ULong *)getDim1FromFAC(fac,i,&size1,&youso);	// ここはARM対応してない；関数に渡してるだけだから
	if (lp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	printf("size1=%d/youso=%d\n",size1,youso);
	if (youso<SPRITE_ELEMENTS) {
		setExternalFuncErrmes("要素数が足りません","Elements are not enough.");
		return (RET_FUNC_ERR);
	} // 多い時は、超える分を無視するだけ
	fac[0].dl.l[LL]=[sconsole sp_pat:sp ptn:lp size1:size1];
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

RET_FUNC _F_sp_color(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	int p=(int)fac[i++].dl.l[LL];
	ULong rgba=fac[i++].dl.l[LL]; // 合成RGB値
	int pb=1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pb=(int)fac[i].dl.l[LL];
	}
	//
	fac[0].dl.l[LL]=[sconsole sp_color:p col:rgba paletBlock:pb];
	//
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_move(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	int pl=(int)fac[i++].dl.l[LL];
	int x=0; // =0は警告回避穂のため
	BOOL fomitX=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		x=(int)fac[i].dl.l[LL];
	} else {
		fomitX=YES;
	}
	i++;
	int y=0; // =0は警告回避穂のため
	BOOL fomitY=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		y=(int)fac[i].dl.l[LL];
	} else {
		fomitY=YES;
	}
	i++;
	int sp=-1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		sp=(int)fac[i].dl.l[LL];
	}
	[sconsole sp_setting:pl x:x y:y sp:sp paletBlock:DEFAULT_SPRITE_PALET_BLOCK flip:SPRITE_FLIP_NONE prw:SPRITE_PRW_SPBG0BG1 fomitX:fomitX fomitY:fomitY];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

RET_FUNC _F_sp_setting(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int pl=(int)fac[i++].dl.l[LL];
	//
	int x=0; // =0は警告回避穂のため
	BOOL fomitX=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		x=(int)fac[i].dl.l[LL];
	} else {
		fomitX=YES;
	}
	i++;
	int y=0; // =0は警告回避穂のため
	BOOL fomitY=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		y=(int)fac[i].dl.l[LL];
	} else {
		fomitY=YES;
	}
	i++;
	int sp=-1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		sp=(int)fac[i].dl.l[LL];
	}
	i++;
	int pb=-1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pb=(int)fac[i].dl.l[LL];
	}
	i++;
	int hv=-1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		hv=(int)fac[i].dl.l[LL];
	}
	i++;
	int prw=-1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		prw=(int)fac[i].dl.l[LL];
	}
//	nslog(@"pl=%d,x=%d,y=%d,sp=%d,pb=%d,flip=%d,prw=%d,fomitX=%d,fomitY=%d",pl,x,y,sp,pb,hv,prw,fomitX,fomitY);
	[sconsole sp_setting:pl x:x y:y sp:sp paletBlock:pb flip:hv prw:prw fomitX:fomitX fomitY:fomitY];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_stat(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	int pl		=(int)fac[i++].dl.l[LL];
	int dataType=(int)fac[i++].dl.l[LL];
	//
	fac[0].dl.l[LL]=[sconsole sp_stat:pl dataType:dataType];
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sp_disableBG0SPBG1(SWord numFAC,FAC fac[])
{
	printFunc();
	int flag=basic2cYESNO(fac[0].dl.l[LL]);
	//
	if ([sconsole setFDisableBG0SPBG1:flag]) {
		setExternalFuncErrmes("ワークエリアが確保出来ません","Can't alloc workarea.");
		return (RET_FUNC_ERR);
	}
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------

static RET_FUNC _F_sp_image(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	UByte *bp=fac[i++].dl.bp[LL];
	if (*bp==0) {
		nslog(@"ファイル名がNULLである");
		fac[0].dl.l[LL]=-PIC_FILENOTFOUND; // ファイルが見つかるはずがない
	} else {
		NSString *path=@(bstrWithUTF8(bp)); // UTF8化
		int ofstx=0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			ofstx=(int)fac[i].dl.l[LL];
		}
		i++;
		//
		int ofsty=0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			ofsty=(int)fac[i].dl.l[LL];
		}
		i++;
		//
		int pwx0=0,*pwx=&pwx0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			pwx=fac[i].dl.ip[LL]; // 変数アドレス
		}
		i++;
		//
		int pwy0=0,*pwy=&pwy0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			pwy=fac[i].dl.ip[LL]; // 変数アドレス
		}
		i++;
		//
		int tsp=0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			tsp=(int)fac[i].dl.l[LL];
		}
		i++;
		//
		int tpl=-1; // プレーン登録はしない印
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			tpl=(int)fac[i].dl.l[LL];
		}
		i++;
		//
		BOOL fomitSX=YES;
		int sx=0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			sx=(int)fac[i].dl.l[LL];
			fomitSX=NO;
		}
		i++;
		//
		BOOL fomitSY=YES;
		int sy=0;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			sy=(int)fac[i].dl.l[LL];
			fomitSY=NO;
		}
		i++;
		//
		int prw=SPRITE_PRW_SPBG0BG1; // デフォルトの優先順位はSP>BG0>BG1
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			prw=(int)fac[i].dl.l[LL];
		}
		i++;
		//
		BOOL fblack=YES;
		if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
			fblack=basic2cYESNO(fac[i].dl.l[LL]);
		}
		i++;
		//
		fac[0].dl.l[LL]=[sconsole sp_image:path ofstx:ofstx ofsty:ofsty pwx:pwx pwy:pwy tsp:(SWord)tsp tpl:(SWord)tpl sx:sx sy:sy fomitSX:fomitSX fomitSY:fomitSY prw:(SWord)prw fblack:fblack];
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


//---------------------------------------------------------------------------------------------

RET_FUNC _F_bg_fill(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	int pg=(int)fac[i++].dl.l[LL];
	int sp=(int)fac[i++].dl.l[LL];

	int pb=DEFAULT_BG_PALET_BLOCK;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pb=(int)fac[i].dl.l[LL];
	}
	i++;
	int hv=SPRITE_FLIP_NONE;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		hv=(int)fac[i].dl.l[LL];
	}
	[sconsole bg_fill:pg sp:sp paletBlock:pb flip:hv];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

RET_FUNC _F_bg_put(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int pg=(int)fac[i++].dl.l[LL];
	int x =(int)fac[i++].dl.l[LL];
	int y =(int)fac[i++].dl.l[LL];
	int sp=(int)fac[i++].dl.l[LL];
	int pb=DEFAULT_BG_PALET_BLOCK;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pb=(int)fac[i].dl.l[LL];
	}
	i++;
	int hv=SPRITE_FLIP_NONE;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		hv=(int)fac[i].dl.l[LL];
	}
	[sconsole bg_put:pg x:x y:y sp:sp paletBlock:pb flip:hv];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

RET_FUNC _F_bg_get(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int pg=(int)fac[i++].dl.l[LL];
	int x =(int)fac[i++].dl.l[LL];
	int y =(int)fac[i++].dl.l[LL];
	//
	int *pbp=NULL;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pbp=fac[i].dl.ip[LL];
		nslog(@"pbp=%p",pbp);
	}
	i++;
	int *fflip=NULL;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		fflip=fac[i].dl.ip[LL];
		nslog(@"fflip=%p",fflip);
	}
	
	PatternRegs *reg=[sconsole bg_get:pg x:x y:y];
	if (pbp  !=NULL) {
		*pbp  =reg->paletBlock;
		nslog(@"pb=%d",*pbp);
	}
	if (fflip!=NULL) {
		*fflip=reg->fflip;
		nslog(@"flip=%d",*fflip);
	}
	//
	fac[0].dl.l[LL]=reg->ptrn; // パターン番号を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_bg_set(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int bno  =(int)fac[i++].dl.l[LL];
	int pg   =(int)fac[i++].dl.l[LL];
	int fdisp=basic2cYESNO(fac[i].dl.l[LL]);
	//
	if ([sconsole bg_set:bno page:pg fdisp:fdisp]) {
		setExternalFuncErrmes("ワークエリアが確保出来ません","Can't alloc workarea.");
		return (RET_FUNC_ERR);
	}
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_bg_scroll(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int bno=(int)fac[i++].dl.l[LL];
	//
	int x=0; // =0は警告回避穂のため
	BOOL fomitX=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		x=(int)fac[i].dl.l[LL];
	} else {
		fomitX=YES;
	}
	i++;
	
	int y=0; // =0は警告回避穂のため
	BOOL fomitY=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		y=(int)fac[i].dl.l[LL];
	} else {
		fomitY=YES;
	}
	//
	[sconsole bg_scroll:bno x:x y:y fomitX:fomitX fomitY:fomitY];
	//
	fac[0].dl.l[LL]=0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_bg_stat(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int pl		=(int)fac[i++].dl.l[LL];
	int dataType=(int)fac[i++].dl.l[LL];
	//
	int ret=[sconsole bg_stat:pl dataType:dataType];
	if (dataType==3) {
		// 表示設定はBASICのYES/NOに変換する必要がある
		nslog(@"表示設定=%d",ret);
		ret=c2basicYESNO(ret);
		nslog(@"変換後表示設定=%d",ret);
	}
	//
	fac[0].dl.l[LL]=ret;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// v2.1
//---------------------------------------------------------------------------------------------

static RET_FUNC _F_spAnimationParameter(SWord numFAC,FAC fac[])
// アニメーションパラメーター設定(簡易)
{
	printFunc();
	//
	int i=0;
	CGFloat tx=0;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		tx=fac[i].dl.d;
	}
	i++;
	CGFloat ty=0;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		ty=fac[i].dl.d;
	}
	i++;
	CGFloat scaleX=1.0;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		scaleX	=fac[i].dl.d;
	}
	i++;
	CGFloat scaleY=1.0;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		scaleY	=fac[i].dl.d;
	}
	i++;
	CGFloat angle=0;
	BOOL fdegree=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		angle	=fac[i].dl.d;
		fdegree	=YES;
	}
	i++;
	int axis=(fdegree? AXIS_X:AXIS_NONE);
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		axis=(int)fac[i].dl.l[LL];
	}
	i++;
	// 水平移動		tx,ty,1.0,1.0,0,AXIS_NONE
	// 拡大縮小		0,0,scaleX,scaleY,0,AXIS_NONE
	// 回転			0,0,1.0,1.0,angle,axis
	[sconsole setAnimeParameter2:tx ty:ty scaleX:scaleX scaleY:scaleY angle:angle axis:axis];
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_spAnimationMatrix(SWord numFAC,FAC fac[])
// アニメーションパラメーター設定(詳細)
{
	printFunc();
	// こう設定される。鏡像変換は自動的に行われるので考えなくていい
	// m11,m12,m13,0
	// m21,m22,m23,0
	// m31,m32,m33,0
	//  tx, ty,  0,1
	CATransform3D matrix=CATransform3DIdentity; // まずはデフォルト設定
	int i=0;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m11=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m12=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m13=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m21=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m22=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m23=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m31=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m32=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m33=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m41=fac[i].dl.d;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		matrix.m42=fac[i].dl.d;
	}
	i++;
	[sconsole setAnimeParameter3:matrix];
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// アニメーション実行
static RET_FUNC _F_spAnimation(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	int anime=(int)fac[i++].dl.l[LL];	// アニメーションモード
	
	CFTimeInterval 	duration=0; // 省略はANIMATION_STOP時のみ
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		duration=fac[i].dl.d;
	}
	if (duration<0) duration=-duration;
	if (duration==0) anime=ANIMATION_STOP;
	i++;
	float repeatCount=1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		repeatCount=(float)fac[i].dl.d;
	}
	if (repeatCount<1) repeatCount=1;
	i++;
	BOOL autoreverses=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		autoreverses=basic2cYESNO(fac[i].dl.l[LL]);
	}
	i++;
	int animationCurve=UIViewAnimationCurveEaseInOut;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		animationCurve=(int)fac[i].dl.l[LL];
	}
	if (animationCurve<UIViewAnimationCurveEaseInOut) animationCurve=UIViewAnimationCurveEaseInOut;
	if (animationCurve>UIViewAnimationCurveLinear) 	  animationCurve=UIViewAnimationCurveLinear;
	//
	[sconsole setAnimeParameter1:duration repeatCount:repeatCount autoreverses:autoreverses animationCurve:animationCurve];
	sconsole.fanime=anime; // KVO発生
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------

static RET_FUNC _F_spTransform(SWord numFAC,FAC fac[])
// 変形設定
{
	printFunc();
	//
	int i=0;
	CGFloat tx=0;
	BOOL ftx=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		tx=fac[i].dl.d;
		ftx=YES;
	}
	i++;
	CGFloat ty=0;
	BOOL fty=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		ty=fac[i].dl.d;
		fty=YES;
	}
	i++;
	CGFloat scaleX=1.0;
	BOOL fscaleX=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		scaleX	=fac[i].dl.d;
		fscaleX	=YES;
	}
	i++;
	CGFloat scaleY=1.0;
	BOOL fscaleY=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		scaleY	=fac[i].dl.d;
		fscaleY	=YES;
	}
	i++;
	// 現在は鏡像変換と回転を同時に設定することが解決できてないので封印
	BOOL fdegree=NO;
	CGFloat angle=0.0;
#if 0
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		angle	=fac[i].dl.d;
		fdegree	=YES;
	}
	i++;
#endif
	
	if (!ftx && !fty && !fscaleX && !fscaleY && !fdegree) {
		// 全パラメーター省略時はキャンセル
		[sconsole transformCancel];
	} else {
		// 回転はxy平面のみ
		[sconsole transform:tx ty:ty scaleX:scaleX scaleY:scaleY angle:angle];
	}
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------

void _F_sBackgroundAlphaSub(double alpha)
{
	[sconsole alpha:alpha];
}

static RET_FUNC _F_sBackgroundAlpha(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	_F_sBackgroundAlphaSub(fac[0].dl.d);
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sBackgroundColor(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int r,g,b,alpha;
	getRGBColorFromFac(fac,0,&r,&g,&b,&alpha); // v2.2
	[sconsole backgroundColor:r g:g b:b alpha:alpha];
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sborder(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	int i=0;
	CGFloat width=fac[i++].dl.d;
	if (width>0) {
		int r,g,b,alpha;
		getRGBColorFromFac(fac,i,&r,&g,&b,&alpha); // v2.2
		[sconsole border:width r:r g:g b:b alpha:alpha];
	} // width<=0の時は何もしない
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// インフォメーションテーブル (5.2.1章)
//---------------------------------------------------------------------------------------------

// 関数名テーブル(トークンテーブル)
static const char *iOSSPTokens[]={
	"sp_init",
	"sp_disp",
	"sp_halt",
	"sp_clr",
	"sp_on",
	"sp_off",
	"sp_def",
	"sp_pat",
	"sp_color",
	"sp_move",
	"sp_setting",
	"sp_stat",
	"sp_disableBG0SPBG1",
	//
	"sp_image",
	//
	"bg_fill",
	"bg_put",
	"bg_get",
	"bg_set",
	"bg_scroll",
	"bg_stat",
	// v2.1
	"spAnimationParameter",
	"spAnimationMatrix",
	"spAnimation",
	"spTransform",
	// v2.2
	"sBackgroundAlpha",
	"sBackgroundColor",
	"sborder",
	"sBorder",
	//
	// バージョン
	"versionXBiOSSprite$",
	// end of table
	NULL,
};

// 実行アドレステーブル
static FUNC_EXEC iOSSPFuncExec[]={
	// Cの標準関数名と重複させないよう_F_を付ける
	{_F_sp_init		},
	{_F_sp_disp		},
	{_F_sp_halt		},
	{_F_sp_clr		},
	{_F_sp_on		},
	{_F_sp_off		},
	{_F_sp_def	},
	{_F_sp_pat	},
	{_F_sp_color	},
	{_F_sp_move		},
	{_F_sp_setting	},
	{_F_sp_stat		},
	{_F_sp_disableBG0SPBG1},
	//
	{_F_sp_image},
	//
	{_F_bg_fill		},
	{_F_bg_put		},
	{_F_bg_get		},
	{_F_bg_set		},
	{_F_bg_scroll	},
	{_F_bg_stat		},
	// v2.1
	{_F_spAnimationParameter},
	{_F_spAnimationMatrix},
	{_F_spAnimation},
	{_F_spTransform},
	// v2.2
	{_F_sBackgroundAlpha},
	{_F_sBackgroundColor},
	{_F_sborder	},
	{_F_sborder	},
	//
	// バージョン
	{_F_version},
	// end of table
	{NULL},
};

//------------------------------
// パラメーターテーブル
// (1)種類別定義
// 1関数の引数は最大MAX_PARAM個

static const uwPARAMTYPE p_sp_init[]={
	INT_RET,
};

static const uwPARAMTYPE p_sp_clr[]={
	INT_OMT,
	INT_OMT,
	INT_RET,
};
#define p_sp_off	p_sp_clr

static const uwPARAMTYPE p_sp_on[]={
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_RET,
};

static const uwPARAMTYPE p_sp_def[]={
	INT_VAL,
	ARRAY1_IC,
	INT_OMT,	// X68との互換性のために存在するが、未使用
	INT_RET,
};

static const uwPARAMTYPE p_sp_pat[]={
	INT_VAL,
	ARRAY1_IC,
	INT_RET,
};

static const uwPARAMTYPE p_sp_color[]={
	INT_VAL,
	INT_VAL,
	INT_OMT,
	INT_RET,
};

static const uwPARAMTYPE p_sp_move[]={
	INT_VAL,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_RET,
};

static const uwPARAMTYPE p_sp_setting[]={
	INT_VAL,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_RET,
};

static const uwPARAMTYPE p_sp_stat[]={
	INT_VAL,
	INT_VAL,
	INT_RET,
};

static const uwPARAMTYPE p_sp_disableBG0SPBG1[]={
	INT_VAL,
	INT_RET,
};
#define p_sp_halt	p_sp_disableBG0SPBG1
#define p_sp_disp	p_sp_disableBG0SPBG1

static const uwPARAMTYPE p_sp_image[]={
	STR_VAL,	// fname
	INT_OMT,	// ofstx
	INT_OMT,	// ofsty
	INT_VP|PARAM_OMIT,	// pwx
	INT_VP|PARAM_OMIT,	// pwy
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	INT_RET,
};

//-----

static const uwPARAMTYPE p_bg_fill[]={
	INT_VAL,
	INT_VAL,
	INT_OMT,
	INT_OMT,
	INT_RET,
};

static const uwPARAMTYPE p_bg_put[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_OMT,
	INT_OMT,
	INT_RET,
};

static const uwPARAMTYPE p_bg_get[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VP|PARAM_OMIT,	// v2.5
	INT_VP|PARAM_OMIT,	// v2.5
	INT_RET,
};

static const uwPARAMTYPE p_bg_set[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_RET,
};

static const uwPARAMTYPE p_bg_scroll[]={
	INT_VAL,
	INT_OMT,
	INT_OMT,
	VOID_RET,
};

static const uwPARAMTYPE p_bg_stat[]={
	INT_VAL,
	INT_VAL,
	INT_RET,
};

//-------

static const uwPARAMTYPE p_spAnimationParameter[]={
	FLOAT_OMT,
	FLOAT_OMT,
	FLOAT_OMT,
	FLOAT_OMT,
	FLOAT_OMT,
	INT_OMT,
	VOID_RET,
};

static const uwPARAMTYPE p_spAnimationMatrix[]={
	FLOAT_OMT,	FLOAT_OMT,	FLOAT_OMT,
	FLOAT_OMT,	FLOAT_OMT,	FLOAT_OMT,
	FLOAT_OMT,	FLOAT_OMT,	FLOAT_OMT,
	FLOAT_OMT,	FLOAT_OMT,
	VOID_RET,
};

static const uwPARAMTYPE p_spAnimation[]={
	INT_VAL,
	FLOAT_OMT,
	FLOAT_OMT,
	INT_OMT,
	INT_OMT,
	VOID_RET,
};

static const uwPARAMTYPE p_spTransform[]={
	FLOAT_OMT,
	FLOAT_OMT,
	FLOAT_OMT,
	FLOAT_OMT,
	FLOAT_OMT,
	VOID_RET,
};

static const uwPARAMTYPE p_sBackgroundAlpha[]={
	FLOAT_VAL,
	VOID_RET,
};

static const uwPARAMTYPE p_sBackgroundColor[]={ // v2.2
	INT_VAL,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	VOID_RET,
};

static const uwPARAMTYPE p_sborder[]={ // v2.2
	FLOAT_VAL,
	INT_VAL,
	INT_OMT,
	INT_OMT,
	INT_OMT,
	VOID_RET,
};

//-------

static const uwPARAMTYPE p_version[]={
	STR_RET,
};

//------------------------------
// パラメーターテーブル
// (2)関数別定義

static
const
uwPARAMTYPE *iOSSPParams[]={
	p_sp_init,
	p_sp_disp,
	p_sp_halt,
	p_sp_clr,
	p_sp_on,
	p_sp_off,
	p_sp_def,
	p_sp_pat,
	p_sp_color,
	p_sp_move,
	p_sp_setting,
	p_sp_stat,
	p_sp_disableBG0SPBG1,
	//
	p_sp_image,
	//
	p_bg_fill,
	p_bg_put,
	p_bg_get,
	p_bg_set,
	p_bg_scroll,
	p_bg_stat,
	// v2.1
	p_spAnimationParameter,
	p_spAnimationMatrix,
	p_spAnimation,
	p_spTransform,
	// v2.2
	p_sBackgroundAlpha,
	p_sBackgroundColor,
	p_sborder,
	p_sborder,
	//
	// バージョン
	p_version	,
	// end of table
	NULL,
};

//-------------
// operationStatus.fsprite=NOのときは、以下は呼び出されない

static void _Frun(void)
// この中の関数の初期化処理
{
	printFunc();
	runView=xb_getRunView();
	[runView vpage:SCONSOLE onoff:NO]; // スプライトはデフォルトOFF
	sconsole=[runView getConsole:SCONSOLE];
	// RUN時画面はここに来る直前に固定されるので、ここで呼び出す必要がある(contextの設定)
	[sconsole start:kCGBitmapByteOrder32Little|kCGImageAlphaPremultipliedLast]; // sconsoleのビットマップはスプライトに合わせてこの形式で確保する
	if ([sconsole initSprite]) {
		// ワークが確保できない
		Error(ERR_NO_WORKAREA);
	}
}

static void _Fend(void)
// この中の関数の終了処理
{
	printFunc();
	[runView disableRotate:NO]; // 画面回転許可
	sconsole=[runView getConsole:SCONSOLE];
	[sconsole freeBG]; 		// BGワーク開放
	[sconsole freeSprite]; 	// スプライトワーク開放
	[sconsole end];
}

// インフォメーションテーブル
const
INFORMATION_TABLE	InfoIosSPFuncs={
	#ifdef FUNC_DEBUG
	"iOS Sprite and BG functions",
	#endif
	returnOnly,	// Finit
	_Frun,		// Frun
	_Fend,		// Fend
	returnOnly,	// Fexit
	returnOnly,	// Fbreak
	NULL,		// FctrlD;未使用
	NULL,		// 予約1
	NULL,		// 予約2
	//
	iOSSPTokens,
	iOSSPParams,
	iOSSPFuncExec
};

//---------------------------------------------------------------------------------------------
