/*
 *	clipact.c
 *
 *	アクターオブジェクト
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2016 Naoyuki Sawa
 *
 *	* Sun Feb 07 21:14:38 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	- 有限状態機械とプロパティヘッダとアプリケーション定義のデータをまとめたものを、アクターオブジェクトと呼ぶ事にしました。
 *        当モジュールは、アクターオブジェクトを、ツリー構造で管理する機能を提供します。
 *	- 2016/02/07現在の所、最低限の機能だけを実装しました。
 *	  今後、アクターオブジェクトを検索する機能を追加したり、座標プロパティや当たり判定プロパティを標準化したりする予定です。
 *	* Fri Feb 26 21:51:12 JST 2016 Naoyuki Sawa
 *	- ActObj_ApplyTrans_l(),ActObj_ApplyTrans_a(),ActObj_ApplyTrans_v()を追加しました。
 *	  ActObj_ApplyTransToChildren_l(),ActObj_ApplyTransToChildren_a(),ActObj_ApplyTransToChildren_v()を追加しました。
 *	  ActObj_ApplyTransToTree_l(),ActObj_ApplyTransToTree_a(),ActObj_ApplyTransToTree_v()を追加しました。
 *	  詳細は、clipfsm.h の同日のコメントを参照して下さい。
 *	* Sat Feb 27 21:21:24 JST 2016 Naoyuki Sawa
 *	- FsmObj_Init()の引数で有権状態機械の初期状態を明示しなくなった事に伴い、ActObj_New()からも初期状態を指定する引数を削除しました。
 *	  詳細は、clipfsm.h の同日のコメントを参照して下さい。
 *	- ActObj_GetParent()を追加しました。
 *	  この関数を追加した理由は、clipact.c の実装個所のコメントを参照して下さい。
 *	* Sat Apr 02 23:34:06 JST 2016 Naoyuki Sawa
 *	- ARRAY_SIZE()マクロの変更に伴い、VC++6.0でintとunsignedの比較に対する警告が厳密に出るようになったので、警告が出ないように明示的なキャストを追加しました。
 *	  動作自体はこれまでと変わりません。
 *	  詳細はclipmisc.hの同日のコメントを参照して下さい。
 *	* Fri Jul 08 21:19:03 JST 2016 Naoyuki Sawa
 *	- clipfsm.cモジュールの、FsmObj_ApplyTrans_l(),FsmObj_ApplyTrans_a(),FsmObj_ApplyTrans_v()に対して行ったのと同じ変更を、
 *	  ActObj_ApplyTrans_l(),ActObj_ApplyTrans_a(),ActObj_ApplyTrans_v()、及び、
 *	  ActObj_ApplyTransToChildren_l(),ActObj_ApplyTransToChildren_a(),ActObj_ApplyTransToChildren_v()、及び、
 *	  ActObj_ApplyTransToTree_l(),ActObj_ApplyTransToTree_a(),ActObj_ApplyTransToTree_v()にも適用しました。
 *	  詳細は、clipfsm.cモジュールの、同日のコメントを参照して下さい。
 *	- 余談ですが、これまで、上記の関数のアセンブラ版の実装は、スタック操作のバグが有った事に気付きました。
 *	  今回の変更に合わせて、スタック操作のバグも修正しました。
 *	* Sat Aug 27 12:10:07 JST 2016 Naoyuki Sawa
 *	- gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
 *	  gnode.hの、同日のコメントも参照して下さい。
 *	- gnode.hの「G_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張」で行ったのと同じ検証を、当モジュール経由でも検証しました。
 *	  今回の変更が、正しく反映されている事を確認しました。
 *	  ------------------------------------------------------------------------------
 *	  ■テストプログラム
 *	  (app.c)
 *	  │void test() {
 *	  │  ST_ActObj *root, *node1, *node2, *node11, *node12, *node21, *node22;
 *	  │  root = ActObj_New(NULL, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │  *(const char**)ActObj_GetData(root) = "root";
 *	  │    node1 = ActObj_New(root, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │    *(const char**)ActObj_GetData(node1) = "node1";
 *	  │      node11 = ActObj_New(node1, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node11) = "node11";
 *	  │      node12 = ActObj_New(node1, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node12) = "node12";
 *	  │    node2 = ActObj_New(root, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │    *(const char**)ActObj_GetData(node2) = "node2";
 *	  │      node21 = ActObj_New(node2, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node21) = "node21";
 *	  │      node22 = ActObj_New(node2, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node22) = "node22";
 *	  │  ActObj_ApplyTransToTree_l(root, FsmTrans_Exec, 1, 0);
 *	  │  ActObj_Free(root);
 *	  │}
 *	  (FsmMap.txt)
 *	  │Test Run
 *	  │     Run
 *	  │         Exec {`
 *	  │                ST_ActObj* pActObj = ActObj_FromFsmObj(pFsmObj);
 *	  │                const char* name = *(const char**)ActObj_GetData(pActObj);
 *	  │                ST_FsmObj_Arg* pArg = pParam;
 *	  │                int nest = (int)pArg->argv[0];
 *	  │                printf("%*s%s\n", nest, "", name);
 *	  │                if(!strcmp(name, "node1")) {
 *	  │                  if(nest <= 1) {
 *	  │                    ActObj_ApplyTransToTree_l(ActObj_GetParent(pActObj), FsmTrans_Exec, 1, nest + 1);
 *	  │                    if(nest == 1) {
 *	  │                      ActObj_Free(pActObj);
 *	  │                      printf("%*s%s自身を削除しました。\n", nest, "", name);
 *	  │                    }
 *	  │                  }
 *	  │                }
 *	  │              `}
 *	  │     end
 *	  │end
 *	  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 *	  □結果
 *	  │root			←G_PRE_ORDERの順序で、親が先にトラバースされている事を確認しました。
 *	  │node1
 *	  │ root
 *	  │ node1
 *	  │  root
 *	  │  node1
 *	  │  node11
 *	  │  node12
 *	  │  node2
 *	  │  node21
 *	  │  node22
 *	  │ node1自身を削除しました。
 *	  │ node2			←期待通り、ここでnode11とnode12のトラバースが行われていないので、正しく動作している事が確認出来ました。
 *	  │ node21
 *	  │ node22
 *	  │node2			←期待通り、ここでnode11とnode12のトラバースが行われていないので、正しく動作している事が確認出来ました。
 *	  │node21
 *	  │node22
 *	  ------------------------------------------------------------------------------
 *	* Mon Sep 05 21:24:05 JST 2016 Naoyuki Sawa
 *	- 64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
 *	  (void*)[2]で渡すと、64ビット版では(void*)⇔(int)を変換する箇所で、コンパイラの警告が出るからです。
 *	* Sun Sep 11 21:23:51 JST 2016 Naoyuki Sawa
 *	- アクターオブジェクトに、演出シーケンサを含めました。
 *	  演出シーケンサを使用するアクターオブジェクトは、ActObj_New()の引数fnAct,nDirSeqChに0以外の値を指定して作成して下さい。
 *	  その後、各アクターオブジェクトの演出シーケンサを、ActObj_GetDirSeq()で取得して使用して下さい。
 *	  fnActからアクターオブジェクトを逆引きするには、ActObj_FromDirSeq()を使用して下さい。
 *	- ユーティリティマクロACTOBJ_FSMFUNC_PROLOGUE_BASE,ACTOBJ_FSMFUNC_EPILOGUE_BASEを追加しました。
 *	  ユーティリティマクロACTOBJ_DIRFUNC_PROLOGUE_BASE,ACTOBJ_DIRFUNC_EPILOGUE_BASEを追加しました。
 */
