//--------------------------------------------------------------------------------------
//
// X-BASIC'
//	外部関数：X68互換＆便利関数
//
//--------------------------------------------------------------------------------------
// 外部関数の構造を持っている
// 以下の処理内で文字列を扱うところは、呼び出す関数側でUTF8/SHIFT-JIS対応しているのでここでは何もしてない。
// ここの中だけで扱う文字列はちゃんと処理すること。
// 他の外部関数を呼び出しているので、それらが正常に初期化されていないと動かない。

#import "libs.h"
#include "XBiOSx68.h"
#include "fdef.h"
#include "support.h"
#import "rgbhsv.h"
#import "XBiOSkey.h"
#import "XBiOSt.h"
#import "XBiOSg.h"
#import "XBiOSsp.h"
#import "XBiOSsound.h"
#import "XBfunc.h"
#import "XBiOSsound.h"
#import "code2code.h"
#include <time.h>
#import	"RunViewController.h"
#import "libs.h"
int checkBreakIniOS(void);

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

// X68 グラフィック16色パレットの初期設定
int x68gPalets160[]={
//   R G B A	// XM6i(Mac)で表示して実測
	0x000000ff,
	0x4a4a4aff,	// 		74,74,74
	0x000077ff,	// B	0,0,119
	0x0200e2ff,	// BI	2,0,226
	0x750203ff,	// R	117,2,3
	0xe20003ff,	// RI	226,0,3
	0x720571ff,	// RB	114,5,113
	0xde07deff,	// RBI	222,7,222
	0x067003ff,	// G	6,112,3
	0x0Bd905ff,	// GI	11,217,5
	0x017777ff,	// GB	1,119,119
	0x02e7e7ff,	// GBI	2,231,231
	0x7f7f01ff,	// GR	119,119,1
	0xe7e700ff,	// GRI	230,231,0
	0x9c9c9cff,	// GRB	156,156,156
	0xe7e7e7ff	// GRBI	231,231,231
};
#define SZ_X68GPALET	(sizeof(x68gPalets160)/sizeof(int))
int x68gPalets16[SZ_X68GPALET];

// X68 テキストパレットの初期設定
int x68tPalets0[4]={CTHBLACK,CTHCYAN,CTHYELLOW,CTHWHITE};
#define SZ_X68TPALET	(sizeof(x68tPalets0)/sizeof(int))
int x68tPalets[SZ_X68TPALET];

static	tConsole2 *tconsole;

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

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

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

