/*	
 *	clipprds.c
 *
 *	演出制御
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2014 Naoyuki Sawa
 *
 *	* Mon Jul 02 23:56:03 JST 2012 Naoyuki Sawa
 *	- 1stリリース。
 *	* Wed Sep 19 15:18:34 JST 2012 Naoyuki Sawa
 *	- 演出順序リストのセットアップと同時に、1フレーム実行するように変更しました。
 *	  ProdSetList_Setup() が処理を戻す前に、セットアップトリガ の0フレーム処理(有れば)が実行されるようになりました。
 *	  ProdCh_SendTrigger()が処理を戻す前に、    指定したトリガ の0フレーム処理(有れば)が実行されるようになりました。
 *	* Wed Sep 19 15:18:34 JST 2012 Naoyuki Sawa
 *	- 演出コマンドバッファの仕組みを追加しました。
 *	  この変更により、演出デバイスの演出データフィルタ関数、及び、演出デバイスの演出データセットアップ関数の中から、本モジュールの関数を呼び出せるようになりました。
 *	  ・たとえば、特定の演出データを受け取ったときに、ProdSetList_Setup()を呼び出して、新しい演出セットリストをセットアップすることができます。
 *	  　現在実行中の演出制御チャネル自身に対して行うこともできますし、別の演出制御チャネルに対して行うこともできます。
 *	  ・たとえば、特定の演出データを受け取ったときに、ProdCh_SendTrigger()を呼び出して、任意のトリガを送信することができます。
 *	  　現在実行中の演出制御チャネル自身に対して送信することもできますし、別の演出制御チャネルに対して送信することもできます。
 *	- これまでは、演出デバイスの演出データセットアップ関数内で、直接ProdSetList_Setup()やProdCh_SendTrigger()等を呼び出すことはできませんでした。
 *	  ProdSetList_Setup()やProdCh_SendTrigger()の途中で再帰呼び出しが発生することになり、内部状態が不正になってしまっていたからです。
 *	  そのため、これまでは、演出デバイスの演出データセットアップ関数内ではグローバルフラグをセットしておき、ProdSetList_Setup()やProdCh_SendTrigger()等の終了後に、グローバルフラグを確認して処理を行う不便がありました。
 *	  今回の変更により、上記のような再帰呼び出しの問題は発生しなくなったため、演出デバイスの演出データセットアップ関数内で、直接ProdSetList_Setup()やProdCh_SendTrigger()等を呼び出すことができ、便利になったと思います。
 *	- 【注意】今回の変更後も、演出デバイスの演出データセットアップ関数内で、ProdCh_Reset()とProdCh_ResetAll()を呼び出すことはできません。
 *	  ProdCh_Reset()とProdCh_ResetAll()は、強制的に内部状態をクリアする関数であり、演出コマンドバッファのクリティカルセクションによって保護されないからです。
 *	* Sat Nov 10 18:19:56 JST 2012 Naoyuki Sawa
 *	- ProdDev_CancelSetup()、ProdDev_GetProdDat()を追加しました。
 *	* Mon Feb 04 23:44:12 JST 2013 Naoyuki Sawa
 *	- ProdCh_Exec()とProdCh_ExecAll()内の処理を、演出コマンドセットアップ処理のクリティカルセクションに入れました。
 *	* Tue Feb 05 11:35:37 JST 2013 Naoyuki Sawa
 *	- ProdCh_ClearWarrantCounter()、ProdCh_ClearWarrantCounterAll()を追加しました。
 *	* Wed Apr 03 18:05:33 JST 2013 Naoyuki Sawa
 *	- 暗黙のクリアトリガ送信仕様を追加しました。
 *	  変更した関数は、ProdSetList_Setup()のみです。
 *	* Wed Apr 10 18:39:31 JST 2013 Naoyuki Sawa
 *	- ワークエリアをST_ProdSeq構造体の一か所にまとめるために、大幅なソース変更を行いました。
 *	  主な変更内容は、定義位置の変更であり、アルゴリズムはほぼ変更ありません。
 *	- ワークエリアをST_ProdSeq構造体の一か所にまとめた目的は、今後、演出の途中状態をまるごとバックアップするためです。
 *	* Tue Apr 16 22:45:58 JST 2013 Naoyuki Sawa
 *	- クリティカルセクション内で、演出コマンドを個別にコピーして保持するのでなく、演出コマンドリストのまま保持するよう変更しました。
 *	  バッファのメモリ節約と、コピー時間の短縮のためです。
 *	- グローバル関数の定義には、変更ありません。
 *	  ただし、ProdCmdList_Setup()に指定する演出コマンドリストは、不変であること。(即ち、ROM,又は,実行されるまで変更しないRAM上にあること)
 *	  実際にはさほど厳密な制約ではなく、クリティカルセクションを抜けるまで不変であれば良いだけなので、余り気にする必要はありません。
 *	  演出デバイスのセットアップ関数内から、再帰的にProdCmdList_Setup()を呼び出す場合にのみ、注意が必要です。
 *	  具体的には、セットアップ関数のスタック上に演出コマンドリストを作成してProdCmdList_Setup()を呼び出したりすると、正しく動作しません。
 *	* Mon Jul 01 17:42:17 JST 2013 Naoyuki Sawa
 *	- 演出コマンドリスト,演出順序リスト,演出セットリストの、終端を示す方法を変更しました。
 *	  これまでは、特殊なフィールド値を持つ終端レコードによって示していました。今後は、最終レコードのEndフラグを用いて示すよう変更します。
 *	  この変更によって、終端レコードを配置することが不要になり、データ容量が節約できます。
 *	- これまでは、演出デバイス番号0を、終端レコードを表す特殊なフィールド値として使用していましたが、今回の変更によって不要になったため、
 *	  今後は、演出デバイス番号0も利用できるようになりました。即ち、演出デバイス番号は(1〜ProdDev_Max)でなく、(0〜ProdDev_Max)となります。
 *	* Fri Sep 13 20:13:42 JST 2013 Naoyuki Sawa
 *	- 同一トリガを二回以上セットアップしようとしたときに、二回目以降のセットアップを無視する仕様を削除しました。
 *	  当仕様を削除した理由は:
 *	  ・実際に使ってみて、効果的であるケースが少なかったこと。	//二回目以降のセットアップを自動的に無視することが、却って、バグを発見しづらくする原因になることもあった
 *	  ・この挙動が効果的なケースに対しても、アプリケーション側で比較的簡単に対応できること。
 *	  当仕様の削除に伴い、以下の変更を行いました:
 *	  ・同一トリガを二回以上セットアップするためのフラグであった、ProdSet_Flag_Multiが不要になり、削除しました。
 *	  ・ST_ProdCh.TriggerMaskフィールドが不要になり、削除しました。
 *	  ・トリガ番号の範囲が、変更前は最大31でしたが、変更後は最大255になりました。(ST_ProdCh.TriggerMaskのビット数の制限に囚われなくなったため)
 *	  ・トリガ番号の範囲変更に伴い、暗黙のクリアトリガのトリガ番号を、31⇒255に変更しました。
 *	- 演出セット構造体のフラグに、保障時間カウンタをクリアする機能である、ProdSet_Flag_Immediateを追加しました。
 *	  これまでは、アプリケーションが明示的にProdCh_ClearWarrantCounter()等を呼び出して保障時間カウンタをクリアする必要が有り、データ化しづらい問題がありました。
 *	  今後も、ProdCh_ClearWarrantCounter()等でクリアすることもできますが、それに加えて、保障時間カウンタをクリアしたいトリガの演出セットにフラグ指定できるようになりました。
 *	* Sat Feb 08 14:57:06 JST 2014 Naoyuki Sawa
 *	- 演出デバイスのフィルタ関数とセットアップ関数の格納方法を変更しました。
 *	- これまでは、演出デバイス毎に、個別の関数ポインタを格納していましたが、
 *	  今後は、共通の関数とし、アプリケーション側で振り分けることにしました。
 *	- こう変更した理由は、演出デバイス毎に個別の、関数ポインタを格納するメモリを節約するためです。
 *	  これまで使用した限り、個別の関数が直接呼び出されることの利点は薄かったので、問題ありません。
 *	- 今回の変更に伴い、ProdDev_Install()の使用方法を変更しました。
 *	* Wed Aug 27 20:38:48 JST 2014 Naoyuki Sawa
 *	- ST_ProdSeq.env_ProdDev_CancelSetupを実体⇒ポインタに変更しました。
 *	  理由1. これまでは、アプリケーションが、ProdCmdList_Setup()を経由せずに直接、演出デバイスのフィルタ関数,又は,セットアップ関数を呼出し、
 *	         演出デバイスのフィルタ関数,又は,セットアップ関数の中でProdDev_CancelSetup()を呼出すと、予測できない不正な動作になっていました。
 *	         ProdCmd_Setup()でのenv_ProdDev_CancelSetupに対するsetjmp()が行われた後かを、ProdDev_CancelSetup()では判断できなかったからです。
 *	         今回の変更により、env_ProdDev_CancelSetupをポインタに変更したので、ProdDev_CancelSetup()で上記を判断できるようになりました。
 *	         今後は、上記のケースでProdDev_CancelSetup()内でエラー停止するようになり、バグが見つけ易くなりました。
 *	  理由2. このジャンプバッファは、ProdCmd_Setup()の呼出し期間中のみ必要な変数であり、当構造体の中に静的に確保することはメモリの無駄です。
 *	         EPSONライブラリの場合、jmp_bufは16ワード(64バイト)の変数であり、64バイトの無駄となっていました。
 *	         今後は、env_ProdDev_CancelSetupの実体はProdCmd_Setup()のスタック上に確保し、当構造体の中にはポインタ(4バイト)のみを確保します。
 *	         当構造体のサイズが、60バイト節約できました。
 */