#include "clip.h"
/****************************************************************************
 *	基本的な関数
 ****************************************************************************/
static int GetPrpTblWords(const void* pPrpKey, int iPrpTbl) {
	//プロパティテープルの(ビット数-1)を取得する。
	int iBitLen = REG_get_value_l(pPrpKey, iPrpTbl, Prp_len, -1);
	if(iBitLen == -1) { DIE(); }
	//(ビット数-1)⇒(ビット数)に補正する。
	iBitLen++;
	//ビット数⇒ワード数に切り上げる。
	return (iBitLen + 31) >> 5;
}
/*--------------------------------------------------------------------------*/
//アクターオブジェクトを作成する。
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//ST_ActObj* ActObj_New(ST_ActObj* pParent/*NULL可*/, const void* pFsmKey/*NULL可*/, int iFsmMap, const void* pPrpKey/*NULL可*/, int iPrpTbl, int nDataBytes) {
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
ST_ActObj* ActObj_New(ST_ActObj* pParent/*NULL可*/,
  const void* pFsmKey/*NULL可*/, int iFsmMap/*(pFsmKey=NULL)ならば参照しない*/,
  const void* pPrpKey/*NULL可*/, int iPrpTbl/*(pPrpKey=NULL)ならば参照しない*/,								//┐この引数順序がST_ActObj構造体内での並びとは逆なのですが、この引数順序の方が直観的に判り易いのでこうする事にしました。
  void (*fnAct/*(nDirSeqCh=0)ならば参照しない*/)(struct _ST_DirSeq* pDirSeq, int iCh, int ActNo, int bOverFlow), int nDirSeqCh/*0可*/,	//┘ST_ActObj構造体内での並びがstDirSeq,stPrpHdrの順である理由は、アドレス計算処理の都合だけでやむを得ずそうしただけです。
  int nDataBytes/*0可*/) {
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	int nPrpTblWords, nDataWords;
	ST_ActObj* pActObj;
	//アプリケーションがpFsmKeyを指定しなかった場合は、ダミーとして、何もしないステートを持つマップを使って初期化する事にしました。
	if(!pFsmKey) {
		//-------------------------------------
		//□FsmMap.txt
		//│Map0 State0
		//│     State0
		//│            default State0
		//│     end
		//│end
		//- - - - - - - - - - - - - - - - - - -
		//□RegFsmMap.txt
		//│FsmMap
		//│       Map0
		//│            init = State0
		//│            State0
		//│                   default
		//│                           Fsm_State(3N+2) = State0
		//│                   end
		//│            end
		//│       end
		//│FsmMap
		//- - - - - - - - - - - - - - - - - - -
		static const uint8_t TBL_FsmMap_dummy[]={
		0x80,
		0x00,0x00,
		HIBYTE(           0x0000),LOBYTE(           0x0000), 0x00,0x00,0x00,	//Map0
		0xC0,
		0x00,0x00,
		HIBYTE(           0x8000),LOBYTE(           0x8000), 0x00,0x00,0x07,	//State0
		0x00,0x00,
		HIBYTE(   Fsm_State_init),LOBYTE(   Fsm_State_init), 0x00,0x00,0x00,	//init = State0
		0x80,
		0x00,0x00,
		HIBYTE(Fsm_Trans_default),LOBYTE(Fsm_Trans_default), 0x00,0x00,0x00,	//default
		0x40,
		0x00,0x00,
		/*Fsm_State*/HIBYTE(0x02),/*Fsm_State*/LOBYTE(0x02), 0x00,0x00,0x00,	//Fsm_State(3N+2) = State0
		};
		//-------------------------------------
		pFsmKey = TBL_FsmMap_dummy;
		iFsmMap = 0;	//Map0
	}
	//アプリケーションがpPrpKeyを指定しなかった場合は、ダミーとして、空のテーブルを使って初期化する事にしました。
	if(!pPrpKey) {
		//dPrpTblC.exeを使ってプロパティテーブルスクリプトをコンパイルすると、空のテーブルは作成出来ないので、以下のデータは手で作成しました。
		//dPrpTblC.exeを使って作成する事は出来ないデータですが、プロパティテーブルのレジストリデータ構造としては有効です。
		//-------------------------------------
		//□PrpTbl.txt
		//│Table0
		//│    (empty)
		//│end
		//- - - - - - - - - - - - - - - - - - -
		//□RegPrpTbl.txt
		//│PrpTbl
		//│    Table0
		//│        len = 1-1	//本当は(len=0-1)としたいがレジストリ構造上出来ない。1bit(切り上げて1word)分無駄に確保してしまうが動作上は問題無い。
		//│    end
		//│end
		//- - - - - - - - - - - - - - - - - - -
		static const uint8_t TBL_PrpTbl_dummy[]={
		0x80,
		0x00,0x00,
		HIBYTE(           0x0000),LOBYTE(           0x0000), 0x00,0x00,0x00,	//Table0
		0x40,
		0x00,0x00,
		HIBYTE(          Prp_len),LOBYTE(          Prp_len), 0x00,0x00,0x00,	//len = 1-1
		};
		//-------------------------------------
		pPrpKey = TBL_PrpTbl_dummy;
		iPrpTbl = 0;	//Table0
	}
	//プロパティテープルのワード数を求める。
	nPrpTblWords = GetPrpTblWords(pPrpKey, iPrpTbl);
	//データのワード数を求める。
	nDataWords = (nDataBytes + 3) >> 2;
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	//アクターオブジェクトのメモリを確保する。
//	pActObj = calloc(sizeof(ST_ActObj) + sizeof(int) * (nPrpTblWords + nDataWords), 1);
//	if(!pActObj) { DIE(); }
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	//アクターオブジェクトのメモリを確保する。		//	typedef struct _ST_ActObj {
	pActObj = calloc(sizeof(ST_ActObj) +			//		GNode*		node;				//+0
	                 sizeof(ST_FsmObj) +			//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
	                 sizeof(ST_DirSeq) +			//	    //	ST_DirSeq	stDirSeq;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)
	                (sizeof(ST_DirSeqCh) * nDirSeqCh) +	//	    //	ST_DirSeqCh	_TBL_DirSeqCh[nDirSeqCh];	//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)
	                 sizeof(ST_PrpHdr) +			//	    //	ST_PrpHdr	stPrpHdr;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)
	                (sizeof(int) * nPrpTblWords) +		//	    //	int		_aPrpTbl[nPrpTblWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)
	                (sizeof(int) * nDataWords), 1);		//	    //	int		_aData[nDataWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)+(sizeof(int)*nPrpTblWords)
	if(!pActObj) { DIE(); }					//	} ST_ActObj;						//=sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)+(sizeof(int)*nPrpTblWords)+(sizeof(int)*nDataWords)
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	//親オブジェクトが指定されていたら…
	if(pParent) {
		//子ノードを作成する。
		pActObj->node = g_node_append_data(pParent->node, pActObj);
	//親オブジェクトが指定されていなければ…
	} else {
		//ルートノードを作成する。
		pActObj->node = g_node_new(pActObj);
	}
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	//プロパティヘッダを初期化する。
//	PrpHdr_init(&pActObj->stPrpHdr, pPrpKey, iPrpTbl);
//	//有限状態機械を初期化する。
//	// - この処理を一番最後に行う必要が有る事に注意せよ。
//	//   有限状態機械のstart関数の中でアクターオブジェクトを操作する可能性が有るので、その前にアクターオブジェクトの初期化が完了していなければいけない。
//	FsmObj_Init(&pActObj->stFsmObj, pFsmKey, iFsmMap);
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	//演出シーケンサを初期化する。					//┐
	DirSeq_Init(ActObj_GetDirSeq(pActObj), fnAct, nDirSeqCh);	//│この初期化順序は必須です。
	//プロパティヘッダを初期化する。				//│ActObj_GetPrpHdr(pActObj)の処理が、stDirSeq.nChを参照しているからです。
	PrpHdr_init(ActObj_GetPrpHdr(pActObj), pPrpKey, iPrpTbl);	//┘
	//有限状態機械を初期化する。
	// - この処理を一番最後に行う必要が有る事に注意せよ。
	//   有限状態機械のstart関数の中でアクターオブジェクトを操作する可能性が有るので、その前にアクターオブジェクトの初期化が完了していなければいけない。
	FsmObj_Init(ActObj_GetFsmObj(pActObj), pFsmKey, iFsmMap);
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	//アクターオブジェクトを返す。
	return pActObj;
}
/*--------------------------------------------------------------------------*/
//このアクターオブジェクトと、子アクターオブジェクトを開放する。
void ActObj_Free(ST_ActObj* pActObj) {
	ActObj_FreeChildren(pActObj);
	g_node_destroy(pActObj->node);
	free(pActObj);
}
/*--------------------------------------------------------------------------*/
static void ActObj_Free_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
	ActObj_Free(pActObj);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトを開放する。