// パレットの設定
// setgPalet16X68(n;int,col;int)
static RET_FUNC _F_setgPalet16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	int   n=(int)fac[0].dl.l[LL];
	int col=(int)fac[1].dl.l[LL];
	if (n>=0 && n<16) {
		x68gPalets16[n]=col;
	} // else 設定しないだけ
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// パレットの読み出し
// int getgPalet16X68(pal;int)
static RET_FUNC _F_getgPalet16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	int pal=(int)fac[0].dl.l[LL];
	if (pal<0 || pal>=SZ_X68GPALET) {
		pal=0;
	}
 	fac[0].dl.l[LL]=x68gPalets16[pal];
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// gColor16X68(n;int)
static RET_FUNC _F_gColor16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	int n=(int)fac[0].dl.l[LL];
	nslog(@"gColor16X68:%d",n);
	if (n>=0 && n<16) {
		FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
		int i=0;
		fac2[i  ].facType=INT_PARAM;
		fac2[i++].dl.l[LL]=x68gPalets16[n]; // rのみに代入
		for (;i<=3;i++) { // g,b,alphaは省略
			fac2[i].facType=VOID_PARAM;
		}
		_F_gColor(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	} else {
		setExternalFuncErrmes("色コードが範囲外です","The color code is illegal.");
		return (RET_FUNC_ERR);
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// gColorX68(col;int)
static RET_FUNC _F_gColorX68(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong col=fac[0].dl.l[LL];
	nslog(@"gColorX68:%d",(int)col);
	if (col<=65535) { // ULongなので常に>=0
		int r,g,b,alpha;
		FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
		int i=0;
		fac2[i  ].facType=INT_PARAM;
		fac2[i++].dl.l[LL]=x68Color2iOSColor(col,&r,&g,&b,&alpha);
		for (;i<=3;i++) { // g,b,alphaは省略
			fac2[i].facType=VOID_PARAM;
		}
		_F_gColor(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	} else {
		setExternalFuncErrmes("色コードが範囲外です","The color code is illegal.");
		return (RET_FUNC_ERR);
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// tColorX68(n;int)
// テキスト色コードの変換が面倒なので、X68の色＋属性コードを再現する処理を作った
// n : X68のテキスト色コード
// 	   色 0～3(bit0-1) : 強調 +4(bit2) , 反転 +8(bit3)
static RET_FUNC _F_tColorX68(SWord numFAC,FAC fac[])
{
	printFunc();
	/*
	 int atrb=ATRB_NORMAL
	 if n and bit(2) then atrb=atrb+ATRB_BOLD
	 if n and bit(3) then atrb=atrb+ATRB_REVERSE
	 tAtrb(atrb+ATRB_CLEAR)
	 dim int cols(3)={CTHBLACK,CTHCYAN,CTHYELLOW,CTHWHITE}
	 tColor(cols(n and &b11))
	 */
	int n=(int)fac[0].dl.l[LL];
	int atrb=ATRB_NORMAL;
	if (n & BIT2) atrb|=ATRB_BOLD;
	if (n & BIT3) atrb|=ATRB_REVERSE;

	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=atrb|ATRB_CLEAR; // 下地を消す指定が必要
	_F_atrb(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)

	nslog(@"n=%d[%d]->$%08x",n,n&3,x68tPalets[n&3]);

	int i=0;
	fac2[i  ].facType=INT_PARAM;
	fac2[i++].dl.l[LL]=x68tPalets[n&3]; // colの下位2ビット 	r
	for (;i<=3;i++) { // g,b,alphaは省略
		fac2[i].facType=VOID_PARAM;
	}
	_F_tColor(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// tColorPaletX68([c0;int][,c1;int][,c2;int][,c3;int])
static RET_FUNC _F_tColorPaletX68(SWord numFAC,FAC fac[])
{
	printFunc();

	for (int i=0;i<SZ_X68TPALET;i++) {
		if (fac[i].facType!=VOID_PARAM) {
			x68tPalets[i]=(int)fac[i].dl.l[LL];
		}
		// 省略された場所は前のまま
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// vpageX68(pg;int[,fsprite;int])
// page3 2 1 0=BIT ?
static RET_FUNC _F_vpageX68(SWord numFAC,FAC fac[])
{
	printFunc();

	int pg=(int)fac[0].dl.l[LL];
	int fsprite=NO;
	if (fac[1].facType!=VOID_PARAM) {
		fsprite=basic2cYESNO(fac[1].dl.l[LL]);
	}
	int page=0;
	if (pg & BIT0) page|=B_GPAGE0;
	if (pg & BIT1) page|=B_GPAGE1;
	if (pg & BIT2) page|=B_GPAGE2;
	if (pg & BIT3) page|=B_GPAGE3;
	page|=B_TPAGE; // テキストは常に表示
	if (fsprite) page|=B_SPAGE;
	
	FAC fac2[1];
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=page;
	_F_vpage(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// apageX68(pg;int)
static RET_FUNC _F_apageX68(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int pg=(int)fac[0].dl.l[LL];
	if (pg<0||pg>3) pg=0; // 範囲外の時は0にしておく
	int gpage[]={GPAGE0,GPAGE1,GPAGE2,GPAGE3};
	FAC fac2[1];
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=gpage[pg];
	_F_apage(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// homeX68(pg;int,hx;int,hy;int)
static RET_FUNC _F_homeX68(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int i=0;
	int pg=(int)fac[i++].dl.l[LL];
	if (pg<0||pg>3) pg=0; // 範囲外の時は0にしておく

	int hx=(int)fac[i++].dl.l[LL];
	int hy=(int)fac[i++].dl.l[LL];
	
	int gpage[]={GPAGE0,GPAGE1,GPAGE2,GPAGE3};
	
	i=0;
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)(-hx);
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)(-hy);
	fac2[i++].facType=VOID_PARAM;	// scaleX
	fac2[i++].facType=VOID_PARAM;	// scaleY
	fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=gpage[pg];
	_F_gTransform(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


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

// pset*X68(x;int,y;int,pal;int)
static RET_FUNC _F_psetX68Sub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	int i=0;
	int   x=(int)fac[i++].dl.l[LL];
	int   y=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=pal;
	RET_FUNC ret;
	if (!fcolX68) {
		ret=_F_gColor16X68(1,fac2);
	} else {
		ret=_F_gColorX68(  1,fac2);
	}
	if (ret!=RET_FUNC_OK) return(ret);

	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeClear;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)x;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)y;
	_F_pset(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeNormal;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// fill*X68(sx;int,sy;int,ex;int,ey;int,pal;int)
static RET_FUNC _F_fillX68Sub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	int i=0;
	int  sx=(int)fac[i++].dl.l[LL];
	int  sy=(int)fac[i++].dl.l[LL];
	int  ex=(int)fac[i++].dl.l[LL];
	int  ey=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし

	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=pal;
	RET_FUNC ret;
	if (!fcolX68) {
		ret=_F_gColor16X68(1,fac2);
	} else {
		ret=_F_gColorX68(  1,fac2);
	}
	if (ret!=RET_FUNC_OK) return(ret);
	
	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeClear;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)sx;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)sy;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)ex;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)ey;
	_F_fill(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)

	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeNormal;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// line*X68(sx;int,sy;int,ex;int,ey;int,pal;int[,style])
static RET_FUNC _F_lineX68Sub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	int i=0;
	int  sx=(int)fac[i++].dl.l[LL];
	int  sy=(int)fac[i++].dl.l[LL];
	int  ex=(int)fac[i++].dl.l[LL];
	int  ey=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	int style=0xffff;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		style=fac[i].dl.l[LL];
	}

	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=pal;
	RET_FUNC ret;
	if (!fcolX68) {
		ret=_F_gColor16X68(1,fac2);
	} else {
		ret=_F_gColorX68(  1,fac2);
	}
	if (ret!=RET_FUNC_OK) return(ret);

	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeClear;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}

	i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)sx;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)sy;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)ex;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)ey;
	fac2[i++].facType=VOID_PARAM;
	fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=style;
	_F_line(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeNormal;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}

	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// box*X68(sx;int,sy;int,ex;int,ey;int,pal;int[,style;int])
static RET_FUNC _F_boxX68Sub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	int i=0;
	int  sx=(int)fac[i++].dl.l[LL];
	int  sy=(int)fac[i++].dl.l[LL];
	int  ex=(int)fac[i++].dl.l[LL];
	int  ey=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	int style=0xffff;
	if (fac[i].facType!=VOID_PARAM) {
		style=(int)fac[i].dl.l[LL];
	}
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=pal;
	RET_FUNC ret;
	if (!fcolX68) {
		ret=_F_gColor16X68(1,fac2);
	} else {
		ret=_F_gColorX68(  1,fac2);
	}
	if (ret!=RET_FUNC_OK) return(ret);

	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeClear;
		_F_blend(1,fac2);
	}

	i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)sx;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)sy;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)ex;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)ey;
	fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=style;
	_F_box(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeNormal;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// symbol*X68(x;int,y;int,mes;str,bai;float,pal;int,font;str[,fontsz;int])
static RET_FUNC _F_symbolX68Sub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	int i=0;
	int  x    =(int)fac[i++].dl.l[LL];
	int  y    =(int)fac[i++].dl.l[LL];
	char *mes      =fac[i++].dl.cp[LL];
	double bai     =fac[i++].dl.d;
	int pal   =(int)fac[i++].dl.l[LL];
	char *font     =fac[i++].dl.cp[LL];
	int fontsz=16;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		fontsz=(int)fac[i].dl.l[LL];
	}
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=pal;
	RET_FUNC ret;
	if (!fcolX68) {
		ret=_F_gColor16X68(1,fac2);
	} else {
		ret=_F_gColorX68(  1,fac2);
	}
	if (ret!=RET_FUNC_OK) return(ret);

	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeClear;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}

	i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)x;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)y;
	fac2[i].facType=STR_PARAM;		fac2[i++].dl.cp[LL]=mes; // UTF8/SJIS対応はsymbol()で
	fac2[i].facType=STR_PARAM;		fac2[i++].dl.cp[LL]=font;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)fontsz*bai;
	fac2[i].facType=VOID_PARAM;
	_F_symbol(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeNormal;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// circle*X68(x;int,y;int,r;int,pal;int[,st;int][,ed;int][,hv;int])
// st,ed=角度(度) ; X68では反時計回り(左回転)
// hvは無視している
static RET_FUNC _F_circleX68Sub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	
	int i=0;
	int   x=(int)fac[i++].dl.l[LL];
	int   y=(int)fac[i++].dl.l[LL];
	int   r=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	nslog(@"x,y=%d,%d/r=%d/col=$%x",x,y,r,pal);
	
	int angle;
	double startAngle=degree2radian(0.0);
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		angle=(int)fac[i].dl.l[LL];
		nslog(@"開始角度(int)=%d",angle);
		startAngle=(double)angle; // ここを(double)fac[i].dl.l[LL]と記述すると、負数の時に間違った変換される(Xcodeのバグ？)
		if (startAngle<-360||startAngle>360) {
			nslog(@"開始角度=%f",startAngle);
			setExternalFuncErrmes("開始角度が範囲外です","Start angle is illegal.");
			return (RET_FUNC_ERR);
		}
		int fminus=NO;
		if (startAngle<0) {
			// 負数指定のあるときは扇型描画なので、一旦正の値に直して計算したあと符号を戻す
			fminus=YES;
			startAngle=-startAngle;
		}
		startAngle=M_PI*2-degree2radian(startAngle); // X68の角度指定をiOSのラジアンに変換する
		if (fminus) startAngle=-startAngle; // 符号戻し
	}
	i++;
	double endAngle=degree2radian(360.0);
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		angle=(int)fac[i].dl.l[LL];
		nslog(@"終了角度(int)=%d",angle);
		endAngle=(double)angle; // ここを(double)fac[i].dl.l[LL]と記述すると、負数の時に間違った変換される(Xcodeのバグ？)
		nslog(@"終了角度=%f",endAngle);
		if (endAngle<-360||endAngle>360) {
			setExternalFuncErrmes("終了角度が範囲外です","End angle is illegal.");
			return (RET_FUNC_ERR);
		}
		int fminus=NO;
		if (endAngle<0) {
			// 負数指定のあるときは扇型描画なので、一旦正の値に直して計算したあと符号を戻す
			fminus=YES;
			endAngle=-endAngle;
		}
		endAngle=M_PI*2-degree2radian(endAngle); // X68の角度指定をiOSのラジアンに変換する
		if (fminus) endAngle=-endAngle; // 符号戻し
	}
	nslog(@"start=%f,end=%f",startAngle,endAngle);

	i++;
	int hv=256;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		// 扁平率
		hv=(int)fac[i].dl.l[LL];
	}
	nslog(@"扁平率=%d",hv);
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=pal;
	RET_FUNC ret;
	if (!fcolX68) {
		ret=_F_gColor16X68(1,fac2);
	} else {
		ret=_F_gColorX68(  1,fac2);
	}
	if (ret!=RET_FUNC_OK) return(ret);

	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeClear;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}

	i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)x;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)y;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=(double)r;
	switch (hv) {
		default:
		{
			nslog(@"楕円");
			double fhv=(double)hv;
			if (hv<256) {
				// 横扁平
				// X68の扁平率は常に縮小側にしか効かないので、ellipse()とは意味が逆になるので注意
				fhv=fhv/256.0;
				nslog(@"横扁平率=%f",fhv);
			}
			else
			if (hv>256) {
				// 縦扁平
				// X68の扁平率は常に縮小側にしか効かないので、ellipse()とは意味が逆になるので注意
				// X68の縦扁平率は等配分ではないので難しい。
				// 上位8ビットで1/2づつの大分割、下位8ビットでその中での割合を示しているようにみえる。
				hv=hv-256;
//				if (hv>=4096) hv=4096; // 残念ながら現在の処理ではこれ以上処理できない
				int l=  hv&0x00ff;			// 下位8ビット
				int h=((hv&0xff00)>>8); 	// 上位8ビット
#if 1
				// 少数計算すると累積演算誤差が激しいので、＊65536して整数演算する
				// 1.0=65536
				int div=2;
				int w=65536/div,ww=0;
				for (int j=1;j<=h;j++) {
					if (j==1) div=3; else div=2;
					ww=ww+w;
					w=w/div;
				}
				nslog(@"縦扁平:hv=%d($%04x):l=%d,h=%d,現在区間幅w=%d,総区間幅ww=%d",hv,hv,l,h,w,ww);
				int ifhv=-65536+ww+(w*l)/256;
				nslog(@"i扁平率=%d",ifhv);
				fhv=(double)ifhv/65536.0;
#else
				double w;	// 現在の区間幅
				double ww;	// 今までの区間幅
				if (hv>=3072) hv=3072; // これくらいから演算結果が0になってしまい変化しない
				int div=2;
				ww=0;
				w=1.0/(double)div;
				for (int j=1;j<=h;j++) {
					if (j==1) div=3; else div=2;
					ww=ww+w;
					w=w/(double)div;
				}
				nslog(@"縦扁平:hv=%d($%04x):l=%d,h=%d,現在区間幅w=%f,総区間幅ww=%f",hv,hv,l,h,w,ww);
				fhv=-1.0+ww+(w*l)/256.0;
#endif
			}
			nslog(@"g扁平率=%f",fhv);
			fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=fhv;
			fac2[i++].facType=VOID_PARAM;
			fac2[i++].facType=VOID_PARAM;
			_F_ellipse(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
			// ellipse(cx;float,cy;float,r;float[,hv;float][,ffill;int][,style;int])
			break;
		}
		case 256:
		case 0: // 真円
			nslog(@"真円");
			fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=startAngle;
			fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=endAngle;
			fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=1; // 反時計方向
			fac2[i++].facType=VOID_PARAM;
			fac2[i++].facType=VOID_PARAM;
			RET_FUNC ret=_F_circle(i,fac2);
			if (ret!=RET_FUNC_OK) return(ret);
			// circle(cx;float,cy;float,r;float[,startAngle;float][,endAngle;float][,clockwise;int][,ffill;int][,style;int])
			break;
	}
	
	if (pal==0) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=BlendModeNormal;
		_F_blend(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// pset16X68(x;int,y;int,pal;int)
static RET_FUNC _F_pset16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_psetX68Sub(numFAC,fac,NO);
}

// fill16X68(sx;int,sy;int,ex;int,ey;int,pal;int)
static RET_FUNC _F_fill16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_fillX68Sub(numFAC,fac,NO);
}

// line16X68(sx;int,sy;int,ex;int,ey;int,pal;int[,style])
static RET_FUNC _F_line16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_lineX68Sub(numFAC,fac,NO);
	
}

// box16X68(sx;int,sy;int,ex;int,ey;int,pal;int[,style;int])
static RET_FUNC _F_box16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_boxX68Sub(numFAC,fac,NO);
	
}

// symbol16X68(x;int,y;int,mes;str,bai;float,pal;int,font;str[,fontsz;int])
static RET_FUNC _F_symbol16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_symbolX68Sub(numFAC,fac,NO);
	
}

// circle16X68(x;int,y;int,r;int,pal;int[,st;int][,ed;int][,hv;int])
static RET_FUNC _F_circle16X68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_circleX68Sub(numFAC,fac,NO);
}

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

// psetX68(x;int,y;int,col;int)
static RET_FUNC _F_psetX68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_psetX68Sub(numFAC,fac,YES);
}

// fillX68(sx;int,sy;int,ex;int,ey;int,col;int)
static RET_FUNC _F_fillX68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_fillX68Sub(numFAC,fac,YES);
}

// lineX68(sx;int,sy;int,ex;int,ey;int,col;int[,style])
static RET_FUNC _F_lineX68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_lineX68Sub(numFAC,fac,YES);
}

// boxX68(sx;int,sy;int,ex;int,ey;int,col;int[,style;int])
static RET_FUNC _F_boxX68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_boxX68Sub(numFAC,fac,YES);
}