#include "clip.h"

/****************************************************************************
 *	ローカル変数
 ****************************************************************************/

static ST_ProdSeq stProdSeq;	//{{2013/04/10:追加}}

/****************************************************************************
 *	演出デバイス
 ****************************************************************************/

//{{2014/02/08:変更
///* 演出デバイスに、関数を登録します。
// * [in]
// *	iProdDev	演出デバイス番号(0〜ProdDev_Max)				//{{2013/07/01:コメント変更}}
// *	pFilter		演出データフィルタ関数(NULL=無し)
// *	pSetup		演出データセットアップ関数(NULL=無し)
// * [out]
// *	無し
// */
//void ProdDev_Install(int iProdDev, int (*pFilter)(int ProdDev, int ProdDat), void (*pSetup)(int ProdDev, int ProdDat)) {
//	ST_ProdDev* pProdDev;
//
//	if((unsigned)iProdDev > ProdDev_Max) { DIE(); } /* 演出デバイス番号が範囲外 */	//{{2013/07/01:変更}}
//	/* 演出デバイスを取得します。 */
//	pProdDev = &stProdSeq.TBL_ProdDev[iProdDev];					//{{2013/07/01:変更}}
//	/* 演出データフィルタ関数を格納します。 */
//	pProdDev->pFilter = pFilter;	/* NULL=可 */
//	/* 演出データセットアップ関数を格納します。 */
//	pProdDev->pSetup = pSetup;	/* NULL=可 */
//}
//↓2014/02/08:変更
/* 演出デバイスに、関数を登録します。
 * [in]
 *	pProdDevInfo	初期化情報へのポインタ
 * [out]
 *	無し
 * [note]
 *	- 本関数は、初期化情報をコピーせず、ポインタを格納することに注意せよ。
 *	  アプリケーションは、本関数が処理を返した後も、初期化情報を変更したり破棄してはいけない。
 *	- pProdDevInfoにNULLならば、演出データフィルタ関数も演出データセットアップ関数も使用しないことを意味する。
 *	- pProdDevInfoがNULLでなく、fnFilterがNULLならば、演出データフィルタ関数を使用しないことを意味する。
 *	- pProdDevInfoがNULLでなく、fnSetupがNULLならば、演出データセットアップ関数を使用しないことを意味する。
 */
void ProdDev_Install(const ST_ProdDevInfo* pProdDevInfo) {
	/* 初期化情報を格納します。 */
	stProdSeq.pProdDevInfo = pProdDevInfo;
}
//}}2014/02/08:変更

/****************************************************************************
 *	演出コマンド
 ****************************************************************************/

//{{2012/11/10:追加
/* アプリケーション定義の、演出データフィルタ関数、又は、演出データセットアップ関数から呼び出し、演出コマンドセットアップ処理をキャンセルします。
 * [in]
 *	無し
 * [out]
 *	無し
 * [note]
 *	//{{2013/04/15:変更
 *	//- 本関数は、ProdCmd_SetupDirect()から呼び出された、演出データフィルタ関数、又は、演出データセットアップ関数からのみ、呼び出してください。
 *	//  それ以外のケースから呼び出すと、不正な動作となります。
 *	//↓2013/04/15:変更
 *	- 本関数は、ProdCmd_Setup()から呼び出された、演出データフィルタ関数、又は、演出データセットアップ関数からのみ、呼び出してください。
 *	  それ以外のケースから呼び出すと、不正な動作となります。
 *	//}}2013/04/15:変更
 *	- これまで、演出コマンドセットアップ処理を取り消す方法は、演出データセットアップ関数内で判断し、実際の処理を行わない方法しかありませんでした。
 *	  演出データセットアップ関数が実際の処理を行わなくても、演出制御モジュールは、演出セットアップしたものと見なし、演出データを格納していました。
 *	- 今回、より柔軟に演出データセットアップ処理をキャンセルできるよう、ProdDev_CancelSetup()関数を追加しました。
 *	  アプリケーション定義の、演出データフィルタ関数、又は、演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出すと、
 *	  演出制御モジュールは、演出セットアップされなかったことを認識し、演出データを格納しません。
 *	  従って、演出制御モジュールが格納している演出データと、実際の実際の演出状態が、一致します。
 */
void ProdDev_CancelSetup() {
//{{2013/04/15:変更
//	/* ProdCmd_SetupDirect()で登録した、戻り位置へ戻ります。 */
//↓2013/04/15:変更
//	/* ProdCmd_Setup()で登録した、戻り位置へ戻ります。 */
//	longjmp(stProdSeq.env_ProdDev_CancelSetup, 1);
//↓2014/08/27:変更
	/* * Wed Aug 27 20:38:48 JST 2014 Naoyuki Sawa
	 * - ST_ProdSeq.env_ProdDev_CancelSetupを実体⇒ポインタに変更しました。
	 *   ここでエラー停止した場合、アプリケーションバグの可能性があります。
	 *   clipprds.hのST_ProdSeq.env_ProdDev_CancelSetupコメントを参照してください。 */
	if(!stProdSeq.env_ProdDev_CancelSetup) { DIE(); }
	longjmp(*stProdSeq.env_ProdDev_CancelSetup, 1);
//}}2014/08/27:変更
}
/* 演出制御モジュールが記憶している、現在、実行中の演出データを、参照します。
 * [in]
 *	iProdDev	演出デバイス番号(0〜ProdDev_Max)				//{{2013/07/01:コメント変更}}
 * [out]
 *	戻り値		演出データ
 * [note]
 *	- ユーティリティ関数です。
 *	  アプリケーション側で、現在、実行中の演出データを記憶しなくても済むよう、追加しました。
 *	  本関数を使うことは、必須ではありません。
 */
int ProdDev_GetProdDat(int iProdDev) {
	ST_ProdDev* pProdDev;
	if((unsigned)iProdDev > ProdDev_Max) { DIE(); } /* 演出デバイス番号が範囲外 */	//{{2013/07/01:変更}}
	/* 演出デバイスを取得します。 */
	pProdDev = &stProdSeq.TBL_ProdDev[iProdDev];					//{{2013/07/01:変更}}
	/* 演出データを取得します。 */
	return pProdDev->ProdDat;
}
//■ProdDev_CancelSetup()とProdDev_GetProdDat()の使用例
//	/* 演出データフィルタ関数 */
//	int myFilter(int ProdDev, int ProdDat) {
//		/* 現在、実行中の演出データを、取得する。 */
//		int OldDat = ProdDev_GetProdDat(ProdDev);
//		/* 新しい演出データが、実行中の演出データよりも小さい番号ならば、切り替えを取り消す。 */
//		if(ProdDat < OldDat) { ProdDev_CancelSetup(); }
//		/* 新しい演出データが、実行中の演出データと同じならば、(実行中＋１)の番号に変換する。 */
//		if(ProdDat == OldDat) { ProdDat = OldDat + 1; }
//		/* 演出データの、フィルタ結果を返す。 */
//		return ProdDat;
//	}
//	/* 演出データセットアップ関数 */
//	void mySetup(int ProdDev, int ProdDat) {
//		/* アプリケーション定義の、演出切り替え禁止フラグがセットされていたら、切り替えを取り消す。 */
//		if(myDisableSetup) { ProdDev_CancelSetup(); }
//		/* 実際の、演出切り替え処理を行う。 */
//		myDeviceDriver(ProdDat);
//	}
//}}2012/11/10:追加

/*--------------------------------------------------------------------------*/