//このアクターオブジェクトは開放しない。
void ActObj_FreeChildren(ST_ActObj* pActObj) {
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, ActObj_Free_func, NULL);
}
/*--------------------------------------------------------------------------*/
//親オブジェクトを取得する。
//親オブジェクトが無ければ(=pFsmObjがルートノードならば)NULLを返す。
// - N-ary Treesの仕様では、親ノードにアクセスするには node->parent を直接参照するだけで良いのですが、
//   ST_ActObjの場合 (pActObj->node->parent ? pActObj->node->parent->data : NULL) と長くなってしまい、
//   アプリケーションの中に何度も書くのは煩わしいので、関数として定義する事にしました。
// - N-ary Treesの機能を使って実現出来る事は、なるべく当モジュールの関数としては実装しない方針ですが、
//   上記の理由で、これは、当モジュールの関数として実装しておく方が良いと判断しました。
ST_ActObj* ActObj_GetParent(ST_ActObj* pActObj) {
	GNode* parent = pActObj->node->parent;
	return parent ? parent->data : NULL;
}
/*--------------------------------------------------------------------------*/
//最初の子アクターオブジェクトを取得する。
//<使用例>
//│ST_ActObj_Iter Iter;
//│ST_ActObj* pChild;
//│for(pChild=ActObj_FirstChild(pActObj,&Iter);
//│    pChild;
//│    pChild=ActObj_NextSibling(&Iter)){
//│      〜  //ここでActObj_Free(pChild)を実行しても安全です。
//│}
ST_ActObj* ActObj_FirstChild(ST_ActObj* pActObj, ST_ActObj_Iter* pIter) {
	GNode* node = g_node_first_child(pActObj->node);
	pIter->pNext = node ? node->data : NULL;
	return ActObj_NextSibling(pIter);
}
/*--------------------------------------------------------------------------*/
//次の子アクターオブジェクトを取得する。
ST_ActObj* ActObj_NextSibling(ST_ActObj_Iter* pIter) {
	ST_ActObj* pActObj = pIter->pNext;
	if(pActObj) {
		GNode* node = g_node_next_sibling(pActObj->node);
		pIter->pNext = node ? node->data : NULL;
	}
	return pActObj;
}
/*--------------------------------------------------------------------------*/
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
////ST_ActObj.stFsmObjへのポインタを、ST_ActObjへのポインタに変換する。
//ST_ActObj* ActObj_FromFsmObj(ST_FsmObj* pFsmObj) {
//	return CONTAINING_RECORD(pFsmObj, ST_ActObj, stFsmObj);
//}
///*--------------------------------------------------------------------------*/
////アプリケーション定義のデータへのポインタを取得する。
//void* ActObj_GetData(ST_ActObj* pActObj) {
//	//プロパティテープルのワード数を求める。
//	int nPrpTblWords = GetPrpTblWords(pActObj->stPrpHdr.pPrpKey, pActObj->stPrpHdr.iTbl);
//	//pActObj->stPrpHdrのプロパティテーブルの後にデータが有る。
//	return (int*)(&pActObj->stPrpHdr + 1) + nPrpTblWords;
//}
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//ST_ActObjの先頭アドレスから、stFsmObjフィールドのアドレスを取得する。
ST_FsmObj* ActObj_GetFsmObj(ST_ActObj* pActObj) {
	return (ST_FsmObj*)((char*)pActObj + sizeof(ST_ActObj));		//		GNode*		node;				//+0
}
/*--------------------------------------------------------------------------*/
//stFsmObjフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。
ST_ActObj* ActObj_FromFsmObj(ST_FsmObj* pFsmObj) {
	return (ST_ActObj*)((char*)pFsmObj - sizeof(ST_ActObj));		//		GNode*		node;				//+0
}
/*--------------------------------------------------------------------------*/
//ST_ActObjの先頭アドレスから、stDirSeqフィールドのアドレスを取得する。
ST_DirSeq* ActObj_GetDirSeq(ST_ActObj* pActObj) {
	return (ST_DirSeq*)((char*)pActObj + sizeof(ST_ActObj)			//		GNode*		node;				//+0
	                                   + sizeof(ST_FsmObj));		//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
}
/*--------------------------------------------------------------------------*/
//stDirSeqフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。
ST_ActObj* ActObj_FromDirSeq(ST_DirSeq* pDirSeq) {
	return (ST_ActObj*)((char*)pDirSeq - sizeof(ST_ActObj)			//		GNode*		node;				//+0
	                                   - sizeof(ST_FsmObj));		//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
}
/*--------------------------------------------------------------------------*/
//ST_ActObjの先頭アドレスから、stPrpHdrフィールドのアドレスを取得する。
ST_PrpHdr* ActObj_GetPrpHdr(ST_ActObj* pActObj) {
	ST_DirSeq* pDirSeq = ActObj_GetDirSeq(pActObj);				//	    //	ST_DirSeq	stDirSeq;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)
	return (ST_PrpHdr*)&pDirSeq->TBL_DirSeqCh[pDirSeq->nCh];		//	    //	ST_DirSeqCh	_TBL_DirSeqCh[nDirSeqCh];	//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)
}
/*--------------------------------------------------------------------------*/
//ST_ActObjの先頭アドレスから、アプリケーション定義のデータのアドレスを取得する。
void* ActObj_GetData(ST_ActObj* pActObj) {
	//プロパティヘッダのアドレスを取得する。
	ST_PrpHdr* pPrpHdr = ActObj_GetPrpHdr(pActObj);
	//プロパティテープルのワード数を求める。
	int nPrpTblWords = GetPrpTblWords(pPrpHdr->pPrpKey, pPrpHdr->iTbl);
	//pActObj->stPrpHdrのプロパティテーブルの後にデータが有る。
	return (int*)(pPrpHdr + 1) + nPrpTblWords;
}
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
/*--------------------------------------------------------------------------*/
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
typedef struct _ST_ActObj_ApplyTrans_func_Param {
	int	iFsmTrans;
	void*	pParam;
} ST_ActObj_ApplyTrans_func_Param;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
static int ActObj_ApplyTrans_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
//	void** d = data;		//┐
//	int iFsmTrans = (int)d[0];	//├←ActObj_ApplyTransToChildren(),ActObj_ApplyTransToTree()
//	void* pParam  =      d[1];	//┘
//	ActObj_ApplyTrans(pActObj, iFsmTrans, pParam);
//↓2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	ST_ActObj_ApplyTrans_func_Param* p = data;	//←ActObj_ApplyTransToChildren(),ActObj_ApplyTransToTree()
	ActObj_ApplyTrans(pActObj, p->iFsmTrans, p->pParam);
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	return 0;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクトの有限状態機械に、遷移を適用する。
void ActObj_ApplyTrans(ST_ActObj* pActObj, int iFsmTrans, void* pParam) {
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	FsmObj_ApplyTrans(&pActObj->stFsmObj, iFsmTrans, pParam);
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	FsmObj_ApplyTrans(ActObj_GetFsmObj(pActObj), iFsmTrans, pParam);
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトの有限状態機械に、遷移を適用する。
//このアクターオブジェクト,及び,直接の子以外の子孫アクターオブジェクトの有限状態機械には、遷移を適用しない。
void ActObj_ApplyTransToChildren(ST_ActObj* pActObj, int iFsmTrans, void* pParam) {
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
//	void* d[2];			//┐
//	d[0] = (void*)iFsmTrans;	//├→ActObj_ApplyTrans_func()
//	d[1] =        pParam;		//┘
//	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_ApplyTrans_func, d);
//↓2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	ST_ActObj_ApplyTrans_func_Param p;	//┐
	p.iFsmTrans = iFsmTrans;		//├→ActObj_ApplyTrans_func()
	p.pParam    = pParam;			//┘
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_ApplyTrans_func, &p);
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクト,及び,子孫アクターオブジェクトの有限状態機械に、遷移を適用する。
void ActObj_ApplyTransToTree(ST_ActObj* pActObj, int iFsmTrans, void* pParam) {
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
//	void* d[2];			//┐
//	d[0] = (void*)iFsmTrans;	//├→ActObj_ApplyTrans_func()
//	d[1] =        pParam;		//┘
//  //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//  #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
//  //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, d);
//	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
//	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
//  //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//  #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
//	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, d);
//	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
//	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
//  #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
//  //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//↓2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	ST_ActObj_ApplyTrans_func_Param p;	//┐
	p.iFsmTrans = iFsmTrans;		//├→ActObj_ApplyTrans_func()
	p.pParam    = pParam;			//┘
    //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
    #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
    //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, &p);
	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
    //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
    #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, &p);
	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
    #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
    //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
}
/*--------------------------------------------------------------------------*/
//{{2016/09/11追加:アクターオブジェクトに、演出シーケンサを含めました。
static int ActObj_ExecDirSeq_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
	ActObj_ExecDirSeq(pActObj);
	return 0;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクトの演出シーケンサを実行する。
void ActObj_ExecDirSeq(ST_ActObj* pActObj) {
	DirSeq_Exec(ActObj_GetDirSeq(pActObj));
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトの演出シーケンサを実行する。
//このアクターオブジェクト,及び,直接の子以外の子孫アクターオブジェクトの演出シーケンサは実行しない。
void ActObj_ExecDirSeqToChildren(ST_ActObj* pActObj) {
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_ExecDirSeq_func, NULL);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクト,及び,子孫アクターオブジェクトの演出シーケンサを実行する。
void ActObj_ExecDirSeqToTree(ST_ActObj* pActObj) {
    #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ExecDirSeq_func, NULL);
	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
    #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ExecDirSeq_func, NULL);
	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
    #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
}
//}}2016/09/11追加:アクターオブジェクトに、演出シーケンサを含めました。
/****************************************************************************
 *	ユーティリティ関数
 ****************************************************************************/
#ifndef PIECE
void ActObj_ApplyTrans_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...) {
	va_list ap;
	va_start(ap, argc);
	ActObj_ApplyTrans_a(pActObj, iFsmTrans, argc, ap);
	va_end(ap);
}
void ActObj_ApplyTrans_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap) {
	void* argv[16/*調整可*/];	//実用上、パラメータ数が16以下と考えて充分だろう。不足した場合は増やせ。
	int i;
	if((unsigned)argc > (unsigned)ARRAY_SIZE(argv)) { DIE(); }	//ここで停止した場合は、argv[]の要素数を増やせ。
	for(i = 0; i < argc; i++) { argv[i] = va_arg(ap, void*); }
	ActObj_ApplyTrans_v(pActObj, iFsmTrans, argc, argv);
}
void ActObj_ApplyTrans_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]) {
	ST_FsmObj_Arg arg = { argc, argv };
	ActObj_ApplyTrans(pActObj, iFsmTrans, &arg);
}
#else //PIECE
void ActObj_ApplyTrans_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...);
void ActObj_ApplyTrans_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap);
void ActObj_ApplyTrans_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);
asm("
		.code
		.align		1
		.global		ActObj_ApplyTrans_l
		.global		ActObj_ApplyTrans_a
		.global		ActObj_ApplyTrans_v
ActObj_ApplyTrans_l:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//[%sp+0] := retp
		;//[%sp+4] := argc
		;//[%sp+8] := ...
		xld.w		%r14, [%sp+4]			;//%r14 := argc
		xadd		%r15, %sp, 8			;//%r15 := ap = &...
ActObj_ApplyTrans_a:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := ap
ActObj_ApplyTrans_v:
		xsub		%sp, %sp, 8
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := argv
		;//[%sp+0] := (arg.argc)
		;//[%sp+4] := (arg.argv)
		xld.w		[%sp+0], %r14			;//[%sp+0] := arg.argc = argc
		xld.w		[%sp+4], %r15			;//[%sp+4] := arg.argv = argv
		ld.w		%r14, %sp			;//%r14    := pParam = &arg
		xcall		ActObj_ApplyTrans		;//ActObj_ApplyTrans(pActObj, iFsmTrans, pParam)
		xadd		%sp, %sp, 8
		ret
");
#endif//PIECE
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_ApplyTransToChildren_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...) {
	va_list ap;
	va_start(ap, argc);
	ActObj_ApplyTransToChildren_a(pActObj, iFsmTrans, argc, ap);
	va_end(ap);
}
void ActObj_ApplyTransToChildren_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap) {
	void* argv[16/*調整可*/];	//実用上、パラメータ数が16以下と考えて充分だろう。不足した場合は増やせ。
	int i;
	if((unsigned)argc > (unsigned)ARRAY_SIZE(argv)) { DIE(); }	//ここで停止した場合は、argv[]の要素数を増やせ。
	for(i = 0; i < argc; i++) { argv[i] = va_arg(ap, void*); }
	ActObj_ApplyTransToChildren_v(pActObj, iFsmTrans, argc, argv);
}
void ActObj_ApplyTransToChildren_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]) {
	ST_FsmObj_Arg arg = { argc, argv };
	ActObj_ApplyTransToChildren(pActObj, iFsmTrans, &arg);
}
#else //PIECE
void ActObj_ApplyTransToChildren_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...);
void ActObj_ApplyTransToChildren_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap);
void ActObj_ApplyTransToChildren_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);
asm("
		.code
		.align		1
		.global		ActObj_ApplyTransToChildren_l
		.global		ActObj_ApplyTransToChildren_a
		.global		ActObj_ApplyTransToChildren_v
ActObj_ApplyTransToChildren_l:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//[%sp+0] := retp
		;//[%sp+4] := argc
		;//[%sp+8] := ...
		xld.w		%r14, [%sp+4]			;//%r14 := argc
		xadd		%r15, %sp, 8			;//%r15 := ap = &...
ActObj_ApplyTransToChildren_a:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := ap
ActObj_ApplyTransToChildren_v:
		xsub		%sp, %sp, 8
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := argv
		;//[%sp+0] := (arg.argc)
		;//[%sp+4] := (arg.argv)
		xld.w		[%sp+0], %r14			;//[%sp+0] := arg.argc = argc
		xld.w		[%sp+4], %r15			;//[%sp+4] := arg.argv = argv
		ld.w		%r14, %sp			;//%r14    := pParam = &arg
		xcall		ActObj_ApplyTransToChildren	;//ActObj_ApplyTransToChildren(pActObj, iFsmTrans, pParam)
		xadd		%sp, %sp, 8
		ret
");
#endif//PIECE
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_ApplyTransToTree_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...) {
	va_list ap;
	va_start(ap, argc);
	ActObj_ApplyTransToTree_a(pActObj, iFsmTrans, argc, ap);
	va_end(ap);
}
void ActObj_ApplyTransToTree_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap) {
	void* argv[16/*調整可*/];	//実用上、パラメータ数が16以下と考えて充分だろう。不足した場合は増やせ。
	int i;
	if((unsigned)argc > (unsigned)ARRAY_SIZE(argv)) { DIE(); }	//ここで停止した場合は、argv[]の要素数を増やせ。
	for(i = 0; i < argc; i++) { argv[i] = va_arg(ap, void*); }
	ActObj_ApplyTransToTree_v(pActObj, iFsmTrans, argc, argv);
}
void ActObj_ApplyTransToTree_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]) {
	ST_FsmObj_Arg arg = { argc, argv };
	ActObj_ApplyTransToTree(pActObj, iFsmTrans, &arg);
}
#else //PIECE
void ActObj_ApplyTransToTree_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...);
void ActObj_ApplyTransToTree_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap);
void ActObj_ApplyTransToTree_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);
asm("
		.code
		.align		1
		.global		ActObj_ApplyTransToTree_l
		.global		ActObj_ApplyTransToTree_a
		.global		ActObj_ApplyTransToTree_v
ActObj_ApplyTransToTree_l:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//[%sp+0] := retp
		;//[%sp+4] := argc
		;//[%sp+8] := ...
		xld.w		%r14, [%sp+4]			;//%r14 := argc
		xadd		%r15, %sp, 8			;//%r15 := ap = &...
ActObj_ApplyTransToTree_a:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := ap
ActObj_ApplyTransToTree_v:
		xsub		%sp, %sp, 8
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := argv
		;//[%sp+0] := (arg.argc)
		;//[%sp+4] := (arg.argv)
		xld.w		[%sp+0], %r14			;//[%sp+0] := arg.argc = argc
		xld.w		[%sp+4], %r15			;//[%sp+4] := arg.argv = argv
		ld.w		%r14, %sp			;//%r14    := pParam = &arg
		xcall		ActObj_ApplyTransToTree		;//ActObj_ApplyTransToTree(pActObj, iFsmTrans, pParam)
		xadd		%sp, %sp, 8
		ret
");
#endif//PIECE