// symbolX68(x;int,y;int,mes;str,bai;float,col;int,font;str[,fontsz;int])
static RET_FUNC _F_symbolX68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_symbolX68Sub(numFAC,fac,YES);
}

// circleX68(x;int,y;int,r;int,col;int[,st;int][,ed;int][,hv;int])
static RET_FUNC _F_circleX68(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_circleX68Sub(numFAC,fac,YES);
}

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

// int rgbX68(r;int,g;int,b;int)
// X68 r,g,b=0～31
// フルカラー色コードを返す
static RET_FUNC _F_rgbX68(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int r=(int)fac[i++].dl.l[LL];
	int g=(int)fac[i++].dl.l[LL];
	int b=(int)fac[i++].dl.l[LL];
	if (r<0||r>31) r=31; // エラーは出さない(面倒)
	if (g<0||g>31) g=31; // エラーは出さない(面倒)
	if (b<0||b>31) b=31; // エラーは出さない(面倒)
	// 整数演算するため、演算順序を厳密に指定して演算誤差を減らす
	r=(r*256)/32;
	g=(g*256)/32;
	b=(b*256)/32;
	fac[0].dl.l[LL]=rgb(r,g,b,255);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int hsvX68(hu;int,sa;int,va;int)
// X68 h=0～191,sa,va=0～31
// フルカラー色コードを返す
static RET_FUNC _F_hsvX68(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int hu=(int)fac[i++].dl.l[LL];
	int sa=(int)fac[i++].dl.l[LL];
	int va=(int)fac[i++].dl.l[LL];
	if (hu<0||hu>191) hu=191; // エラーは出さない(面倒)
	if (sa<0||sa> 31) sa=31;  // エラーは出さない(面倒)
	if (va<0||va> 31) va=31;  // エラーは出さない(面倒)
	 // 整数演算するため、演算順序を厳密に指定して演算誤差を減らす
	hu=(hu*360)/192;
	sa=(sa*256)/32;
	va=(va*256)/32;
	fac[0].dl.l[LL]=hsv(hu,sa,va,255);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// int rgbX68X68(r;int,g;int,b;int)
// X68 r,g,b=0～31
// X68の色コードを返す
static RET_FUNC _F_rgbX68X68(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int r=(int)fac[i++].dl.l[LL];
	int g=(int)fac[i++].dl.l[LL];
	int b=(int)fac[i++].dl.l[LL];
	//  54321 09876 54321 0 bit
	// %00000_00000_00000_1	輝度
	// %00000_00000_11111_1	青
	// %00000_11111_00000_0	赤
	// %11111_00000_00000_0	緑
	if (r<0||r>31) r=31; // エラーは出さない(面倒)
	if (g<0||g>31) g=31; // エラーは出さない(面倒)
	if (b<0||b>31) b=31; // エラーは出さない(面倒)
	//
	g=(g<<11);
	r=(r<< 6);
	b=(b<< 1);
	//
	fac[0].dl.l[LL]=(g|r|b); // 輝度ビットは0にしておく
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int hsvX68X68(hu;int,sa;int,va;int)
// X68 h=0～191,sa,va=0～31
static RET_FUNC _F_hsvX68X68(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int hu=(int)fac[i++].dl.l[LL];
	int sa=(int)fac[i++].dl.l[LL];
	int va=(int)fac[i++].dl.l[LL];
	if (hu<0||hu>191) hu=191; // エラーは出さない(面倒)
	if (sa<0||sa> 31) sa=31;  // エラーは出さない(面倒)
	if (va<0||va> 31) va=31;  // エラーは出さない(面倒)
	// X68でのhsv->RGB直接変換式が見つけられなかったので、
	// 一旦フルカラーで変換してX68のRGBに変換する
	// 整数演算するため、演算順序を厳密に指定して演算誤差を減らす
	nslog(@"hsv(%d,%d,%d)=",hu,sa,va);
	hu=(hu*360)/192;
	sa=(sa*256)/32;
	va=(va*256)/32;
	nslog(@"(%d,%d,%d)=",hu,sa,va);

	double hd=(double)(hu);
	double sd=_cf(sa);
	double vd=_cf(va);
	double rd, gd, bd;
	hsv2rgb( &rd, &gd, &bd, hd, sd, vd ); // rd/gd/bdは0〜<1.0なので注意
	int r,g,b;
	rd=rd*32; r=(int)rd;
	gd=gd*32; g=(int)gd;
	bd=bd*32; b=(int)bd;
	g=(g<<11);
	r=(r<< 6);
	b=(b<< 1);
	fac[0].dl.l[LL]=(g|r|b); // 輝度ビットは0にしておく
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// int randX68([type;int])
// type : NO/省略 rand() , YES=random()
static RET_FUNC _F_randX68(SWord numFAC,FAC fac[])
{
	printFunc();

	int type=NO;
	if (fac[0].facType!=VOID_PARAM) { // 引数が省略されていない時
		type=basic2cYESNO(fac[0].dl.l[LL]);
	}
	nslog(@"type=%d",type);
	int r=(type? (int)random():rand()); // 整数乱数
	r%=32768; // X68は0〜32767の範囲なので
	fac[0].dl.l[LL]=r;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


// contrastX68(ns;int,ne;int,spd;float[,mode;int])
// n?=0〜15(16段階)
// spd=wait()の引数
// mode=制御する画面;CONTRAST_*のorで指定
// X68のcontrast()は現在の明るさから指定値までをアナログ的に変化させる
// iOS版というかこの関数は現在の明るさを保存していないので、開始値と終了値の両方を与える必要がある
static RET_FUNC _F_contrastX68(SWord numFAC,FAC fac[])
{
	printFunc();

	int i=0;
	int ns=(int)fac[i++].dl.l[LL];
	int ne=(int)fac[i++].dl.l[LL];
	double  spd=fac[i++].dl.d;
	int mode=CONTRAST_TEXT|CONTRAST_GRAPHIC|CONTRAST_SPRITE;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		mode=(int)fac[i].dl.l[LL];
	}
/*
 float stp,stp0
 float st,ed
	st=ns:// float化
	ed=ne:// float化
	st=1.0/15*st
	ed=1.0*15*ed
	stp=(ed-st)/32
	stp0=stp
	if stp<0 then stp0=-stp
	repeat
	 gBackgroundAlpha(st)
	 st=st+stp
	 wait(spd)
	until abs(st-ed)<stp0
 */
	// BackgroundAlphaは(0.0〜1.0)
	double stp,stp0;
	double st,ed;
	st=(double)ns;	// double化
	ed=(double)ne;	// double化
	st=1.0/15*st;
	ed=1.0/15*ed;
	stp=(ed-st)/32;	// どの区間であっても同一段階で変化させる
	stp0=stp;
	if (stp<0) stp0=-stp;	// stp0は増減値の絶対値
	nslog(@"st=%f,ed=%f,stp=%f",st,ed,stp);
	do {
		if (mode&CONTRAST_GRAPHIC)	_F_gBackgroundAlphaSub(st);
		if (mode&CONTRAST_TEXT	)	_F_tBackgroundAlphaSub(st);
		if (mode&CONTRAST_SPRITE)	_F_sBackgroundAlphaSub(st);
		st=st+stp;
		
		FAC fac2[2];
		int i=0;
		fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=spd;
		fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=BASIC_YES;
		_F_wait(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	} while (fabs(st-ed)>=stp0);	// 累積演算誤差を考慮しての判定
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------
// スプライト系関数は、スプライトが有効になっていないと使えない

BOOL isSpriteEnable(void)
{
	if (!operationStatus.fsprite) {
		// スプライト機能が無効の時はこちらも使えない
		setExternalFuncErrmes("スプライト機能が無効のため使えません","This function can't work because sprite funcsions are disable.");
		return NO;
	}
	// スプライトは有効
	return YES;
}

// int bg_getX68(pg;int,x;int,y;int)
// pg = テキストページ0/1
// x,y= 座標
static RET_FUNC _F_bg_getX68(SWord numFAC,FAC fac[])
{
	printFunc();

	// スプライト機能が無効の時はこちらも使えない
	if (!isSpriteEnable()) return (RET_FUNC_ERR);
	
	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 pb,flip;
	
	// ただし、パターンは0〜255しか使わない範囲で互換性が取れる
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pg;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=x;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=y;
	fac2[i].facType=POINTER_PARAM;fac2[i++].dl.ip[LL]=&pb;
	fac2[i].facType=POINTER_PARAM;fac2[i++].dl.ip[LL]=&flip;
	_F_bg_get(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	int sp=fac2[0].dl.l[LL]; // リターン値
	nslog(@"bg_getX68 : pb=%d,flip=%d,sp=%d",pb,flip,sp);

	pb  =pb   <<  8;	// bit 8-11へ
	flip=flip << 14;	// bit14,15へ
	fac[0].dl.l[LL]=(sp | pb | flip);
	nslog(@"return=$%x",(int)fac[0].dl.l[LL]);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int bg_putX68(pg;int,x;int,y;int,pd;int)
// pg = テキストページ0/1
// x,y= 座標
// pd = パターンデータ
static RET_FUNC _F_bg_putX68(SWord numFAC,FAC fac[])
{
	printFunc();
	
	// スプライト機能が無効の時はこちらも使えない
	if (!isSpriteEnable()) return (RET_FUNC_ERR);

	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 pd=(int)fac[i++].dl.l[LL];

	int pb,flip,sp;
	// ただし、パターンは0〜255しか使わない範囲で互換性が取れる
	pb  =(pd >>  8) & 0xf;	// bit 8-11から
	flip=(pd >> 14) & 0x3;	// bit14,15から
	sp  =(pd & 0xff);		// bit0-7
	nslog(@"bg_putX68 : pb=%d,flip=%d,sp=%d",pb,flip,sp);
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pg;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=x;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=y;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=sp;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pb;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=flip;
	_F_bg_put(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	fac[0].dl.l[LL]=fac2[0].dl.l[LL];
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int bg_fillX68(pg;int,pd;int)
// pg = テキストページ0/1
// pd = パターンデータ
static RET_FUNC _F_bg_fillX68(SWord numFAC,FAC fac[])
{
	printFunc();
	
	// スプライト機能が無効の時はこちらも使えない
	if (!isSpriteEnable()) return (RET_FUNC_ERR);
	
	int i=0;
	int pg=(int)fac[i++].dl.l[LL];
	int pd=(int)fac[i++].dl.l[LL];

	int pb,flip,sp;
	// ただし、パターンは0〜255しか使わない範囲で互換性が取れる
	pb  =(pd >>  8) & 0xf;	// bit 8-11から	パレットブロック
	flip=(pd >> 14) & 0x3;	// bit14=水平反転,15=垂直反転
	sp  =(pd & 0xff);		// bit0-7		パターンコード
	nslog(@"bg_fillX68 : pb=%d,flip=%d,sp=%d",pb,flip,sp);

	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pg;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=sp;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pb;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=flip;
	_F_bg_fill(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	fac[0].dl.l[LL]=fac2[0].dl.l[LL];
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int sp_colorX68(pc;int,col;int[,pb;int])
// pc  = パレットコード
// col = X68色コード
// pb  = パレットブロック
static RET_FUNC _F_sp_colorX68(SWord numFAC,FAC fac[])
{
	printFunc();
	
	// スプライト機能が無効の時はこちらも使えない
	if (!isSpriteEnable()) return (RET_FUNC_ERR);
	//
	int i=0;
	int pc=(int)fac[i++].dl.l[LL];
	ULong colX68=fac[i++].dl.l[LL]; // X68色
	int pb=1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pb=(int)fac[i].dl.l[LL];
	}
	nslog(@"pc=%d,X68色=$%04x,pb=%d",pc,(int)colX68,pb);
	//
	int r,g,b,alpha;
	colX68=x68Color2iOSColor(colX68,&r,&g,&b,&alpha);
	nslog(@"iOS色=$%08x",(int)colX68);
	//
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pc;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=colX68;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pb;
	_F_sp_color(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	//
	fac[0].dl.l[LL]=fac2[0].dl.l[LL];
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int sp_setX68(pl;int[,x;int][,y;int][,pd;int][,pr;int])
static RET_FUNC _F_sp_setX68(SWord numFAC,FAC fac[])
{
	printFunc();
	
	// スプライト機能が無効の時はこちらも使えない
	if (!isSpriteEnable()) return (RET_FUNC_ERR);
	
	int i=0;
	int pl=(int)fac[i++].dl.l[LL];
	//
	int x=16; // =0は警告回避穂のため
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		x=(int)fac[i].dl.l[LL];
	}
	i++;
	int y=16; // =0は警告回避穂のため
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		y=(int)fac[i].dl.l[LL];
	}
	i++;
	
	// パターンデータ
	int pd=0;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		pd=(int)fac[i].dl.l[LL];
	}
	i++;
	
	int pb,flip,sp;
	// ただし、パターンは0〜255しか使わない範囲で互換性が取れる
	pb  =(pd >>  8) & 0xf;	// bit 8-11から	パレットブロック
	flip=(pd >> 14) & 0x3;	// bit14=水平反転,15=垂直反転
	sp  =(pd & 0xff);		// bit0-7		パターンコード
	nslog(@"sp_setX68 : pb=%d,flip=%d,sp=%d",pb,flip,sp);
	
	int prw=-1;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		prw=(int)fac[i].dl.l[LL];
	}
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pl;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=x-16;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=y-16;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=sp;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=pb;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=flip;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=prw;
	_F_sp_setting(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	fac[0].dl.l[LL]=fac2[0].dl.l[LL];
	//
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 便利関数

// str localizedString(js;str,es;str)
static RET_FUNC _F_localizedString(SWord numFAC,FAC fac[])
{
	printFunc();
	// 単に返す文字列アドレスを切り替えるだけなので、文字コードは関係ない
	char *retStr=fac[1].dl.cp[LL];
	if (isLocalizeJapan()) {
		retStr=fac[0].dl.cp[LL];
	}
	fac[0].dl.cp[LL]=retStr;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// hitKey([fcls;int][,jstr;str][,estr;str])
static RET_FUNC _F_hitKey(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int i=0;
	int fcls=YES;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		fcls=basic2cYESNO(fac[i].dl.l[LL]);
	}
	i++;
	
	char *jstr="ここをタップしてください";
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		jstr=fac[i].dl.cp[LL];
	}
	i++;
	
	char *estr="Tap Here";
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		estr=fac[i].dl.cp[LL];
	}
	i++;
	
	char *retStr=estr;
	if (isLocalizeJapan()) {
		retStr=jstr;
	}
	nslog(@"hitKey:%s",retStr);

	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL] =0;
	fac2[i].facType=STR_PARAM;	fac2[i++].dl.cp[LL]=retStr; // UTF8/SJIS対応はsetFunctionKey()で
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL] =' ';
	_F_setFunctionKey(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=BASIC_YES;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=0;	// st
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=0;	// ed
	fac2[i++].facType=VOID_PARAM; // f2stage
	fac2[i++].facType=VOID_PARAM; // clearance
	_F_displayFunctionKey(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	do {
		// Breakチェックをする
		if (checkBreakIniOS()) {
			fcls=NO; // breakされた時はclsは無効にする
			break;
		}
		// 回っている間に乱数をかき混ぜる
		rand();
		random();
		_F_inkey(0,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
		EnterRunLoop(0.1); 
	} while (fac2[0].dl.l[LL]==0);

	if (fcls) {
		_F_cls(0,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}

	i=0;
	fac2[i  ].facType=INT_PARAM;
	fac2[i++].dl.l[LL]=BASIC_NO;
	for (;i<=4;i++) { // st,ed,f2stage,clearanceは省略
		fac2[i].facType=VOID_PARAM;
	}
	_F_displayFunctionKey(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	_F_kbclr(0,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int getch()
static RET_FUNC _F_getch(SWord numFAC,FAC fac[])
{
	printFunc();

	int cc=0; // すぐBreakチェックで終わるときのため

	FAC fac2[1];
	_F_kbclr(0,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	do {
		// Breakチェックをする
		if (checkBreakIniOS()) {
			break;
		}
		_F_inkey(0,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
		cc=fac2[0].dl.l[LL];
	} while (cc==0);
	
	fac[0].dl.l[LL]=cc;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// 1/60sec=16.6ms単位で待つ
// vwait(tm;int)
static RET_FUNC _F_vwait(SWord numFAC,FAC fac[])
{
	printFunc();

	int tm=(int)fac[0].dl.l[LL];
	nslog(@"待ち時間=%d",tm);
	float tf=(float)tm;
	tf=tf/60.0;	// 1/60秒単位にする
	
	FAC fac2[2];
	int i=0;
	fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=tf;	// wait(秒単位,YES)
	fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=BASIC_YES;
	_F_wait(i,fac2);	// breakチェックはこの中でされている // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// 時計からrand()乱数を初期化する
// srand2()
static RET_FUNC _F_srand2(SWord numFAC,FAC fac[])
{
	printFunc();
	static unsigned int before=-1;

	time_t tm;
	time(&tm);
	nslog(@"tm=%d",(int)tm);
	
	unsigned int ttm=(unsigned int)(tm<<4); // 系列を広げるため16単位にする
	nslog(@"ttm=%u",ttm);
	if (ttm==before) {
		ttm+=(unsigned int)clock();
		nslog(@"前回と同じなので補正ttm=%u",ttm);
		// これでも同じならしょうがない
	}
	before=ttm;
	srand(ttm);
	srandom(ttm);
	//
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// 0～seed-1の乱数発生
// int rand2(seed;int[,type;int])
// type : NO/省略 rand() , YES=random()
static RET_FUNC _F_rand2(SWord numFAC,FAC fac[])
{
	printFunc();
	int seed=(int)fac[0].dl.l[LL];
	nslog(@"seed=%d",seed);
	
	int type=NO;
	if (fac[1].facType!=VOID_PARAM) { // 引数が省略されていない時
		type=basic2cYESNO(fac[1].dl.l[LL]);
	}
	nslog(@"type=%d",type);
	int r=(type? (int)random():rand()); // 整数乱数
	fac[0].dl.l[LL]=(r % seed);
	fac[0].facType=FACTYPE_RETURN;
	
	return (RET_FUNC_OK); // OK
}

// ベルを指定回数鳴らす
// bell(tim;int)
static RET_FUNC _F_bell(SWord numFAC,FAC fac[])
{
	printFunc();
	int tim=(int)fac[0].dl.l[LL];
	nslog(@"bell:回数=%d",tim);
	FAC fac2[1];
	for (int i=1;i<=tim;i++) {
		_F_beep( 0,fac2);	// (void) -> fac2 // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=2;
		_F_vwait(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// X68の16色パターンをiOSフルカラーパターンに変換する
void ptrn16X68toiOS(int xcy,UByte ptrnX68[],ULong ptrniOS[],int fdouble,int ftoumei)
{
UByte c;
int cl,pl;
int i,j=0;
	for (i=0;i<xcy;i++) {
		c=ptrnX68[i];
		pl=(c >> 4);
		if (pl==0 && ftoumei) {
			cl=0; // 透明
		} else {
			cl=x68gPalets16[pl];
		}
		ptrniOS[j]=cl;
		if (fdouble) {
			j++;
			ptrniOS[j]=cl;
		}
		//
		j++;
		pl=(c & 0xf);
		if (pl==0 && ftoumei) {
			cl=0; // 透明
		} else {
			cl=x68gPalets16[pl];
		}
		ptrniOS[j]=cl;
		if (fdouble) {
			j++;
			ptrniOS[j]=cl;
		}
		j++;
	}
}

// ptrn16X68toiOS(xcy;int,ptrnX68();char,ptrniOS();int[,fdouble;int][ftoumei;int])
// パターンのX68->iOS変換
// X68パターンは1バイトで2ドットなので、iOSパターンの要素数は*2、fdouble=1の時は横倍化されるので更に*2
static RET_FUNC _F_ptrn16X68toiOS(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int i=0;
	int xcy=(int)fac[i++].dl.l[LL];
	
	SWord   size1X68;
	uwYouso yousoX68;
	UByte *ptrnX68=(UByte *)getDim1FromFAC(fac,i++,&size1X68,&yousoX68);
	if (ptrnX68==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"ptrnX68:1要素サイズ=%d,要素数=%d",size1X68,yousoX68);
	nslog(@"xcy/2=%d",xcy/2);
	
	if (yousoX68<xcy/2) {
		// パターン定義に必要な要素数が足りない
		// 1バイトでH/Lで2ドット入るので/2
		setExternalFuncErrmes("パターン定義に必要な配列の要素数が足りません","Array's elements are not enough for pattern definition.");
		return (RET_FUNC_ERR);
	}
	
	SWord   size1iOS;
	uwYouso yousoiOS;
	ULong *ptrniOS=(ULong *)getDim1FromFAC(fac,i++,&size1iOS,&yousoiOS);
	if (ptrniOS==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"ptrniOS:1要素サイズ=%d,要素数=%d",size1iOS,yousoiOS);
	
	if (size1iOS!=4||size1X68!=1) {
		// 1要素サイズが違う
		setExternalFuncErrmes("要素型が異なります","Array's type is illegal.");
		return (RET_FUNC_ERR);
	}

	int fdouble=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		fdouble=basic2cYESNO(fac[i].dl.l[LL]);
	}
	i++;

	int ftoumei=NO;
	if (fac[i].facType!=VOID_PARAM) { // 引数が省略されていない時
		ftoumei=basic2cYESNO(fac[i].dl.l[LL]);
	}
	i++;
	
	nslog(@"必要要素数=%d",yousoX68*2*(fdouble? 2:1));
	if (yousoiOS<yousoX68*2*(fdouble? 2:1)) {
		// 要素数が足りない
		setExternalFuncErrmes("変換後配列の要素数が足りません","Array's elements are not enough.");
		return (RET_FUNC_ERR);
	}
	
	ptrn16X68toiOS(xcy,ptrnX68,ptrniOS,fdouble,ftoumei);
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


// 8*8のパターンを16*16のパターンに拡大変換する
void ptrn8to16(UByte ptrn8[],UByte ptrn16[])
{
	UByte c,*p1,*p2;
	int y,x;
	p1= ptrn16;
	for (y=0;y<8;y++) {
		p2=&p1[16];
		for (x=0;x<8;x++) {
			c=ptrn8[y*8+x];
			*p1++=c; *p1++=c;
			*p2++=c; *p2++=c;
		}
		p1+=16;
	}
}

// ptrn8to16(ptrn8();char,ptrn16;char)
// 8*8のパターンを16*16のパターンに拡大変換する
// X68のスプライトパターンは画面モードによって8*8のことがあるが、iOSでは16*16のみなので
static RET_FUNC _F_ptrn8to16(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int i=0;
	
	SWord   size18;
	uwYouso youso8;
	UByte *ptrn8=(UByte *)getDim1FromFAC(fac,i++,&size18,&youso8);
	if (ptrn8==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"ptrn8:1要素サイズ=%d,要素数=%d",size18,youso8);
	if (youso8<8*8) {
		// パターン定義に必要な要素数が足りない
		setExternalFuncErrmes("配列の要素数が足りません","Array's elements are not enough.");
		return (RET_FUNC_ERR);
	}
	
	SWord   size116;
	uwYouso youso16;
	UByte *ptrn16=(UByte *)getDim1FromFAC(fac,i++,&size116,&youso16);
	if (ptrn16==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"ptrn16:1要素サイズ=%d,要素数=%d",size116,youso16);
	if (youso16<16*16) {
		// 要素数が足りない
		setExternalFuncErrmes("変換後配列の要素数が足りません","Array's elements are not enough.");
		return (RET_FUNC_ERR);
	}
	
	ptrn8to16(ptrn8,ptrn16);
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


// WaitPCM(sno;int)
// 音が止まるまで待つ
static RET_FUNC _F_WaitPCM(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int sno=(int)fac[0].dl.l[LL];
	if (sno>=0) {
		FAC fac2[2];
		do {
			// Breakチェックをする
			if (checkBreakIniOS()) {
				break;
			}
			int i=0;
			fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=0.05;	// ちょっと待ちながら
			fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=BASIC_YES;
			_F_wait(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
			fac2[0].facType=INT_PARAM;
			fac2[0].dl.l[LL]=sno;
		} while (_F_a_stat(1,fac2),fac2[0].dl.l[LL]!=0);
	}	// sno<0:サウンドファイルの読み込みに失敗しているときは待ち処理させない(本質的にはサウンドファイル読み込みを成功するよう修正すること)
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// PCMplay(sno;int,fwait;int)
// ADPCMを鳴らす
// fwait : YES=終了待ちする
static RET_FUNC _F_PCMplay(SWord numFAC,FAC fac[])
{
	printFunc();
	
	int i=0;
	int   sno=(int)fac[i++].dl.l[LL];
	int fwait=basic2cYESNO(fac[i++].dl.l[LL]);
	
	FAC fac2[2];
	fac2[0].facType=INT_PARAM;
	fac2[0].dl.l[LL]=sno;
	_F_a_play(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	if (fwait) {
		fac2[0].facType=INT_PARAM;
		fac2[0].dl.l[LL]=sno;
		_F_WaitPCM(1,fac2);	// 終了待ち;Breakチェックも行われている // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	}
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// paint*X68b(x;int,y;int,pal;int)
static RET_FUNC _F_paintX68bSub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	
	int i=0;
	int   x=(int)fac[i++].dl.l[LL];
	int   y=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	if (pal<0||pal>=(fcolX68? 65536:SZ_X68GPALET)) pal=0; // 色コードが範囲を超えるときは0にしてしまう
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=x;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=y;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=(fcolX68? x68Color2iOSColor(pal,NULL,NULL,NULL,NULL):x68gPalets16[pal]);
	fac2[i++].facType=VOID_PARAM;
	_F_bitmapPaint(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	_F_bitmapImgLoadSub(0,0,0,0);
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// circle*X68b(x;int,y;int,r;int,pal;int)
static RET_FUNC _F_circleX68bSub(SWord numFAC,FAC fac[],BOOL fcolX68)
{
	printFunc();
	int i=0;
	int   x=(int)fac[i++].dl.l[LL];
	int   y=(int)fac[i++].dl.l[LL];
	int   r=(int)fac[i++].dl.l[LL];
	int pal=(int)fac[i++].dl.l[LL];
	if (pal<0||pal>=(fcolX68? 65536:SZ_X68GPALET)) pal=0; // 色コードが範囲を超えるときは0にしてしまう
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	i=0;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=x;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=y;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=r;
	fac2[i].facType=INT_PARAM;	fac2[i++].dl.l[LL]=(fcolX68? x68Color2iOSColor(pal,NULL,NULL,NULL,NULL):x68gPalets16[pal]);
	fac2[i++].facType=VOID_PARAM;
	fac2[i++].facType=VOID_PARAM;
	_F_bitmapCircle(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
	_F_bitmapImgLoadSub(0,0,0,0);
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_paint16X68b(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_paintX68bSub(numFAC,fac,NO);
}

static RET_FUNC _F_paintX68b(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_paintX68bSub(numFAC,fac,YES);
}

static RET_FUNC _F_circle16X68b(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_circleX68bSub(numFAC,fac,NO);
}

static RET_FUNC _F_circleX68b(SWord numFAC,FAC fac[])
{
	printFunc();
	return _F_circleX68bSub(numFAC,fac,YES);
}

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

static RET_FUNC _F_x68Color2iOSColor(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int col=(int)fac[i++].dl.l[LL];
	if (fac[i].facType!=VOID_PARAM) {
		int *r	  =fac[i++].dl.ip[LL];
		int *g	  =fac[i++].dl.ip[LL];
		int *b	  =fac[i++].dl.ip[LL];
		int *alpha=fac[i++].dl.ip[LL];
		fac[0].dl.l[LL]=x68Color2iOSColor(col,r,g,b,alpha);
	} else { // r/g/b/alpha省略時は合成RGB値のみを返すため、各変数はダミーを与える
		int r,g,b,alpha;
		fac[0].dl.l[LL]=x68Color2iOSColor(col,&r,&g,&b,&alpha);
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_x68256Color2iOSColor(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int col=(int)fac[i++].dl.l[LL];
	if (fac[i].facType!=VOID_PARAM) {
		int *r	  =fac[i++].dl.ip[LL];
		int *g	  =fac[i++].dl.ip[LL];
		int *b	  =fac[i++].dl.ip[LL];
		int *alpha=fac[i++].dl.ip[LL];
		fac[0].dl.l[LL]=x68256Color2iOSColor(col,r,g,b,alpha);
	} else { // r/g/b/alpha省略時は合成RGB値のみを返すため、各変数はダミーを与える
		int r,g,b,alpha;
		fac[0].dl.l[LL]=x68256Color2iOSColor(col,&r,&g,&b,&alpha);
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_x6816Color2iOSColor(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int pal=(int)fac[i++].dl.l[LL];
	ULong col=x68gPalets16[pal];
	if (fac[i].facType!=VOID_PARAM) {
		int *r	  =fac[i++].dl.ip[LL];
		int *g	  =fac[i++].dl.ip[LL];
		int *b	  =fac[i++].dl.ip[LL];
		int *alpha=fac[i++].dl.ip[LL];
		splitRGB(col,r,g,b,alpha);
		fac[0].dl.l[LL]=col;
	} else { // r/g/b/alpha省略時は合成RGB値のみを返す
		fac[0].dl.l[LL]=col;
	}
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// 度をラジアンに変換する
// float deg2rad(deg;float)
static RET_FUNC _F_deg2rad(SWord numFAC,FAC fac[])
{
	printFunc();
	double deg=fac[0].dl.d;
//	nslog(@"度=%f",deg);
	fac[0].dl.d=degree2radian(deg);
//	nslog(@"ラジアン=%f",fac[0].dl.d);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// ラジアンを度に変換する
// float rad2deg(rad;float)
static RET_FUNC _F_rad2deg(SWord numFAC,FAC fac[])
{
	printFunc();
	double rad=fac[0].dl.d;
//	nslog(@"ラジアン=%f",rad);
	fac[0].dl.d=radian2degree(rad);
//	nslog(@"度=%f",fac[0].dl.d);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// タッチキーの表示＆設定をする
// 表示は現在のグラフィックページに対して行う＝グラフィック表示の設定が必要
// int setTouchKeys(sx;int,sy;int,xc;int,yc;int,k1x;int,k1y;int,keys();int,[disps();str,fnt;str][,touchNo();int][,dx;int][dy;int])
static RET_FUNC _F_setTouchKeys(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	double  sx=fac[i++].dl.d;
	double  sy=fac[i++].dl.d;
	int  xc=fac[i++].dl.l[LL];
	int  yc=fac[i++].dl.l[LL];
	double k1x=(double)fac[i++].dl.l[LL]; // 以下の処理の都合でdoubleで保持
	double k1y=(double)fac[i++].dl.l[LL];
	nslog(@"sx,sy=%f,%f",sx,sy);
	nslog(@"xc,yc=%d,%d",xc,yc);
	nslog(@"k1x,k1y=%f,%f",k1x,k1y);

	SWord   size1Keys;
	uwYouso yousoKeys;
	int *keys=(int *)getDim1FromFAC(fac,i++,&size1Keys,&yousoKeys);
	if (keys==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"keys:1要素サイズ=%d,要素数=%d",size1Keys,yousoKeys);
	
	SWord   size1Disps;
	uwYouso yousoDisps;
	char *disps=NULL;
	if (fac[i].facType!=VOID_PARAM) {
		disps=(char *)getDim1FromFAC(fac,i,&size1Disps,&yousoDisps);
		if (disps==NULL) { // 1次元でない
			return (RET_FUNC_ERR);
		}
		nslog(@"disps:1要素サイズ=%d,要素数=%d",size1Disps,yousoDisps);
	} else {
		nslog(@"disps省略時は表示なし");
	}
	i++;

	char *fnt=NULL;
	if (fac[i].facType!=VOID_PARAM) {
		fnt=fac[i].dl.cp[LL];
		nslog(@"font=%s",fnt);
	} else {
		// disps省略時のみfnt省略可能
		if (disps!=NULL) {
			setExternalFuncErrmes("dispsがあるときはfntの指定は省略できません","Can't omit fnt when disps is not omitted.");
			return (RET_FUNC_ERR);
		}
		nslog(@"font省略");
	}
	i++;
	
	SWord   size1TouchNo;
	uwYouso yousoTouchNo;
	int *touchNo=NULL;
	if (fac[i].facType!=VOID_PARAM) {
		touchNo=(int *)getDim1FromFAC(fac,i,&size1TouchNo,&yousoTouchNo);
		if (touchNo==NULL) { // 1次元でない
			return (RET_FUNC_ERR);
		}
		nslog(@"touchNo:1要素サイズ=%d,要素数=%d",size1TouchNo,yousoTouchNo);
	}
	i++;

	// v3.50
	int dx=0,dy=0;
	if (fac[i].facType!=VOID_PARAM) {
		dx=fac[i].dl.l[LL];
		if (dx<0) dx=0;
		if (dx>=k1x) dx=k1x;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) {
		dy=fac[i].dl.l[LL];
		if (dy<0) dy=0;
		if (dy>=k1y) dy=k1y;
	}
	i++;
	nslog(@"dx=%d,dy=%d",dx,dy);
	
	
	// startup.basと合わせること
#define	FKEY_NOT_REPEAT   	BIT8
#define	FKEY_NOT_BEGANONLY	BIT9	// エリア外からタッチしたままエリア内に入ってきた時も検知するかどうか
#define	FKEY_WAKUONLY		BIT10	// 枠のみ描画(タッチエリアにはならない)
#define	WD		2	// 枠線幅
#define COLSTEP	4
	int col[COLSTEP]={0x1f1f1fff,0x3f3f3fff,0x7f7f7fff,0xffffffff};	// キーの枠線色変化
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	fac2[0].facType=FLOAT_PARAM;
	fac2[0].dl.d=0.9;
	_F_kBackgroundAlpha(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)

	fac2[0].facType=FLOAT_PARAM;
	fac2[0].dl.d=WD;
	_F_lineWidth(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)

	double pointSize=k1x;
	if (pointSize>k1y) pointSize=k1y; // 小さい方を取る
	pointSize=(pointSize-WD*COLSTEP*2)*0.8; // 8割のサイズにする

	double sx1,sy1;
	int j=0,k=0;
	sy1=sy;
	for (int yy=0;yy<yc;yy++) {
		sx1=sx;
		for (int xx=0;xx<xc;xx++) {
			int ky=keys[k];
			nslog(@"yy=%d,xx=%d,ky=$%04x",yy,xx,ky);
			if (ky!=0) {
				if (disps!=NULL) {
				if (disps[0]!=0) { // disps(i)<>""
					// 枠線下消去
					i=0;
					fac2[i  ].facType=INT_PARAM; 	fac2[i++].dl.l[LL]=0x000000ff;
					fac2[i++].facType=VOID_PARAM;
					fac2[i++].facType=VOID_PARAM;
					fac2[i++].facType=VOID_PARAM;
					_F_gColor(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
					
					i=0;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1+(k1x-1);
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1+(k1y-1);
					fac2[i++].facType=VOID_PARAM;
					_F_fill(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
					
					// 枠線描画
					for (int d=0;d<COLSTEP;d++) {
						i=0;
						fac2[i  ].facType=INT_PARAM; 	fac2[i++].dl.l[LL]=col[d];
						fac2[i++].facType=VOID_PARAM;
						fac2[i++].facType=VOID_PARAM;
						fac2[i++].facType=VOID_PARAM;
						_F_gColor(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
						
						i=0;
						double fd=(double)(d*WD);
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1+fd;
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1+fd;
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1+(k1x-1)-fd;
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1+(k1y-1)-fd;
						fac2[i++].facType=VOID_PARAM;
						_F_box(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
					}
					
					// フォントサイズ取得
					nslog(@"[%@]",@(disps));
					double fontWx,fontWy;
					i=0;
					fac2[i].facType=STR_PARAM;		fac2[i++].dl.cp[LL]=disps;
					fac2[i].facType=STR_PARAM;		fac2[i++].dl.cp[LL]=fnt;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=pointSize;
					fac2[i].facType=FLOAT_VP;		fac2[i++].dl.dp[LL]=&fontWy;
					_F_fontSize(i, fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
					fontWx=fac2[0].dl.d;
					if (fontWy>pointSize) fontWy=pointSize;
					
					// キー文字描画
					i=0;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1+k1x/2-fontWx/2;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1+k1y/2-fontWy/2;
					fac2[i].facType=STR_PARAM;		fac2[i++].dl.cp[LL]=disps;
					fac2[i].facType=STR_PARAM;		fac2[i++].dl.cp[LL]=fnt;
					fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=pointSize;
					fac2[i++].facType=VOID_PARAM;
					_F_symbol(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
				} // disps[0]=0 ; disps(i)=""のときは枠線も文字も表示しない(タッチエリア設定専用)
				} // disps!=NULL
					
				// キーエリア設定
				if (touchNo!=NULL) {
					// キーエリアの属性を取得(上位8ビットは属性)
					if (!(ky & FKEY_WAKUONLY) && ky!=0) {
						int kcol;
						i=0;
						if (ky & FKEY_NOT_REPEAT) {
							kcol=0x007d0564;		// リピート無し色
							// リピート無し / repeat none
							fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=-1;
							fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=0;
						} else {
							kcol=0x7d000564;		// リピートあり色
							// リピート時間 / repeat time
							fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=3;
							fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=2;
						}
						_F_keyRepeatTime(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)

						i=0;
						int fBeganonly=BASIC_YES;
						if (ky & FKEY_NOT_BEGANONLY) fBeganonly=BASIC_NO;
						double fc=(double)(WD*COLSTEP);
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1+fc;
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1+fc;
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=k1x-fc*2;
						fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=k1y-fc*2;
						fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=ky&0xff;
						fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=fBeganonly;
						fac2[i].facType=INT_PARAM;		fac2[i++].dl.l[LL]=kcol;
						fac2[i++].facType=VOID_PARAM;
						fac2[i++].facType=VOID_PARAM;
						fac2[i++].facType=VOID_PARAM;
						_F_setTouchArea(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
		
						touchNo[j]=fac2[0].dl.l[LL];
					} else { // ky=0またはWAKUONLYのときはタッチエリアは設定しない
						touchNo[j]=-1;
					}
					j++;
				} // touchNo=NULL=省略時はタッチエリアは設定しない(描画のみ)
			} // if (ky!=0)
			if (disps!=NULL) {
				disps+=operationStatus.sz_str; // 次の文字列先頭へ
			}
			k++;
			sx1+=(k1x+dx);
		}
		sy1+=(k1y+dy);
	}
	fac[0].dl.l[LL]=j;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// タッチキーを消す
// 表示は現在のグラフィックページに対して行う＝グラフィック表示の設定が必要
// keys()とtouchNo()の数が合わないとエラーが発生する
// int resetTouchKeys(sx;int,sy;int,xc;int,yc;int,k1x;int,k1y;int,keys()[,touchNo();int][,dx;int][dy;int])
static RET_FUNC _F_resetTouchKeys(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	double  sx=fac[i++].dl.d;
	double  sy=fac[i++].dl.d;
	int  xc=fac[i++].dl.l[LL];
	int  yc=fac[i++].dl.l[LL];
	double k1x=(double)fac[i++].dl.l[LL]; // 以下の処理の都合でdoubleで保持
	double k1y=(double)fac[i++].dl.l[LL];
	nslog(@"sx,sy=%f,%f",sx,sy);
	nslog(@"xc,yc=%d,%d",xc,yc);
	nslog(@"k1x,k1y=%f,%f",k1x,k1y);
	
	SWord   size1Keys;
	uwYouso yousoKeys;
	int *keys=(int *)getDim1FromFAC(fac,i++,&size1Keys,&yousoKeys);
	if (keys==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"keys:1要素サイズ=%d,要素数=%d",size1Keys,yousoKeys);
	
	SWord   size1TouchNo;
	uwYouso yousoTouchNo;
	int *touchNo=NULL;
	if (fac[i].facType!=VOID_PARAM) {
		touchNo=(int *)getDim1FromFAC(fac,i,&size1TouchNo,&yousoTouchNo);
		if (touchNo==NULL) { // 1次元でない
			return (RET_FUNC_ERR);
		}
		nslog(@"touchNo:1要素サイズ=%d,要素数=%d",size1TouchNo,yousoTouchNo);
		if (yousoTouchNo<yousoKeys) {
			// 必要な要素数が足りない
			setExternalFuncErrmes("配列の要素数が足りません","Array's elements are not enough.");
			return (RET_FUNC_ERR);
		}
	}
	i++;
	
	// v3.50
	int dx=0,dy=0;
	if (fac[i].facType!=VOID_PARAM) {
		dx=fac[i].dl.l[LL];
		if (dx<0) dx=0;
		if (dx>=k1x) dx=k1x;
	}
	i++;
	if (fac[i].facType!=VOID_PARAM) {
		dy=fac[i].dl.l[LL];
		if (dy<0) dy=0;
		if (dy>=k1y) dy=k1y;
	}
	i++;
	nslog(@"dx=%d,dy=%d",dx,dy);
	
	FAC fac2[10]; // 余裕を持って確保；スタック上だから問題なし
	
	double sx1,sy1;
	int k=0;
	sy1=sy;
	for (int yy=0;yy<yc;yy++) {
		sx1=sx;
		for (int xx=0;xx<xc;xx++) {
			int ky=keys[k];
			nslog(@"yy=%d,xx=%d,ky=$%04x",yy,xx,ky);
			if (ky!=0) {
				// 下消去
				i=0;
				fac2[i  ].facType=INT_PARAM; 	fac2[i++].dl.l[LL]=0x000000ff;
				fac2[i++].facType=VOID_PARAM;
				fac2[i++].facType=VOID_PARAM;
				fac2[i++].facType=VOID_PARAM;
				_F_gColor(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
				
				// アンチエイリアス対応のため、一回り大きく消す
				i=0;
				fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1-1;
				fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1-1;
				fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sx1+k1x+1;
				fac2[i].facType=FLOAT_PARAM;	fac2[i++].dl.d=sy1+k1y+1;
				fac2[i++].facType=VOID_PARAM;
				_F_fill(i,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
				
				if (touchNo!=NULL) {
					fac2[0].facType =INT_PARAM;
					int no=*touchNo++;
					if (no>=0) {
						fac2[0].dl.l[LL]=no;
						nslog(@"k=%d : %d",k,no);
						_F_removeTouchArea(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
					} // <0 : ここは描画のみなので開放も不要
				}
			} // if (ky!=0)
			k++;
			sx1+=(k1x+dx);
		}
		sy1+=(k1y+dy);
	}
	fac[0].dl.l[LL]=k; // でもリターン値はなし
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// 表示は消さない全タッチエリア開放
// resetAllTouchKeys(touchNo();int,cnt;int)
static RET_FUNC _F_resetAllTouchKeys(SWord numFAC,FAC fac[])
{
	printFunc();

	int i=0;
	
	SWord   size1;
	uwYouso youso;
	int *touchNo=(int *)getDim1FromFAC(fac,i++,&size1,&youso);
	if (touchNo==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	nslog(@"touchNo:1要素サイズ=%d,要素数=%d",size1,youso);
	
	int cnt=(int)fac[i++].dl.l[LL];
	nslog(@"キー数:%d",cnt);
	
	if (youso<cnt) {
		// 必要な要素数が足りない
		setExternalFuncErrmes("配列の要素数が足りません","Array's elements are not enough.");
		return (RET_FUNC_ERR);
	}

	for (int j=0;j<cnt;j++) {
		FAC fac2[2];
		fac2[0].facType =INT_PARAM;
		int no=*touchNo++;
		if (no>=0) {
			fac2[0].dl.l[LL]=no;
			nslog(@"j=%d : %d",j,no);
			_F_removeTouchArea(1,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
		} // <0 : ここは描画のみなので開放も不要
	}
	
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	
	return (RET_FUNC_OK); // OK
}

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

// 対応しているか調べる
static int checkCopatibleSub(int devType)
{
	NSString *dev=getDeviceModelName();
	// iPad
	// iPod touch ?
	// 01234567890
	// iPhone 1〜6
	// iPhone 6 Plus
	NSLog(@"device=%@",dev);

	if ((devType & COMPATIBLE_IPAD) && [dev hasPrefix:@"iPad"]) {
		NSLog(@"iPad ok");
		return (YES);
	}
	if ((devType & COMPATIBLE_IPODTOUCH4) && [dev hasPrefix:@"iPod touch 4"]) {
		NSLog(@"iPod touch 4 ok");
		return (YES);
	}
	if ((devType & COMPATIBLE_IPODTOUCH5) && [dev hasPrefix:@"iPod touch 5"]) {
		NSLog(@"iPod touch 5 ok");
		return (YES);
	}
	if ((devType & COMPATIBLE_IPODTOUCH6) && [dev hasPrefix:@"iPod touch 6"]) {
		NSLog(@"iPod touch 6 ok");
		return (YES);
	}
	if ([dev hasPrefix:@"iPhone"]) {
		// iPhone
		unichar c=[dev characterAtIndex:7];
		if ((devType & COMPATIBLE_IPHONE4) && c=='4')  {
			NSLog(@"iPhone 4 ok");
			return (YES);
		}
		if ((devType & COMPATIBLE_IPHONE5) && c=='5')  {
			NSLog(@"iPhone 5 ok");
			return (YES);
		}
		unichar	cc=[dev characterAtIndex:9];
		if ((devType & COMPATIBLE_IPHONE6PLUS) && c=='6' && cc=='P')  {
			NSLog(@"iPhone 6 Plus ok");
			return (YES);
		}
		if ((devType & COMPATIBLE_IPHONE6)     && c=='6' && cc!='P')  {
			NSLog(@"iPhone 6 ok");
			return (YES);
		}
	}
	NSLog(@"該当設定なし");
	return (NO);
}

// 指定されたデバイスタイプを文字列にする
static NSString *compatibleDeviceName(int devType)
{
	NSMutableString *mes=[[NSMutableString alloc]init];
	BOOL fadd=NO;
	if (devType&COMPATIBLE_IPAD) {
		[mes appendString:@"iPad"];
		fadd=YES;
	}
	
	// 同系統のデバイスタイプを省略しながら文字列にする
	NSString *baseName=[NSString stringWithFormat:@"%@iPod touch",fadd? @",":@""];
	if (devType&COMPATIBLE_IPODTOUCH4) {
		[mes appendFormat:@"%@4",baseName];
		baseName=@"/";
		fadd=YES;
	}
	if (devType&COMPATIBLE_IPODTOUCH5) {
		[mes appendFormat:@"%@5",baseName];
		baseName=@"/";
		fadd=YES;
	}
	if (devType&COMPATIBLE_IPODTOUCH6) {
		[mes appendFormat:@"%@6",baseName];
		fadd=YES;
	}

	baseName=[NSString stringWithFormat:@"%@iPhone",fadd? @",":@""];
	if (devType&COMPATIBLE_IPHONE4) {
		[mes appendFormat:@"%@4",baseName];
		baseName=@"/";
	}
	if (devType&COMPATIBLE_IPHONE5) {
		[mes appendFormat:@"%@5",baseName];
		baseName=@"/";
	}
	if (devType&COMPATIBLE_IPHONE6) {
		[mes appendFormat:@"%@6",baseName];
		baseName=@"/";
	}
	if (devType&COMPATIBLE_IPHONE6PLUS) {
		[mes appendFormat:@"%@6 Plus",baseName];
	}
	
	return (NSString *)mes;
}

// int checkCompatible(deviceType;int[,fdisplay;int])
// deviceType:対応している機種
// fdisplay:YES=表示を出す
static RET_FUNC _F_checkCompatible(SWord numFAC,FAC fac[])
{
	printFunc();
	int i=0;
	int devType=fac[i++].dl.l[LL];
	if (devType==0) devType=COMPATIBLE_ALL;
	nslog(@"devType=$%x",devType);

	BOOL fdisplay=YES;
	if (fac[i].facType!=VOID_PARAM) {
		fdisplay=basic2cYESNO(fac[i].dl.l[LL]);
	}
	nslog(@"fdisplay=%d",fdisplay);
	
	int ok=checkCopatibleSub(devType);
	if (fdisplay) {
		if (!ok) {
			nslog(@"対応していない");
			nslog(@"tconsole=%@",tconsole);
			NSString *message=[NSString stringWithFormat:NSLocalStr(@"COMPATIBLE_DEVICE"),compatibleDeviceName(devType)];
			[tconsole selectMenu:NSLocalStr(@"NOT_COMPATIBLE") menu:@[NSLocalStr(@"CONFIRM")] message:message];
			[tconsole waitUntilSelectEnd]; // selectMenu2も終了待ちはwaitUntilSelectEnd
		}
	}
	fac[0].dl.l[LL]=c2basicYESNO(ok);
	fac[0].facType=FACTYPE_RETURN;
	
	return (RET_FUNC_OK); // OK
}

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

// 関数名テーブル(トークンテーブル)
static const char *iOSX68Tokens[]={
	// 互換関数
	"setgPalet16X68",
	"getgPalet16X68",
	"gColor16X68",
	"gColorX68",
	"tColorX68",
	"tColorPaletX68",
	"vpageX68",
	"apageX68",
	"homeX68",
	//
	"pset16X68",
	"fill16X68",
	"line16X68",
	"box16X68",
	"symbol16X68",
	"circle16X68",
	//
	"psetX68",
	"fillX68",
	"lineX68",
	"boxX68",
	"symbolX68",
	"circleX68",
	//
	"rgbX68",
	"hsvX68",
	"rgbX68X68",
	"hsvX68X68",
	"randX68",
	"contrastX68",
	"bg_getX68",
	"bg_putX68",
	"bg_fillX68",
	"sp_colorX68",
	"sp_setX68",
	// 便利関数
	"localizedString",
	"hitKey",
	"getch",
	"vwait",
	"srand2",
	"rand2",
	"bell",
	"ptrn16X68toiOS",
	"ptrn8to16",
	"WaitPCM",
	"PCMplay",
	"paint16X68b",
	"circle16X68b",
	"paintX68b",
	"circleX68b",
	"x68Color2iOSColor",
	"x68256Color2iOSColor",	// v2.6
	"x6816Color2iOSColor",
	"deg2rad",
	"rad2deg",
	//
	"setTouchKeys",			// v3.20
	"resetTouchKeys",		// v3.20
	"resetAllTouchKeys",	// v3.20
	"checkCompatible",		// v3.20
	// バージョン
	"versionXBiOSX68$",
	// end of table
	NULL,
};
				
// 実行アドレステーブル
static FUNC_EXEC iOSX68FuncExec[]={
	// Cの標準関数名と重複させないよう_F_を付ける
	{_F_setgPalet16X68},
	{_F_getgPalet16X68},
	{_F_gColor16X68},
	{_F_gColorX68},
	{_F_tColorX68},
	{_F_tColorPaletX68},
	{_F_vpageX68},
	{_F_apageX68},
	{_F_homeX68},
//
	{_F_pset16X68},
	{_F_fill16X68},
	{_F_line16X68},
	{_F_box16X68},
	{_F_symbol16X68},
	{_F_circle16X68},
	//
	{_F_psetX68},
	{_F_fillX68},
	{_F_lineX68},
	{_F_boxX68},
	{_F_symbolX68},
	{_F_circleX68},
//
	{_F_rgbX68},
	{_F_hsvX68},
	{_F_rgbX68X68},
	{_F_hsvX68X68},
	{_F_randX68},
	{_F_contrastX68},
	{_F_bg_getX68},
	{_F_bg_putX68},
	{_F_bg_fillX68},
	{_F_sp_colorX68},
	{_F_sp_setX68},
	// 便利関数
	{_F_localizedString},
	{_F_hitKey},
	{_F_getch},
	{_F_vwait},
	{_F_srand2},
	{_F_rand2},
	{_F_bell},
	{_F_ptrn16X68toiOS},
	{_F_ptrn8to16},
	{_F_WaitPCM},
	{_F_PCMplay},
	{_F_paint16X68b},
	{_F_circle16X68b},
	{_F_paintX68b},
	{_F_circleX68b},
	{_F_x68Color2iOSColor},
	{_F_x68256Color2iOSColor},	// v2.6
	{_F_x6816Color2iOSColor},
	{_F_deg2rad},
	{_F_rad2deg},
	//
	{_F_setTouchKeys},
	{_F_resetTouchKeys},
	{_F_resetAllTouchKeys},
	{_F_checkCompatible},
	// バージョン
	{_F_version},
	// end of table
	{NULL},
};

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

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

static const uwPARAMTYPE p_setgPalet16X68[]={
	INT_VAL,
	INT_VAL,
	VOID_RET,
};
#define p_PCMplay	p_setgPalet16X68

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

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

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

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

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

static const uwPARAMTYPE p_gColor16X68[]={
	INT_VAL,
	VOID_RET,
};
#define p_gColorX68	p_gColor16X68
#define	p_vwait		p_gColor16X68
#define	p_bell		p_gColor16X68

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

static const uwPARAMTYPE p_line16X68[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_OMT,
	VOID_RET,
};
#define p_lineX68	p_line16X68

static const uwPARAMTYPE p_fill16X68[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	VOID_RET,
};
#define p_fillX68	p_fill16X68

static const uwPARAMTYPE p_box16X68[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_OMT,
	VOID_RET,
};
#define p_boxX68	p_box16X68

static const uwPARAMTYPE p_symbol16X68[]={
	INT_VAL,
	INT_VAL,
	STR_VAL,
	FLOAT_VAL,
	INT_VAL,
	STR_VAL,
	INT_OMT,
	VOID_RET,
};
#define p_symbolX68	p_symbol16X68

static const uwPARAMTYPE p_circle16X68[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_OMT,	// st
	INT_OMT,	// ed
	INT_OMT,	// hv:扁平率
	VOID_RET,
};
#define p_circleX68	p_circle16X68

static const uwPARAMTYPE p_paint16X68b[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	VOID_RET,
};
#define p_pset16X68	p_paint16X68b
#define p_psetX68	p_paint16X68b
#define p_paintX68b	p_paint16X68b
#define p_homeX68	p_paint16X68b

static const uwPARAMTYPE p_circle16X68b[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_VAL,
	VOID_RET,
};
#define p_circleX68b	p_circle16X68b

static const uwPARAMTYPE p_rgbX68[]={
	INT_VAL,
	INT_VAL,
	INT_VAL,
	INT_RET,
};
#define p_hsvX68	p_rgbX68
#define p_bg_getX68	p_rgbX68
#define p_rgbX68X68	p_rgbX68
#define p_hsvX68X68	p_rgbX68


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

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

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

static const uwPARAMTYPE p_srand2[]={
	VOID_RET,
};

static const uwPARAMTYPE p_localizedString[]={
	STR_VAL,
	STR_VAL,
	STR_RET
};

static const uwPARAMTYPE p_hitKey[]={
	INT_OMT,
	STR_OMT,
	STR_OMT,
	VOID_RET
};

static const uwPARAMTYPE p_getch[]={
	INT_RET
};

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

static const uwPARAMTYPE p_ptrn16X68toiOS[]={
	INT_VAL,
	ARRAY1_CHAR,
	ARRAY1_INT,
	INT_OMT,
	INT_OMT,
	VOID_RET
};

static const uwPARAMTYPE p_ptrn8to16[]={
	ARRAY1_CHAR,
	ARRAY1_CHAR,
	VOID_RET
};

static const uwPARAMTYPE p_x68Color2iOSColor[]={
	INT_VAL,
	INT_VP|PARAM_OMIT,	// v2.5
	INT_VP|PARAM_OMIT,	// v2.5
	INT_VP|PARAM_OMIT,	// v2.5
	INT_VP|PARAM_OMIT,	// v2.5
	INT_RET,
};
#define p_x68256Color2iOSColor	p_x68Color2iOSColor
#define p_x6816Color2iOSColor	p_x68Color2iOSColor

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

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

static const uwPARAMTYPE p_deg2rad[]={
	FLOAT_VAL,
	FLOAT_RET
};
#define p_rad2deg	p_deg2rad

static const uwPARAMTYPE p_setTouchKeys[]={
	FLOAT_VAL,	// sx
	FLOAT_VAL,	// sy
	INT_VAL,	// xc
	INT_VAL,	// yc
	INT_VAL,	// k1x
	INT_VAL,	// k1y
	ARRAY1_INT,	// keys()
	ARRAY1_STR|PARAM_OMIT,	// disps()
	STR_OMT,	// fnt
	ARRAY1_INT|PARAM_OMIT,	// touchNo()
	INT_OMT,	// dx	v3.50
	INT_OMT,	// dy	v3.50
	INT_RET
};

static const uwPARAMTYPE p_resetTouchKeys[]={
	FLOAT_VAL,	// sx
	FLOAT_VAL,	// sy
	INT_VAL,	// xc
	INT_VAL,	// yc
	INT_VAL,	// k1x
	INT_VAL,	// k1y
	ARRAY1_INT,	// keys()
	ARRAY1_INT|PARAM_OMIT,	// touchNo()
	INT_OMT,	// dx	v3.50
	INT_OMT,	// dy	v3.50
	VOID_RET
};

static const uwPARAMTYPE p_resetAllTouchKeys[]={
	ARRAY1_INT,	// touchNo()
	INT_VAL,	// cnt
	VOID_RET
};

static const uwPARAMTYPE p_checkCompatible[]={
	INT_VAL,	// deviceType
	INT_OMT,	// fdisplay
	INT_RET
};

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

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

static
const
uwPARAMTYPE *iOSX68Params[]={
	p_setgPalet16X68,
	p_getgPalet16X68,
	p_gColor16X68,
	p_gColorX68,
	p_tColorX68,
	p_tColorPaletX68,
	p_vpageX68,
	p_apageX68,
	p_homeX68,
	//
	p_pset16X68,
	p_fill16X68,
	p_line16X68,
	p_box16X68,
	p_symbol16X68,
	p_circle16X68,
	//
	p_psetX68,
	p_fillX68,
	p_lineX68,
	p_boxX68,
	p_symbolX68,
	p_circleX68,
	//
	p_rgbX68,
	p_hsvX68,
	p_rgbX68X68,
	p_hsvX68X68,
	p_randX68,
	p_contrastX68,
	p_bg_getX68,
	p_bg_putX68,
	p_bg_fillX68,
	p_sp_colorX68,
	p_sp_setX68,
	//
	p_localizedString,
	p_hitKey,
	p_getch,
	p_vwait,
	p_srand2,
	p_rand2,
	p_bell,
	p_ptrn16X68toiOS,
	p_ptrn8to16,
	p_WaitPCM,
	p_PCMplay,
	p_paint16X68b,
	p_circle16X68b,
	p_paintX68b,
	p_circleX68b,
	p_x68Color2iOSColor,
	p_x68256Color2iOSColor,	// v2.6
	p_x6816Color2iOSColor,
	p_deg2rad,
	p_rad2deg,
	//
	p_setTouchKeys,
	p_resetTouchKeys,
	p_resetAllTouchKeys,
	p_checkCompatible,
	// バージョン
	p_version	,
	// end of table
	NULL,
};

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

// この中の関数の初期化処理

static void _Finit(void)
{
	printFunc();
}

static void _Frun(void)
{
	printFunc();
	// 実行前には一旦戻す
	for (int i=0;i<SZ_X68GPALET;i++) {
		x68gPalets16[i]=x68gPalets160[i];
	}
	for (int i=0;i<SZ_X68TPALET;i++) {
		x68tPalets[i]=x68tPalets0[i];
	}
	// _Finitでは未確定なのでこちらで代入
	RunViewController *runView=xb_getRunView();
	tconsole=[runView getConsole:TCONSOLE];
}

// この中の関数の終了処理
static void _Fend(void)
{
	printFunc();
}

// インフォメーションテーブル
const
INFORMATION_TABLE	InfoX68Funcs={
	#ifdef FUNC_DEBUG
	"iOS X68 Compatible functions",
	#endif
	_Finit,		// Finit
	_Frun,		// Frun
	_Fend,		// Fend
	returnOnly,	// Fexit
	returnOnly,	// Fbreak
	NULL,		// FctrlD;未使用
	NULL,		// 予約1
	NULL,		// 予約2
	//
	iOSX68Tokens,
	iOSX68Params,
	iOSX68FuncExec
};

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