//{{2013/04/15:変更
///* ダイレクトモードの、演出コマンドセットアップ処理です。
// * [in]
// *	pProdCmd	演出コマンド(NULL=不可)
// * [out]
// *	無し
// * [note]
// *	- 演出コマンドセットアップ処理のクリティカルセクション外で、演出コマンドをセットアップする際に使用します。
// *	  演出コマンドを、演出コマンドバッファに格納せず、直接、演出デバイスにセットアップします。
// *	- ProdCmd_Setup_EnterCS()のコメントを参照してください。
// */
//static void ProdCmd_SetupDirect(const ProdCmd* pProdCmd) {
//	ST_ProdDev* pProdDev;
//	int ProdDat;
//
//	if(pProdCmd == NULL) { DIE(); } /* NULL=不可 */
////{{2012/11/10:追加
//	/* 演出データフィルタ関数、又は、演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時の、戻り位置を登録します。 */
//	if(setjmp(stProdSeq.env_ProdDev_CancelSetup) == 0) {
////}}2012/11/10:追加
//		/* 演出デバイスと、演出データを取得します。 */
//		if((pProdCmd->iProdDev < 1) || (pProdCmd->iProdDev > ProdDev_Max)) { DIE(); } /* 演出デバイス番号が範囲外 */
//		pProdDev = &stProdSeq.TBL_ProdDev[pProdCmd->iProdDev - 1];
//		ProdDat = pProdCmd->ProdDat;
//		/* 演出データフィルタ関数が有れば… */
//		if(pProdDev->pFilter != NULL) {
//			/* 演出データを変換します。 */
//			ProdDat = (*pProdDev->pFilter)(pProdCmd->iProdDev, ProdDat);	/* 演出データフィルタ関数が、ProdDev_CancelSetup()を呼び出した時は、以下の処理を飛ばします。 */
//		}
//		/* 演出コマンドの、NoResetフラグがセットされていたら… */
//		if((pProdCmd->Flag & ProdCmd_Flag_NoReset) != 0) {
//			/* 演出データが変化しなければ、セットアップしません。 */
//			if(ProdDat == pProdDev->ProdDat) {
//				return; /* ここまで */
//			}
//		}
//		/* 演出データセットアップ関数が有れば… */
//		if(pProdDev->pSetup != NULL) {
//			/* 演出データを演出デバイスにセットアップします。 */
//			(*pProdDev->pSetup)(pProdCmd->iProdDev, ProdDat);	/* 演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時は、以下の処理を飛ばします。 */
//		}
//		/* 演出データを格納します。 */
//		pProdDev->ProdDat = ProdDat;
////{{2012/11/10:追加
//	} /* 演出データフィルタ関数、又は、演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時の、戻り位置はここです。 */
////}}2012/11/10:追加
//}
//↓2013/04/15:変更
/* 演出コマンドをセットアップします。
 * [in]
 *	pProdCmd	演出コマンド(NULL=不可)
 * [out]
 *	無し
 * [note]
 *	- ProdCmdList_Setup_LeaveCS()からのみ使用します。
 *	  ProdCmdList_Setup_LeaveCS()を参照してください。
 */
static void ProdCmd_Setup(const ProdCmd* pProdCmd) {
	ST_ProdDev* pProdDev;
	int ProdDat;
//{{2014/08/27:追加
	jmp_buf env, *env_save;
//}}2014/08/27:追加

	if(pProdCmd == NULL) { DIE(); } /* NULL=不可 */
	/* 演出データフィルタ関数、又は、演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時の、戻り位置を登録します。 */
//{{2014/08/27:変更
//	if(setjmp(stProdSeq.env_ProdDev_CancelSetup) == 0) {
//↓2014/08/27:変更
	/* * Wed Aug 27 20:38:48 JST 2014 Naoyuki Sawa
	 * - ST_ProdSeq.env_ProdDev_CancelSetupを実体⇒ポインタに変更しました。
	 * - 当関数はST_ProdSeq.ProdCmd_Setup_CountCSで保護されており再入しないはずだから、当関数が呼出された時にstProdSeq.env_ProdDev_CancelSetup==NULLであるはずです。
	 *   従って、現在値をenv_saveへ退避することは必須ではなく、単純に、当関数から抜けるときにNULLに戻すだけでも問題ないかも知れません。(未検証)
	 *   しかし、今後実装を変更した場合に柔軟に対応できるよう、現在値をenv_saveへ退避して、当関数から抜けるときにenv_saveを戻すことにしました。 */
	env_save = stProdSeq.env_ProdDev_CancelSetup;
	           stProdSeq.env_ProdDev_CancelSetup = &env;
	if(setjmp(env) == 0) {
//}}2014/08/27:変更
		/* 演出デバイスと、演出データを取得します。 */
		if((unsigned)pProdCmd->iProdDev > ProdDev_Max) { DIE(); } /* 演出デバイス番号が範囲外 */	//{{2013/07/01:変更}}
		pProdDev = &stProdSeq.TBL_ProdDev[pProdCmd->iProdDev];						//{{2013/07/01:変更}}
		ProdDat = pProdCmd->ProdDat;
	//{{2014/02/08:変更
	//	/* 演出データフィルタ関数が有れば… */
	//	if(pProdDev->pFilter != NULL) {
	//		/* 演出データを変換します。 */
	//		ProdDat = (*pProdDev->pFilter)(pProdCmd->iProdDev, ProdDat);	/* 演出データフィルタ関数が、ProdDev_CancelSetup()を呼び出した時は、以下の処理を飛ばします。 */
	//	}
	//↓2014/02/08:変更
		/* 演出データフィルタ関数が有れば… */
		if(stProdSeq.pProdDevInfo && stProdSeq.pProdDevInfo->fnFilter) {
			/* 演出データを変換します。 */
			ProdDat = (*stProdSeq.pProdDevInfo->fnFilter)(pProdCmd->iProdDev, ProdDat);	/* 演出データフィルタ関数が、ProdDev_CancelSetup()を呼び出した時は、以下の処理を飛ばします。 */
		}
	//}}2014/02/08:変更
		/* 演出コマンドの、NoResetフラグがセットされていたら… */
		if((pProdCmd->Flag & ProdCmd_Flag_NoReset) != 0) {
			/* 演出データが変化しなければ、セットアップしません。 */
			if(ProdDat == pProdDev->ProdDat) {
//{{2014/08/27:変更
//				return; /* ここまで */
//↓2014/08/27:変更
				/* * Wed Aug 27 20:38:48 JST 2014 Naoyuki Sawa
				 * - ST_ProdSeq.env_ProdDev_CancelSetupを実体⇒ポインタに変更しました。
				 * - 当関数はST_ProdSeq.ProdCmd_Setup_CountCSで保護されており再入しないはずだから、当関数が呼出された時にstProdSeq.env_ProdDev_CancelSetup==NULLであるはずです。
				 *   従って、現在値をenv_saveへ退避することは必須ではなく、単純に、当関数から抜けるときにNULLに戻すだけでも問題ないかも知れません。(未検証)
				 *   しかし、今後実装を変更した場合に柔軟に対応できるよう、現在値をenv_saveへ退避して、当関数から抜けるときにenv_saveを戻すことにしました。 */
				goto L_EXIT; /* env_saveを戻す処理へ */
//}}2014/08/27:変更
			}
		}
	//{{2014/02/08:変更
	//	/* 演出データセットアップ関数が有れば… */
	//	if(pProdDev->pSetup != NULL) {
	//		/* 演出データを演出デバイスにセットアップします。 */
	//		(*pProdDev->pSetup)(pProdCmd->iProdDev, ProdDat);	/* 演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時は、以下の処理を飛ばします。 */
	//	}
	//↓2014/02/08:変更
		/* 演出データセットアップ関数が有れば… */
		if(stProdSeq.pProdDevInfo && stProdSeq.pProdDevInfo->fnSetup) {
			/* 演出データを演出デバイスにセットアップします。 */
			(*stProdSeq.pProdDevInfo->fnSetup)(pProdCmd->iProdDev, ProdDat);	/* 演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時は、以下の処理を飛ばします。 */
		}
	//}}2014/02/08:変更
		/* 演出データを格納します。 */
		pProdDev->ProdDat = ProdDat;
	} /* 演出データフィルタ関数、又は、演出データセットアップ関数が、ProdDev_CancelSetup()を呼び出した時の、戻り位置はここです。 */
//{{2014/08/27:追加
L_EXIT:
	/* * Wed Aug 27 20:38:48 JST 2014 Naoyuki Sawa
	 * - ST_ProdSeq.env_ProdDev_CancelSetupを実体⇒ポインタに変更しました。
	 * - 当関数はST_ProdSeq.ProdCmd_Setup_CountCSで保護されており再入しないはずだから、当関数が呼出された時にstProdSeq.env_ProdDev_CancelSetup==NULLであるはずです。
	 *   従って、現在値をenv_saveへ退避することは必須ではなく、単純に、当関数から抜けるときにNULLに戻すだけでも問題ないかも知れません。(未検証)
	 *   しかし、今後実装を変更した場合に柔軟に対応できるよう、現在値をenv_saveへ退避して、当関数から抜けるときにenv_saveを戻すことにしました。 */
	stProdSeq.env_ProdDev_CancelSetup = env_save;
//}}2014/08/27:追加
}
//}}2013/04/15:変更

/*--------------------------------------------------------------------------*/

//{{2013/04/13:削除
///* バッファモードの、演出コマンドセットアップ処理です。
// * [in]
// *	pProdCmd	演出コマンド(NULL=不可)
// * [out]
// *	無し
// * [note]
// *	- 演出コマンドセットアップ処理のクリティカルセクション内で、演出コマンドをセットアップする際に使用します。
// *	  演出コマンドを、演出デバイスにセットアップせず、一時、演出コマンドバッファに格納します。
// *	- ProdCmd_Setup_EnterCS()のコメントを参照してください。
// */
//static void ProdCmd_SetupBuffer(const ProdCmd* pProdCmd) {
//	int i;
//
//	if(pProdCmd == NULL) { DIE(); } /* NULL=不可 */
//	/* 演出コマンドバッファの末尾に、演出コマンドを追加します。
//	 * 演出コマンドバッファに空きがければ、演出コマンドを破棄します。
//	 */
//	for(i = 0; i < ProdCmd_Buffer_Size; i++) {
//		if(stProdSeq.TBL_ProdCmd_Buffer[i].iProdDev == 0) {
//			stProdSeq.TBL_ProdCmd_Buffer[i] = *pProdCmd;
//			return; /* ここまで */
//		}
//	}
//}
//}}2013/04/13:削除

/*--------------------------------------------------------------------------*/

//{{2013/04/13:削除
///* 演出コマンドをセットアップします。
// * [in]
// *	pProdCmd	演出コマンド(NULL=不可)
// * [out]
// *	無し
// * [note]
// *	//{{2013/04/10:変更
// *	//- ProdCmd_SetupDirect()、又は、ProdCmd_SetupBuffer()への、関数ポインタです。
// *	//  ProdCmd_Setup_EnterCS()と、ProdCmd_Setup_LeaveCS()によって、切り替えます。
// *	//- ProdCmd_Setup_EnterCS()のコメントを参照してください。
// *	//↓2013/04/10:変更
// *	- stProdSeq.ProdCmd_Setup_CountCSを参照して、実行モードを切り替えるように変更しました。
// *	  この変更によって、関数ポインタは不要になり、通常の関数になりました。
// *	//}}2013/04/10:変更
// */
////{{2013/04/10:変更
////static void (*ProdCmd_Setup)(const ProdCmd* pProdCmd) = ProdCmd_SetupDirect;
////↓2013/04/10:変更
//static void ProdCmd_Setup(const ProdCmd* pProdCmd) {
//	/* 演出コマンドセットアップ処理を実行します。 */
//	((stProdSeq.ProdCmd_Setup_CountCS == 0) ? ProdCmd_SetupDirect		/* クリティカルセクション外ならば、ダイレクトモードで実行します */
//					     : ProdCmd_SetupBuffer)(pProdCmd);	/* クリティカルセクション内ならば、  バッファモードで実行します */
//}
////}}2013/04/10:変更
//}}2013/04/13:削除

/*--------------------------------------------------------------------------*/

//{{2013/04/15:変更
///* 演出コマンドセットアップ処理の、クリティカルセクションに入ります。
// * [in]
// *	無し
// * [out]
// *	無し
// * [note]
// *	- ProdCmd_Setup_EnterCS()の呼び出しと同じ回数、ProdCmd_Setup_LeaveCS()を呼び出す必要があります。
// *	  ProdCmd_Setup_EnterCS()とProdCmd_Setup_LeaveCS()の呼び出しは、入れ子になっていても構いません。
// */
//static void ProdCmd_Setup_EnterCS() {
////{{2013/04/10:削除
////	/* クリティカルセクションに入る初回ならば… */
////	if(stProdSeq.ProdCmd_Setup_CountCS == 0) {
////		/* 演出コマンドセットアップ処理を、バッファモードに切り替えます。 */
////		ProdCmd_Setup = ProdCmd_SetupBuffer;
////	}
////}}2013/04/10:削除
//	/* クリティカルセクションに入った回数を増やします。 */
//	stProdSeq.ProdCmd_Setup_CountCS++;
//}
//↓2013/04/15:変更
/* 演出コマンドリストセットアップ処理の、クリティカルセクションに入ります。
 * [in]
 *	無し
 * [out]
 *	無し
 * [note]
 *	- ProdCmdList_Setup_EnterCS()の呼び出しと同じ回数、ProdCmdList_Setup_LeaveCS()を呼び出す必要があります。
 *	  ProdCmdList_Setup_EnterCS()とProdCmdList_Setup_LeaveCS()の呼び出しは、入れ子になっていても構いません。
 */
static void ProdCmdList_Setup_EnterCS() {
	/* クリティカルセクションに入った回数を増やします。 */
	stProdSeq.ProdCmdList_Setup_CountCS++;
}
//}}2013/04/15:変更

/*--------------------------------------------------------------------------*/

//{{2013/04/15:変更
///* 演出コマンドセットアップ処理の、クリティカルセクションを抜けます。
// * [in]
// *	無し
// * [out]
// *	無し
// * [note]
// *	- ProdCmd_Setup_EnterCS()のコメントを参照してください。
// */
//static void ProdCmd_Setup_LeaveCS() {
//	/* クリティカルセクションを抜ける最後ならば… */
//	if(stProdSeq.ProdCmd_Setup_CountCS == 1) {
//		/* 演出コマンドバッファが空になるまで… */
//		while(stProdSeq.TBL_ProdCmd_Buffer[0].iProdDev != 0) {
//			/* 演出コマンドバッファから、先頭の演出コマンドを取り出します。 */
//			ProdCmd prodCmd = stProdSeq.TBL_ProdCmd_Buffer[0];
//			memmove(&stProdSeq.TBL_ProdCmd_Buffer[0],
//				&stProdSeq.TBL_ProdCmd_Buffer[1],
//				sizeof(ProdCmd) * (ProdCmd_Buffer_Size - 1));
//			stProdSeq.TBL_ProdCmd_Buffer[(ProdCmd_Buffer_Size - 1)].iProdDev = 0;
//			/* 演出コマンドを実行します。
//			 * - ProdCmd_SetupDirect()の中で、新しい演出コマンドが演出コマンドバッファの【末尾】に追加される可能性があります。
//			 *   ProdCmd_SetupDirect()の中で【末尾】に追加された新しい演出コマンドも、このループの中で処理します。
//			 * - ProdCmd_SetupDirect()の中で、ProdCmd_Setup_EnterCS()とProdCmd_Setup_LeaveCS()が呼び出される可能性もあります。
//			 *   ProdCmd_SetupDirect()の中で、ProdCmd_Setup_EnterCS()とProdCmd_Setup_LeaveCS()の呼び出しは一対一のはずなので、考慮する必要はありません。
//			 */
//			ProdCmd_SetupDirect(&prodCmd);
//		}
////{{2013/04/10:削除
////		/* 演出コマンドセットアップ処理を、ダイレクトモードに切り戻します。
////		 * - この処理は、上記のループよりも後で行う必要があることに注意してください。
////		 *   上記のループよりも後前に行うと、ProdCmd_SetupDirect()の中で新しいコマンドがセットアップされた時に、先に実行されてしまい、順序が不正になります。
////		 */
////		ProdCmd_Setup = ProdCmd_SetupDirect;
////}}2013/04/10:削除
//	}
//	/* クリティカルセクションに入った回数を減らします。 */
//	stProdSeq.ProdCmd_Setup_CountCS--;
//}
//↓2013/04/15:変更
/* 演出コマンドリストセットアップ処理の、クリティカルセクションを抜けます。
 * [in]
 *	無し
 * [out]
 *	無し
 * [note]
 *	- ProdCmdList_Setup_EnterCS()のコメントを参照してください。
 */
static void ProdCmdList_Setup_LeaveCS() {
	/* クリティカルセクションを抜ける最後ならば… */
	if(stProdSeq.ProdCmdList_Setup_CountCS == 1) {
		/* 演出コマンドリストバッファが空になるまで…
		 * - ProdCmd_Setup()の中で、新しい演出コマンドが演出コマンドリストバッファの【末尾】に追加される可能性があります。
		 *   ProdCmd_Setup()の中で【末尾】に追加された新しい演出コマンドリストも、このループの中で処理します。
		 * - ProdCmd_Setup()の中で、ProdCmdList_Setup_EnterCS()とProdCmdList_Setup_LeaveCS()が呼び出される可能性もあります。
		 *   ProdCmd_Setup()の中で、ProdCmdList_Setup_EnterCS()とProdCmdList_Setup_LeaveCS()の呼び出しは一対一のはずなので、考慮する必要はありません。
		 */
		while(stProdSeq.TBL_ProdCmdList_Buffer[0] != NULL) {
			/* 演出コマンドバッファから、先頭の演出コマンドを取り出します。 */
			const ProdCmd* pProdCmdList = stProdSeq.TBL_ProdCmdList_Buffer[0];
			memmove(&stProdSeq.TBL_ProdCmdList_Buffer[0],
				&stProdSeq.TBL_ProdCmdList_Buffer[1],
				sizeof(ProdCmd*) *       (ProdCmdList_Buffer_Size - 1));
			stProdSeq.TBL_ProdCmdList_Buffer[(ProdCmdList_Buffer_Size - 1)] = NULL;
		//{{2013/07/01:変更
		//	/* 演出コマンドリストが、演出デバイス番号=0(終端)に達するまで… */
		//	while(pProdCmdList->iProdDev != 0) {
		//		/* 演出コマンドをセットアップします。 */
		//		ProdCmd_Setup(pProdCmdList);
		//		/* 演出コマンドリストを進めます。 */
		//		pProdCmdList++;
		//	}
		//↓2013/07/01:変更
			for(;;) {
				/* 演出コマンドをセットアップします。 */
				ProdCmd_Setup(pProdCmdList);
				/* 演出コマンドの、Endフラグがセットされていたら… */
				if((pProdCmdList->Flag & ProdCmd_Flag_End) != 0) {
					break; /* 抜けます */
				}
				/* 演出コマンドリストを進めます。 */
				pProdCmdList++;
			}
		//}}2013/07/01:変更
		}
	}
	/* クリティカルセクションに入った回数を減らします。 */
	stProdSeq.ProdCmdList_Setup_CountCS--;
}
//}}2013/04/15:変更

/*--------------------------------------------------------------------------*/

//{{2013/04/13:変更
///* 演出コマンドリストをセットアップします。
// * [in]
// *	pProdCmdList	演出コマンドリスト(NULL=不可)
// * [out]
// *	無し
// */
//void ProdCmdList_Setup(const ProdCmd* pProdCmdList) {
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdCmd_Setup()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//
//	if(pProdCmdList == NULL) { DIE(); } /* NULL=不可 */
//	/* 演出デバイス番号=0(終端)でなければ… */
//	while(pProdCmdList->iProdDev != 0) {
//		/* 演出コマンドをセットアップします。 */
//		ProdCmd_Setup(pProdCmdList);
//		/* 演出コマンドリストを進めます。 */
//		pProdCmdList++;
//	}
//
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//}
//↓2013/04/13:変更
/* 演出コマンドリストをセットアップします。
 * [in]
 *	pProdCmdList	演出コマンドリスト(NULL=不可)
 * [out]
 *	無し
 */
void ProdCmdList_Setup(const ProdCmd* pProdCmdList) {
	int i;

	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - 以下の処理は、クリティカルセクションで保護する必要はありませんが、本関数の末尾で呼び出すProdCmdList_Setup_LeaveCS()との対応のために、ProdCmdList_Setup_EnterCS()が必要です。
	 *   ProdCmdList_Setup_LeaveCS()の直前で、ProdCmdList_Setup_EnterCS()を実行するように変更しても構いませんが、形式上、本関数の先頭でクリティカルセクションに入れることにしました。
	 */
	ProdCmdList_Setup_EnterCS();

	if(pProdCmdList == NULL) { DIE(); } /* NULL=不可 */
	/* 演出コマンドリストバッファの末尾に、演出コマンドリストを追加します。
	 * 演出コマンドリストバッファに空きがければ、演出コマンドリストを破棄します。
	 */
	for(i = 0; i < ProdCmdList_Buffer_Size; i++) {
		if(stProdSeq.TBL_ProdCmdList_Buffer[i] == NULL) {
			stProdSeq.TBL_ProdCmdList_Buffer[i] = pProdCmdList;
			break; /* 抜けます */
		}
	}

	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。
	 * - クリティカルセクション外だったならば、ProdCmdList_Setup_LeaveCS()の呼び出しによって、いま追加した演出コマンドリストを、即、実行します。
	 *   クリティカルセクション内だったならば、ProdCmdList_Setup_LeaveCS()を呼び出しによって、演出コマンドリストを実行しません。
	 */
	ProdCmdList_Setup_LeaveCS();
}
//}}2013/04/13:変更

/****************************************************************************
 *	演出順序制御チャネル
 ****************************************************************************/

/* 演出順序制御チャネルを、停止します。
 * [in]
 *	iProdOrdCh	演出順序制御チャネル番号(0〜ProdOrdCh_Max)
 * [out]
 *	無し
 */
static void ProdOrdCh_Stop(int iProdOrdCh) {
	ST_ProdOrdCh* pProdOrdCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdCmdList_Setup()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdCmdList_Setup()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	if((unsigned)iProdOrdCh > ProdOrdCh_Max) { DIE(); } /* 演出順序制御チャネル番号が範囲外 */
	/* 演出順序制御チャネルを取得します。 */
	pProdOrdCh = &stProdSeq.TBL_ProdOrdCh[iProdOrdCh];
	/* 停止していたら、何もしません。 */
	if(pProdOrdCh->pProdOrdList == NULL) {
		goto L_EXIT; /* ここまで */
	}
//{{2013/07/01:変更
//	/* 演出順序リストが終端に到達するまで… */
//	while(pProdOrdCh->pProdOrdList->pProdCmdList != NULL) {
//		/* ProdOrd_Flag_Ensureフラグがセットされているか、又は、遅延時間が"停止時"ならば… */
//		if(((pProdOrdCh->pProdOrdList->Flag & ProdOrd_Flag_Ensure) != 0) ||
//		    (pProdOrdCh->pProdOrdList->Delay == 65535/*停止時*/)) {
//			/* 演出コマンドリストをセットアップします。繰り返し回数は考慮しません。 */
//			ProdCmdList_Setup(pProdOrdCh->pProdOrdList->pProdCmdList);
//		}
//		/* 演出順序リストを進めます。 */
//		pProdOrdCh->pProdOrdList++;
//	}
//↓2013/07/01:変更
	for(;;) {
		/* ProdOrd_Flag_Ensureフラグがセットされているか、又は、遅延時間が"停止時"ならば… */
		if(((pProdOrdCh->pProdOrdList->Flag & ProdOrd_Flag_Ensure) != 0) ||
		    (pProdOrdCh->pProdOrdList->Delay == 65535/*停止時*/)) {
			/* 演出コマンドリストをセットアップします。繰り返し回数は考慮しません。 */
			ProdCmdList_Setup(pProdOrdCh->pProdOrdList->pProdCmdList);
		}
		/* 演出順序の、Endフラグがセットされていたら… */
		if((pProdOrdCh->pProdOrdList->Flag & ProdOrd_Flag_End) != 0) {
			break; /* 抜けます */
		}
		/* 演出順序リストを進めます。 */
		pProdOrdCh->pProdOrdList++;
	}
//}}2013/07/01:変更
	/* 演出順序制御チャネルをクリアします。 */
	memset(pProdOrdCh, 0, sizeof(ST_ProdOrdCh));
L_EXIT:
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

//{{2012/09/19:追加
static void ProdOrdCh_Exec(int iProdOrdCh);
//}}2012/09/19:追加

/* 演出順序制御チャネルに、演出順序リストをセットアップします。
 * [in]
 *	iProdOrdCh	演出順序制御チャネル番号(0〜ProdOrdCh_Max)
 *	pProdOrdList	演出順序リスト(NULL=不可)
 * [out]
 *	無し
 */
static void ProdOrdCh_SetupProdOrdList(int iProdOrdCh, const ProdOrd* pProdOrdList) {
	ST_ProdOrdCh* pProdOrdCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdOrdCh_Stop()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdOrdCh_Stop()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	if((unsigned)iProdOrdCh > ProdOrdCh_Max) { DIE(); } /* 演出順序制御チャネル番号が範囲外 */
	if(pProdOrdList == NULL) { DIE(); } /* NULL=不可 */
	/* まず、確実に停止します。 */
	ProdOrdCh_Stop(iProdOrdCh);
	/* 演出順序制御チャネルを取得します。 */
	pProdOrdCh = &stProdSeq.TBL_ProdOrdCh[iProdOrdCh];
	/* 演出順序リストを格納します。 */
	pProdOrdCh->pProdOrdList = pProdOrdList;
//{{2012/09/19:追加
// * Wed Sep 19 15:18:34 JST 2012 Naoyuki Sawa
// - 演出順序リストのセットアップと同時に、1フレーム実行するように変更しました。
//   理由1. ProdSetList_Setup()が処理を戻す前に、セットアップトリガの0フレーム処理(有れば)が実行される方が、扱い易いからです。
//   理由2. ProdCh_SendTrigger()が処理を戻す前に、指定したトリガの0フレーム処理(有れば)が実行される方が、扱い易いからです。
// - この変更に伴い、ProdCh_Exec()内の、ProdSetCh_Exec()とProdOrdCh_Exec()の実行順序を入れ替えました。
//   [旧]: ProdSetCh_Exec()⇒ProdOrdCh_Exec()の順
//   [新]: ProdOrdCh_Exec()⇒ProdSetCh_Exec()の順
//   理由. [旧]の順では、ProdSetCh_Exec()で演出順序リストをセットアップした時1フレーム実行し、さらにProdOrdCh_Exec()で1フレーム実行してしまいます。
//         ProdCh_Exec()一回の呼び出しで、2フレーム実行してしまう問題があります。
//         [新]の順ならば、上記の問題は生じません。
	ProdOrdCh_Exec(iProdOrdCh);
//}}2012/09/19:追加

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

/* 演出順序制御チャネルを、実行します。
 * [in]
 *	iProdOrdCh	演出順序制御チャネル番号(0〜ProdOrdCh_Max)
 * [out]
 *	無し
 */
static void ProdOrdCh_Exec(int iProdOrdCh) {
	ST_ProdOrdCh* pProdOrdCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdOrdCh_Stop(),ProdCmdList_Setup()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdOrdCh_Stop(),ProdCmdList_Setup()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	if((unsigned)iProdOrdCh > ProdOrdCh_Max) { DIE(); } /* 演出順序制御チャネル番号が範囲外 */
	/* 演出順序制御チャネルを取得します。 */
	pProdOrdCh = &stProdSeq.TBL_ProdOrdCh[iProdOrdCh];
	/* 停止していたら、何もしません。 */
	if(pProdOrdCh->pProdOrdList == NULL) {
		goto L_EXIT; /* ここまで */
	}
	for(;;) {
	//{{2013/07/01:削除
	//	/* 演出順序リストが、終端に到達していたら… */
	//	if(pProdOrdCh->pProdOrdList->pProdCmdList == NULL) {
	//		/* 演出順序制御チャネルを停止します。 */
	//		ProdOrdCh_Stop(iProdOrdCh);
	//		goto L_EXIT; /* ここまで */
	//	}
	//}}2013/07/01:削除
		/* 遅延時間カウンタが、演出順序の遅延時間に到達していなければ… */
		if(pProdOrdCh->DelayCounter < pProdOrdCh->pProdOrdList->Delay) {
			/* 演出順序の遅延時間が、"停止時"でなければ… */
			if(pProdOrdCh->pProdOrdList->Delay != 65535/*停止時*/) {
				/* 遅延時間カウンタを進めます。 */
				pProdOrdCh->DelayCounter++;
			}
			goto L_EXIT; /* ここまで */
		/* 遅延時間カウンタが、演出順序の遅延時間に到達していたら… */
		} else {
			/* 遅延時間カウンタを、リセットします。 */
			pProdOrdCh->DelayCounter = 0;
			/* 演出コマンドリストを、セットアップします。 */
			ProdCmdList_Setup(pProdOrdCh->pProdOrdList->pProdCmdList);
		}
		/* 繰り返し回数カウンタが、演出順序の繰り返し回数に到達してなければ… */
		if(pProdOrdCh->RepeatCounter < pProdOrdCh->pProdOrdList->Repeat) {
			/* 演出順序の繰り返し回数が、"無限"でなければ… */
			if(pProdOrdCh->pProdOrdList->Repeat != 255/*無限*/) {
				/* 繰り返し回数カウンタを進めます。 */
				pProdOrdCh->RepeatCounter++;
			/* 演出順序の繰り返し回数が、"無限"ならば… */
			} else {
				/* 演出順序の遅延時間が、0でないことを確認します。
				 * - 繰り返し回数=255(無限),遅延時間=0(即時)だと、永久ループになります。
				 */
				if(pProdOrdCh->pProdOrdList->Delay == 0) { DIE(); } /* 演出順序が不正 */
			}
		/* 繰り返し回数カウンタが、演出順序の繰り返し回数に到達していたら… */
		} else {
	//{{2013/07/01:追加
			/* 演出順序の、Endフラグがセットされていたら… */
			if((pProdOrdCh->pProdOrdList->Flag & ProdOrd_Flag_End) != 0) {
				/* 演出順序制御チャネルをクリアします。
				 * - ProdOrdCh_Stop()を呼び出してはいけません。
				 *   演出順序リストの最終レコードを、意図せず再実行してしまうことになるからです。
				 * - 「pProdOrdCh->pProdOrdList = NULL」とするだけでは不足です。
				 *   RepeatCounterとDelayCounterもクリアする必要があるからです。
				 *   確実のために、ProdOrdCh_Stop()と同様に、構造体全体をクリアすることにします。
				 */
				memset(pProdOrdCh, 0, sizeof(ST_ProdOrdCh));
				goto L_EXIT; /* ここまで */
			}
	//}}2013/07/01:追加
			/* 演出順序リストを進めます。 */
			pProdOrdCh->pProdOrdList++;
		}
	}
L_EXIT:
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/****************************************************************************
 *	演出セット制御チャネル
 ****************************************************************************/

/* 演出セットリストから、トリガに対応する演出セットを検索します。
 * [in]
 *	pProdSetList	演出セットリスト(NULL=不可)
 *	Trigger		トリガ(0〜255)							//{{2013/09/13:コメント変更}}
 * [out]
 *	戻り値		演出セットが見つかった場合は、演出セットを返します。
 *			演出セットが見つからなかった場合は、NULLを返します。
 */
static const ProdSet* ProdSetList_FindTrigger(const ProdSet* pProdSetList, int Trigger) {
	if(pProdSetList == NULL) { DIE(); } /* NULL=不可 */
	if((unsigned)Trigger > 255) { DIE(); } /* トリガが範囲外 */			//{{2013/09/13:変更}}
//{{2013/07/01:変更
//	/* 演出セットリストが終端に到達するまで… */
//	while(pProdSetList->pProdOrdList != NULL) {
//		/* 演出セットのトリガが、指定されたトリガに一致したら、演出セットを返します。 */
//		if(pProdSetList->Trigger == Trigger) {
//			return pProdSetList;
//		}
//		/* 演出セットリストを進めます。 */
//		pProdSetList++;
//	}
//↓2013/07/01:変更
	for(;;) {
		/* 演出セットのトリガが、指定されたトリガに一致したら、演出セットを返します。 */
		if(pProdSetList->Trigger == Trigger) {
			return pProdSetList;
		}
		/* 演出セットの、Endフラグがセットされていたら… */
		if((pProdSetList->Flag & ProdSet_Flag_End) != 0) {
			break; /* 抜けます */
		}
		/* 演出セットリストを進めます。 */
		pProdSetList++;
	}
//}}2013/07/01:変更
	/* 演出セットが見つからなかった場合は、NULLを返します。 */
	return NULL;
}

/*--------------------------------------------------------------------------*/

/* 演出セット制御チャネルに、演出セットをセットアップします。
 * [in]
 *	iProdSetCh	演出セット制御チャネル番号(0〜ProdSetCh_Max)
 *	pProdSet	演出セット(NULL=不可)
 * [out]
 *	無し
 */
static void ProdSetCh_SetupProdSet(int iProdSetCh, const ProdSet* pProdSet) {
	ST_ProdSetCh* pProdSetCh;
	int i;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdOrdCh_SetupProdOrdList()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdOrdCh_SetupProdOrdList()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	if((unsigned)iProdSetCh > ProdSetCh_Max) { DIE(); } /* 演出セット制御チャネル番号が範囲外 */
	if(pProdSet == NULL) { DIE(); } /* NULL=不可 */
	/* 演出セット制御チャネルを取得します。 */
	pProdSetCh = &stProdSeq.TBL_ProdSetCh[iProdSetCh];
	/* 演出セットバッファに残っている演出セットの、演出順序リストをセットアップしながら破棄して行くループです。
	 * この処理は必要です。個々の演出セットの保証時間が0でも、セットアップせずに破棄してはいけません。
	 * ProdOrd_Flag_Ensureフラグがセットされている演出順序を、確実に実行する必要があるからです。
	 */
	for(;;) {
		/* 保証時間カウンタが残っていたら… */
		if(pProdSetCh->WarrantCounter > 0) {
			/* 演出セットバッファの末尾に、演出セットを追加します。 */
			for(i = 0; i < ProdSetCh_ProdSetBuffer_Size; i++) {
				if(pProdSetCh->pProdSetBuffer[i] == NULL) {
					pProdSetCh->pProdSetBuffer[i] = pProdSet;
					goto L_EXIT; /* ここまで */
				}
			}
			/* 演出セットバッファに空きが無ければ、演出セットを破棄します。 */
			goto L_EXIT; /* ここまで */
		}
		/* 演出セットバッファが、空ならば… */
		if(pProdSetCh->pProdSetBuffer[0] == NULL) {
			/* 演出セットの演出順序リストをセットアップします。 */
			ProdOrdCh_SetupProdOrdList(iProdSetCh/*=iProdOrdCh*/, pProdSet->pProdOrdList);
			/* 保証時間カウンタを、設定します。 */
			pProdSetCh->WarrantCounter = pProdSet->Warrant;
			goto L_EXIT; /* ここまで */
		}
		/* 演出セットバッファの先頭にある、演出セットの演出順序リストをセットアップします。 */
		ProdOrdCh_SetupProdOrdList(iProdSetCh/*=iProdOrdCh*/, pProdSetCh->pProdSetBuffer[0]->pProdOrdList);
		/* 保証時間カウンタを、設定します。 */
		pProdSetCh->WarrantCounter = pProdSetCh->pProdSetBuffer[0]->Warrant;
		/* 演出セットバッファの先頭にある、演出セットを削除します。 */
		memmove(&pProdSetCh->pProdSetBuffer[0],
			&pProdSetCh->pProdSetBuffer[1],
			sizeof(ProdSet*) * (ProdSetCh_ProdSetBuffer_Size - 1));
		pProdSetCh->pProdSetBuffer[(ProdSetCh_ProdSetBuffer_Size - 1)] = NULL;
	}
L_EXIT:
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

/* 演出セット制御チャネルを、実行します。
 * [in]
 *	iProdSetCh	演出セット制御チャネル番号(0〜ProdSetCh_Max)
 * [out]
 *	無し
 */
static void ProdSetCh_Exec(int iProdSetCh) {
	ST_ProdSetCh* pProdSetCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdOrdCh_SetupProdOrdList()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdOrdCh_SetupProdOrdList()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	if((unsigned)iProdSetCh > ProdSetCh_Max) { DIE(); } /* 演出セット制御チャネル番号が範囲外 */
	/* 演出セット制御チャネルを取得します。 */
	pProdSetCh = &stProdSeq.TBL_ProdSetCh[iProdSetCh];
	/* 演出セットバッファが、空でなければ… */
	while(pProdSetCh->pProdSetBuffer[0] != NULL) {
		/* 保証時間カウンタが残っていたら… */
		if(pProdSetCh->WarrantCounter > 0) {
			break; /* 抜けます */
		}
		/* 演出セットバッファの先頭にある、演出セットの演出順序リストをセットアップします。 */
		ProdOrdCh_SetupProdOrdList(iProdSetCh/*=iProdOrdCh*/, pProdSetCh->pProdSetBuffer[0]->pProdOrdList);
		/* 保証時間カウンタを、設定します。 */
		pProdSetCh->WarrantCounter = pProdSetCh->pProdSetBuffer[0]->Warrant;
		/* 演出セットバッファの先頭にある、演出セットを削除します。 */
		memmove(&pProdSetCh->pProdSetBuffer[0],
			&pProdSetCh->pProdSetBuffer[1],
			sizeof(ProdSet*) * (ProdSetCh_ProdSetBuffer_Size - 1));
		pProdSetCh->pProdSetBuffer[(ProdSetCh_ProdSetBuffer_Size - 1)] = NULL;
	}
	/* 次回のために、保証時間カウンタを減らします。 */
	if(pProdSetCh->WarrantCounter > 0) {
		pProdSetCh->WarrantCounter--;
	}

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

/* 演出セット制御チャネルの、保証時間カウンタをクリアします。
 * [in]
 *	iProdSetCh	演出セット制御チャネル番号(0〜ProdSetCh_Max)
 * [out]
 *	無し
 */
static void ProdSetCh_ClearWarrantCounter(int iProdSetCh) {
	ST_ProdSetCh* pProdSetCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdOrdCh_SetupProdOrdList()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdOrdCh_SetupProdOrdList()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	if((unsigned)iProdSetCh > ProdSetCh_Max) { DIE(); } /* 演出セット制御チャネル番号が範囲外 */
	/* 演出セット制御チャネルを取得します。 */
	pProdSetCh = &stProdSeq.TBL_ProdSetCh[iProdSetCh];
	/* 演出セットバッファが、空でなければ… */
	while(pProdSetCh->pProdSetBuffer[0] != NULL) {
		/* 演出セットバッファの先頭にある、演出セットの演出順序リストをセットアップします。 */
		ProdOrdCh_SetupProdOrdList(iProdSetCh/*=iProdOrdCh*/, pProdSetCh->pProdSetBuffer[0]->pProdOrdList);
		/* 演出セットバッファの先頭にある、演出セットを削除します。 */
		memmove(&pProdSetCh->pProdSetBuffer[0],
			&pProdSetCh->pProdSetBuffer[1],
			sizeof(ProdSet*) * (ProdSetCh_ProdSetBuffer_Size - 1));
		pProdSetCh->pProdSetBuffer[(ProdSetCh_ProdSetBuffer_Size - 1)] = NULL;
	}
	/* 保証時間カウンタを、クリアします。 */
	pProdSetCh->WarrantCounter = 0;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/****************************************************************************
 *	演出制御チャネル
 ****************************************************************************/

/* 演出制御チャネルを、実行します。
 * [in]
 *	iProdCh		演出制御チャネル
 * [out]
 *	無し
 */
void ProdCh_Exec(int iProdCh) {
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdOrdCh_Exec()経由で、演出データセットアップ関数が呼び出され、ProdSetCh_Exec()を実行する前に、影響が生じることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdOrdCh_Exec()経由で、演出データセットアップ関数が呼び出され、ProdSetCh_Exec()を実行する前に、影響が生じることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

//{{2012/09/19:変更
//	ProdSetCh_Exec(iProdCh);
//	ProdOrdCh_Exec(iProdCh);
//↓2012/09/19:変更
//↓ * Wed Sep 19 15:18:34 JST 2012 Naoyuki Sawa
//↓ - ProdOrdCh_SetupProdOrdList()内のコメントを参照してください。
	ProdOrdCh_Exec(iProdCh);
	ProdSetCh_Exec(iProdCh);
//}}2012/09/19:変更

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/* 全ての演出制御チャネルを、実行します。
 * [in]
 *	無し
 * [out]
 *	無し
 */
void ProdCh_ExecAll() {
	int iProdCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdCh_Exec()経由で、演出データセットアップ関数が呼び出され、次の演出制御チャネルのProdCh_Exec()を実行する前に、影響が生じることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdCh_Exec()経由で、演出データセットアップ関数が呼び出され、次の演出制御チャネルのProdCh_Exec()を実行する前に、影響が生じることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	/* 全ての演出制御チャネルを、実行します。 */
	for(iProdCh = 0; iProdCh <= ProdCh_Max; iProdCh++) {
		ProdCh_Exec(iProdCh);
	}

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

/* 演出制御チャネルの、保証時間カウンタをクリアします。
 * [in]
 *	iProdCh		演出制御チャネル
 * [out]
 *	無し
 */
void ProdCh_ClearWarrantCounter(int iProdCh) {
	ProdSetCh_ClearWarrantCounter(iProdCh);
}

/* 全ての演出制御チャネルの、保証時間カウンタをクリアします。
 * [in]
 *	無し
 * [out]
 *	無し
 */
void ProdCh_ClearWarrantCounterAll() {
	int iProdCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdCh_ClearWarrantCounter()経由で、演出データセットアップ関数が呼び出され、次の演出制御チャネルのProdCh_ClearWarrantCounter()を実行する前に、影響が生じることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdCh_ClearWarrantCounter()経由で、演出データセットアップ関数が呼び出され、次の演出制御チャネルのProdCh_ClearWarrantCounter()を実行する前に、影響が生じることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	/* 全ての演出制御チャネルの、保証時間カウンタをクリアします。 */
	for(iProdCh = 0; iProdCh <= ProdCh_Max; iProdCh++) {
		ProdCh_ClearWarrantCounter(iProdCh);
	}

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

/* 演出制御チャネルを、リセットします。
 * [in]
 *	iProdCh		演出制御チャネル
 * [out]
 *	無し
 * [note]
 *	- 本関数は、演出セット制御チャネルと演出順序制御チャネルをリセットしますが、演出デバイスを停止しません。
 *	  演出デバイスは、アプリケーション定義であり、本システムの管理外だからです。
 *	- 必要に応じて、アプリケーションが明示的に、演出デバイスを停止してください。
 *	  全演出デバイスを停止する演出コマンドリストを定義しておき、ProdCmdList_Setup() で実行するのが適切です。
 */
void ProdCh_Reset(int iProdCh) {
	if((unsigned)iProdCh > ProdCh_Max) { DIE(); } /* 演出制御チャネル番号が範囲外 */
	memset(&stProdSeq.TBL_ProdCh   [iProdCh], 0, sizeof(ST_ProdCh   ));
	memset(&stProdSeq.TBL_ProdSetCh[iProdCh], 0, sizeof(ST_ProdSetCh));
	memset(&stProdSeq.TBL_ProdOrdCh[iProdCh], 0, sizeof(ST_ProdOrdCh));
}

/* 全ての演出制御チャネルを、リセットします。
 * [in]
 *	無し
 * [out]
 *	無し
 *	- 本関数は、演出セット制御チャネルと演出順序制御チャネルをリセットしますが、演出デバイスを停止しません。
 *	  演出デバイスは、アプリケーション定義であり、本システムの管理外だからです。
 *	- 必要に応じて、アプリケーションが明示的に、演出デバイスを停止してください。
 *	  全演出デバイスを停止する演出コマンドリストを定義しておき、ProdCmdList_Setup() で実行するのが適切です。
 */
void ProdCh_ResetAll() {
	int iProdCh;
	for(iProdCh = 0; iProdCh <= ProdCh_Max; iProdCh++) {
		ProdCh_Reset(iProdCh);
	}
}

/*--------------------------------------------------------------------------*/

/* 演出制御チャネルに、トリガを送信します。
 * [in]
 *	iProdCh		演出制御チャネル
 * [out]
 *	無し
 * [note]
 *	//{{2013/09/13:変更
 *	////{{2013/04/13:変更
 *	////- 本関数は、演出コマンドセットアップ処理のクリティカルセクションに入れる必要はありません。
 *	////  演出データセットアップ関数が呼び出される可能性があるのは、本関数末尾のProdSetCh_SetupProdSet()経由だけであり、
 *	////  そのタイミングで本モジュールの関数が使用されても、内部状態が不完全だったり、処理順序が入れ替わる等の問題は生じないからです。
 *	////↓2013/04/13:変更
 *	//- 本関数は、演出コマンドリストセットアップ処理のクリティカルセクションに入れる必要はありません。
 *	//  演出データセットアップ関数が呼び出される可能性があるのは、本関数末尾のProdSetCh_SetupProdSet()経由だけであり、
 *	//  そのタイミングで本モジュールの関数が使用されても、内部状態が不完全だったり、処理順序が入れ替わる等の問題は生じないからです。
 *	////}}2013/04/13:変更
 *	//↓2013/09/13:変更
 *	- 本関数は、演出コマンドリストセットアップ処理のクリティカルセクションに入れないのが適切です。
 *	  演出データセットアップ関数が呼び出される可能性があるのは、ProdCh_ClearWarrantCounter()経由とProdSetCh_SetupProdSet()経由です。
 *	  ProdCh_ClearWarrantCounter()に起因する演出データセットアップ処理は、ProdSetCh_SetupProdSet()よりも先に実行することが自然です。
 *	  (保証時間カウンタを待っていた、既存の演出データセットアップ処理を行ってから、新しい演出セットをセットアップするのが自然だから)
 *	  従って本関数は、演出コマンドリストセットアップ処理のクリティカルセクションに入れないのが適切です。
 *	//}}2013/09/13:変更
 */
void ProdCh_SendTrigger(int iProdCh, int Trigger) {
	ST_ProdCh* pProdCh;
	const ProdSet* pProdSet;

	if((unsigned)iProdCh > ProdCh_Max) { DIE(); } /* 演出制御チャネル番号が範囲外 */
	if((unsigned)Trigger > 255) { DIE(); } /* トリガが範囲外 */			//{{2013/09/13:変更}}
	/* 演出制御チャネルを取得します。 */
	pProdCh = &stProdSeq.TBL_ProdCh[iProdCh];
	/* 演出セットリストが無ければ、何もしません。 */
	if(pProdCh->pProdSetList == NULL) {
		return; /* ここまで */
	}
	/* トリガに対応する演出セットを検索します。 */
	pProdSet = ProdSetList_FindTrigger(pProdCh->pProdSetList, Trigger);
	/* トリガに対応する演出セットが無ければ、何もしません。 */
	if(pProdSet == NULL) {
		return; /* ここまで */
	}
//{{2013/09/13:削除
//	/* このトリガの初回の送信時ならば… */
//	if((pProdCh->TriggerMask & (1<<Trigger)) == 0) {
//		/* 送信済みトリガマスクをセットします。 */
//		pProdCh->TriggerMask |= (1<<Trigger);
//	/* このトリガの二回目以降の送信時ならば… */
//	} else {
//		/* ProdSet_Flag_Multiフラグがセットされていなければ、セットアップしません。 */
//		if((pProdSet->Flag & ProdSet_Flag_Multi) == 0) {
//			return; /* ここまで */
//		}
//	}
//}}2013/09/13:削除
//{{2013/09/13:追加
	/* ProdSet_Flag_Immediateフラグがセットされていたら… */
	if((pProdSet->Flag & ProdSet_Flag_Immediate) != 0) {
		/* 保証時間カウンタをクリアします。 */
		ProdCh_ClearWarrantCounter(iProdCh);
	}
//}}2013/09/13:追加
	/* 演出セット制御チャネルに、演出セットをセットアップします。 */
	ProdSetCh_SetupProdSet(iProdCh, pProdSet);
}

/* 全ての演出制御チャネルに、トリガを送信します。
 * [in]
 *	無し
 * [out]
 *	無し
 */
void ProdCh_SendTriggerAll(int Trigger) {
	int iProdCh;

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdCh_SendTrigger()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdCh_SendTrigger()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更

	/* 全ての演出制御チャネルに、トリガを送信します。 */
	for(iProdCh = 0; iProdCh <= ProdCh_Max; iProdCh++) {
		ProdCh_SendTrigger(iProdCh, Trigger);
	}

//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

/*--------------------------------------------------------------------------*/

/* 演出セットリストを、演出制御チャネルにセットアップします。
 * [in]
 *	pProdSetList	演出セットリスト(NULL=無し)
 *	iProdCh		演出制御チャネル番号(0〜ProdCh_Max)
 * [out]
 *	無し
 * [note]
 *	//{{2013/04/03:変更
 *	//- 本関数は、演出コマンドセットアップ処理のクリティカルセクションに入れる必要はありません。
 *	//  演出データセットアップ関数が呼び出される可能性があるのは、本関数末尾のProdCh_SendTrigger()経由だけであり、
 *	//  そのタイミングで本モジュールの関数が使用されても、内部状態が不完全だったり、処理順序が入れ替わる等の問題は生じないからです。
 *	//↓2013/04/03:変更
 *	//{{2013/04/13:変更
 *	//- 本関数も、演出コマンドセットアップ処理のクリティカルセクションに入れるよう、変更しました。
 *	//  クリアトリガの追加に伴い、クリアトリガとセットアップトリガの処理順序を保証する必要が、新たに生じたためです。
 *	//↓2013/04/13:変更
 *	- 本関数も、演出コマンドリストセットアップ処理のクリティカルセクションに入れるよう、変更しました。
 *	  クリアトリガの追加に伴い、クリアトリガとセットアップトリガの処理順序を保証する必要が、新たに生じたためです。
 *	//}}2013/04/13:変更
 *	//}}2013/04/03:変更
 */
void ProdSetList_Setup(const ProdSet* pProdSetList, int iProdCh) {
	ST_ProdCh* pProdCh;

//{{2013/04/03:追加
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションに入ります。
//	 * - ProdCh_SendTrigger()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
//	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
//	 */
//	ProdCmd_Setup_EnterCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションに入ります。
	 * - ProdCh_SendTrigger()経由で、演出データセットアップ関数が呼び出され、本モジュールの関数が使用されることを防ぐためです。
	 *   クリティカルセクションに入ることで、実際の演出データセットアップ関数呼び出しを、(最短でも)本関数の最後まで遅延します。
	 */
	ProdCmdList_Setup_EnterCS();
//}}2013/04/13:変更
//}}2013/04/03:追加

	if((unsigned)iProdCh > ProdCh_Max) { DIE(); } /* 演出制御チャネル番号が範囲外 */
	/* 演出制御チャネルを取得します。 */
	pProdCh = &stProdSeq.TBL_ProdCh[iProdCh];
//{{2013/04/03:追加
	/* 暗黙の、クリアトリガを送信します。 */
	ProdCh_SendTrigger(iProdCh, 255/*クリア時*/);					//{{2013/09/13:変更}}
//}}2013/04/03:追加
	/* 演出セットリストを格納します。 */
	pProdCh->pProdSetList = pProdSetList; /* NULL=可 */
//{{2013/09/13:削除
//	/* 送信済みトリガマスクを、クリアします。 */
//	pProdCh->TriggerMask = 0;
//}}2013/09/13:削除
	/* 暗黙の、セットアップトリガを送信します。 */
	ProdCh_SendTrigger(iProdCh, 0/*セットアップ時*/);

//{{2013/04/03:追加
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	ProdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	ProdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
//}}2013/04/03:追加
}

