/*	
 *	clipprds.c
 *
 *	演出制御
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2015 Naoyuki Sawa
 *
 *	* Mon Jul 02 23:56:03 JST 2012 Naoyuki Sawa
 *	- 1stリリース。
 *	* Wed Sep 19 15:18:34 JST 2012 Naoyuki Sawa
 *	- 演出順序リストのセットアップと同時に、1フレーム実行するように変更しました。
 *	  PrdSetList_Setup() が処理を戻す前に、セットアップトリガ の0フレーム処理(有れば)が実行されるようになりました。
 *	  PrdCh_SendTrigger()が処理を戻す前に、    指定したトリガ の0フレーム処理(有れば)が実行されるようになりました。
 *	* Wed Sep 19 15:18:34 JST 2012 Naoyuki Sawa
 *	- 演出コマンドバッファの仕組みを追加しました。
 *	  この変更により、演出デバイスの演出データフィルタ関数、及び、演出デバイスの演出データセットアップ関数の中から、本モジュールの関数を呼び出せるようになりました。
 *	  ・たとえば、特定の演出データを受け取ったときに、PrdSetList_Setup()を呼び出して、新しい演出セットリストをセットアップすることができます。
 *	  　現在実行中の演出制御チャネル自身に対して行うこともできますし、別の演出制御チャネルに対して行うこともできます。
 *	  ・たとえば、特定の演出データを受け取ったときに、PrdCh_SendTrigger()を呼び出して、任意のトリガを送信することができます。
 *	  　現在実行中の演出制御チャネル自身に対して送信することもできますし、別の演出制御チャネルに対して送信することもできます。
 *	- これまでは、演出デバイスの演出データセットアップ関数内で、直接PrdSetList_Setup()やPrdCh_SendTrigger()等を呼び出すことはできませんでした。
 *	  PrdSetList_Setup()やPrdCh_SendTrigger()の途中で再帰呼び出しが発生することになり、内部状態が不正になってしまっていたからです。
 *	  そのため、これまでは、演出デバイスの演出データセットアップ関数内ではグローバルフラグをセットしておき、PrdSetList_Setup()やPrdCh_SendTrigger()等の終了後に、グローバルフラグを確認して処理を行う不便がありました。
 *	  今回の変更により、上記のような再帰呼び出しの問題は発生しなくなったため、演出デバイスの演出データセットアップ関数内で、直接PrdSetList_Setup()やPrdCh_SendTrigger()等を呼び出すことができ、便利になったと思います。
 *	- 【注意】今回の変更後も、演出デバイスの演出データセットアップ関数内で、PrdCh_Reset()とPrdCh_ResetAll()を呼び出すことはできません。
 *	  PrdCh_Reset()とPrdCh_ResetAll()は、強制的に内部状態をクリアする関数であり、演出コマンドバッファのクリティカルセクションによって保護されないからです。
 *	* Sat Nov 10 18:19:56 JST 2012 Naoyuki Sawa
 *	- PrdDev_CancelSetup()、PrdDev_GetPrdDat()を追加しました。
 *	* Mon Feb 04 23:44:12 JST 2013 Naoyuki Sawa
 *	- PrdCh_Exec()とPrdCh_ExecAll()内の処理を、演出コマンドセットアップ処理のクリティカルセクションに入れました。
 *	* Tue Feb 05 11:35:37 JST 2013 Naoyuki Sawa
 *	- PrdCh_ClearWarrantCounter()、PrdCh_ClearWarrantCounterAll()を追加しました。
 *	* Wed Apr 03 18:05:33 JST 2013 Naoyuki Sawa
 *	- 暗黙のクリアトリガ送信仕様を追加しました。
 *	  変更した関数は、PrdSetList_Setup()のみです。
 *	* Wed Apr 10 18:39:31 JST 2013 Naoyuki Sawa
 *	- ワークエリアをST_PrdSeq構造体の一か所にまとめるために、大幅なソース変更を行いました。
 *	  主な変更内容は、定義位置の変更であり、アルゴリズムはほぼ変更ありません。
 *	- ワークエリアをST_PrdSeq構造体の一か所にまとめた目的は、今後、演出の途中状態をまるごとバックアップするためです。
 *	* Tue Apr 16 22:45:58 JST 2013 Naoyuki Sawa
 *	- クリティカルセクション内で、演出コマンドを個別にコピーして保持するのでなく、演出コマンドリストのまま保持するよう変更しました。
 *	  バッファのメモリ節約と、コピー時間の短縮のためです。
 *	- グローバル関数の定義には、変更ありません。
 *	  ただし、PrdCmdList_Setup()に指定する演出コマンドリストは、不変であること。(即ち、ROM,又は,実行されるまで変更しないRAM上にあること)
 *	  実際にはさほど厳密な制約ではなく、クリティカルセクションを抜けるまで不変であれば良いだけなので、余り気にする必要はありません。
 *	  演出デバイスのセットアップ関数内から、再帰的にPrdCmdList_Setup()を呼び出す場合にのみ、注意が必要です。
 *	  具体的には、セットアップ関数のスタック上に演出コマンドリストを作成してPrdCmdList_Setup()を呼び出したりすると、正しく動作しません。
 *	* Mon Jul 01 17:42:17 JST 2013 Naoyuki Sawa
 *	- 演出コマンドリスト,演出順序リスト,演出セットリストの、終端を示す方法を変更しました。
 *	  これまでは、特殊なフィールド値を持つ終端レコードによって示していました。今後は、最終レコードのEndフラグを用いて示すよう変更します。
 *	  この変更によって、終端レコードを配置することが不要になり、データ容量が節約できます。
 *	- これまでは、演出デバイス番号0を、終端レコードを表す特殊なフィールド値として使用していましたが、今回の変更によって不要になったため、
 *	  今後は、演出デバイス番号0も利用できるようになりました。即ち、演出デバイス番号は(1〜PrdDev_Max)でなく、(0〜PrdDev_Max)となります。
 *	* Fri Sep 13 20:13:42 JST 2013 Naoyuki Sawa
 *	- 同一トリガを二回以上セットアップしようとしたときに、二回目以降のセットアップを無視する仕様を削除しました。
 *	  当仕様を削除した理由は:
 *	  ・実際に使ってみて、効果的であるケースが少なかったこと。	//二回目以降のセットアップを自動的に無視することが、却って、バグを発見しづらくする原因になることもあった
 *	  ・この挙動が効果的なケースに対しても、アプリケーション側で比較的簡単に対応できること。
 *	  当仕様の削除に伴い、以下の変更を行いました:
 *	  ・同一トリガを二回以上セットアップするためのフラグであった、PrdSet_Flag_Multiが不要になり、削除しました。
 *	  ・ST_PrdCh.TriggerMaskフィールドが不要になり、削除しました。
 *	  ・トリガ番号の範囲が、変更前は最大31でしたが、変更後は最大255になりました。(ST_PrdCh.TriggerMaskのビット数の制限に囚われなくなったため)
 *	  ・トリガ番号の範囲変更に伴い、暗黙のクリアトリガのトリガ番号を、31⇒255に変更しました。
 *	- 演出セット構造体のフラグに、保障時間カウンタをクリアする機能である、PrdSet_Flag_Immediateを追加しました。
 *	  これまでは、アプリケーションが明示的にPrdCh_ClearWarrantCounter()等を呼び出して保障時間カウンタをクリアする必要が有り、データ化しづらい問題がありました。
 *	  今後も、PrdCh_ClearWarrantCounter()等でクリアすることもできますが、それに加えて、保障時間カウンタをクリアしたいトリガの演出セットにフラグ指定できるようになりました。
 *	* Sat Feb 08 14:57:06 JST 2014 Naoyuki Sawa
 *	- 演出デバイスのフィルタ関数とセットアップ関数の格納方法を変更しました。
 *	- これまでは、演出デバイス毎に、個別の関数ポインタを格納していましたが、
 *	  今後は、共通の関数とし、アプリケーション側で振り分けることにしました。
 *	- こう変更した理由は、演出デバイス毎に個別の、関数ポインタを格納するメモリを節約するためです。
 *	  これまで使用した限り、個別の関数が直接呼び出されることの利点は薄かったので、問題ありません。
 *	- 今回の変更に伴い、PrdDev_Install()の使用方法を変更しました。
 *	* Wed Aug 27 20:38:48 JST 2014 Naoyuki Sawa
 *	- ST_PrdSeq.env_PrdDev_CancelSetupを実体⇒ポインタに変更しました。
 *	  理由1. これまでは、アプリケーションが、PrdCmdList_Setup()を経由せずに直接、演出デバイスのフィルタ関数,又は,セットアップ関数を呼出し、
 *	         演出デバイスのフィルタ関数,又は,セットアップ関数の中でPrdDev_CancelSetup()を呼出すと、予測できない不正な動作になっていました。
 *	         PrdCmd_Setup()でのenv_PrdDev_CancelSetupに対するsetjmp()が行われた後かを、PrdDev_CancelSetup()では判断できなかったからです。
 *	         今回の変更により、env_PrdDev_CancelSetupをポインタに変更したので、PrdDev_CancelSetup()で上記を判断できるようになりました。
 *	         今後は、上記のケースでPrdDev_CancelSetup()内でエラー停止するようになり、バグが見つけ易くなりました。
 *	  理由2. このジャンプバッファは、PrdCmd_Setup()の呼出し期間中のみ必要な変数であり、当構造体の中に静的に確保することはメモリの無駄です。
 *	         EPSONライブラリの場合、jmp_bufは16ワード(64バイト)の変数であり、64バイトの無駄となっていました。
 *	         今後は、env_PrdDev_CancelSetupの実体はPrdCmd_Setup()のスタック上に確保し、当構造体の中にはポインタ(4バイト)のみを確保します。
 *	         当構造体のサイズが、60バイト節約できました。
 *	* Wed Feb 04 21:16:57 JST 2015 Naoyuki Sawa
 *	- P/ECE以外で使用する時に、PrdDev_Max,PrdCh_Max,PrdSetCh_PrdSetBuffer_Sizeをアプリケーション側で定義出来るようにしました。
 *	  P/ECE以外で使用する時に、PrdDev_Maxを大幅に増やす場合が有るが、P/ECEには過大であり、大幅に増やした値に固定したくないための対策です。
 *	- 具体的には、clipprds.hをインクルードするよりも先にPrdDev_Maxを定義しておけば、clipprds.h内ではPrdDev_Maxを定義しないようにしました。
 *	  PrdCh_Max,PrdSetCh_PrdSetBuffer_Sizeについても同様に、clipprds.hよりも先に定義しておけば、先に定義した値が有効となります。
 *	- 上記はあくまで、P/ECE以外で当モジュールを単独で使用する場合であり、P/ECEで使用する場合は、clipprds.h内で定義している値に固定となることに注意してください。
 *	  なぜなら、P/ECEで使用する場合はCLiPライブラリの1モジュールとして予めコンパイルしておくので、アプリケーションへのリンク時に変更することは出来ないからです。
 *	* Sat Feb 07 00:00:00 JST 2015 Naoyuki Sawa
 *	- ST_PrdOrdCh.RepeatCounter,ST_PrdOrdCh.DelayCounterをint⇒unsigned shortに変更しました。元々unsigned shortで充分だったのでこの変更による挙動への影響は有りません。
 *	  厳密にはST_PrdOrdCh.RepeatCounterはunsigned charでも充分なのですがそうするとパディングが生じるだけなのでunsigned shortでもメモリ効率は同じです。
 *	- ST_PrdSetCh.WarrantCounterをint⇒unsigned shortに変更しました。元々unsigned shortで充分だったのでこの変更による挙動への影響は有りません。
 *	* Sat Feb 07 07:00:19 JST 2015 Naoyuki Sawa
 *	- PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
 *	  演出制御データをアドレス0ベースでリンク,ROM化しておき、任意アドレスにロード(,又は,バイナリリンク)して使用できるようにするための機能です。
 *	- ST_PrdSeq.AddressOffsetのアドレスオフセット対象であることを示すために、PrdSet.pPrdOrdList,PrdOrd.pPrdCmdListのフィールド名の先頭に'_'を追加し、PrdSet._pPrdOrdList,PrdOrd._pPrdCmdListとしました。
 *	  他の同名のフィールドや変数に間違えてオフセット加算してしまう危険を低らすためです。
 *	- この機能を追加した理由は、演出制御データが大きい場合、プログラムとは別にコンパイル&リンクしておいて、プログラムをリビルドする時間を短く出来るようにするためです。
 *	  演出制御データがアドレス非依存だったならばこんな特殊処理は必要無いのですが、実際にはポインタを含んでいるため、こんな特殊処理が必要になりました。
 *	- 特殊処理が行われるタイミングは、当モジュールの内部処理でPrdSet._pPrdOrdList,及び,PrdOrd._pPrdCmdListを読み出した時だけであることに注意してください。
 *	  当モジュールの内部処理で、ROM上にバイナリリンクされた,又は,RAM上にロードされた、演出制御データのポインタフィールドを読み出す時にリロケートを行うイメージです。
 *	  アプリケーションが、PrdCmdList_Setup()やPrdSetList_Setup()を呼び出した場合、それらに引き渡したポインタには、アドレスオフセットは加算されません。
 *	- PrdDef_AddressOffset()を呼び出さないか,又は,0を設定すれば、これまでどおりの動作になります。
 *	  これまでどおり、演出制御データをアプリケーションプログラムに含めてコンパイル・リンクする場合は、PrdDef_AddressOffset()を呼び出さないか,又は,0を設定してください。
 */
#include "clip.h"

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

static ST_PrdSeq stPrdSeq;	//{{2013/04/10:追加}}

/****************************************************************************
 *	演出制御データ
 ****************************************************************************/

//{{2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
void PrdDef_AddressOffset(int AddressOffset) {
	/* アドレスオフセットを格納します。 */
	stPrdSeq.AddressOffset = AddressOffset;
}
static const PrdCmd* PrdOrd_pPrdCmdList(const PrdOrd* pPrdOrd) {	//当モジュールの内部処理でPrdOrd._pPrdCmdListフィールドを参照する時は常にこの関数を使用してください。直接参照してはいけません。stPrdSeq.AddressOffsetが設定されている場合にリロケートを行うためです。
	return (const PrdCmd*)((int)pPrdOrd->_pPrdCmdList + stPrdSeq.AddressOffset);
}
static const PrdOrd* PrdSet_pPrdOrdList(const PrdSet* pPrdSet) {	//当モジュールの内部処理でPrdSet._pPrdOrdListフィールドを参照する時は常にこの関数を使用してください。直接参照してはいけません。stPrdSeq.AddressOffsetが設定されている場合にリロケートを行うためです。
	return (const PrdOrd*)((int)pPrdSet->_pPrdOrdList + stPrdSeq.AddressOffset);
}
//}}2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* 演出順序制御チャネルを、停止します。
 * [in]
 *	iPrdOrdCh	演出順序制御チャネル番号(0〜PrdOrdCh_Max)
 * [out]
 *	無し
 */
static void PrdOrdCh_Stop(int iPrdOrdCh) {
	ST_PrdOrdCh* pPrdOrdCh;

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

	if((unsigned)iPrdOrdCh > PrdOrdCh_Max) { DIE(); } /* 演出順序制御チャネル番号が範囲外 */
	/* 演出順序制御チャネルを取得します。 */
	pPrdOrdCh = &stPrdSeq.TBL_PrdOrdCh[iPrdOrdCh];
	/* 停止していたら、何もしません。 */
	if(pPrdOrdCh->pPrdOrdList == NULL) {
		goto L_EXIT; /* ここまで */
	}
//{{2013/07/01:変更
//	/* 演出順序リストが終端に到達するまで… */
//	while(pPrdOrdCh->pPrdOrdList->pPrdCmdList != NULL) {
//		/* PrdOrd_Flag_Ensureフラグがセットされているか、又は、遅延時間が"停止時"ならば… */
//		if(((pPrdOrdCh->pPrdOrdList->Flag & PrdOrd_Flag_Ensure) != 0) ||
//		    (pPrdOrdCh->pPrdOrdList->Delay == 65535/*停止時*/)) {
//			/* 演出コマンドリストをセットアップします。繰り返し回数は考慮しません。 */
//			PrdCmdList_Setup(pPrdOrdCh->pPrdOrdList->pPrdCmdList);
//		}
//		/* 演出順序リストを進めます。 */
//		pPrdOrdCh->pPrdOrdList++;
//	}
//↓2013/07/01:変更
	for(;;) {
		/* PrdOrd_Flag_Ensureフラグがセットされているか、又は、遅延時間が"停止時"ならば… */
		if(((pPrdOrdCh->pPrdOrdList->Flag & PrdOrd_Flag_Ensure) != 0) ||
		    (pPrdOrdCh->pPrdOrdList->Delay == 65535/*停止時*/)) {
			/* 演出コマンドリストをセットアップします。繰り返し回数は考慮しません。 */
		    //{{2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		    //	PrdCmdList_Setup(pPrdOrdCh->pPrdOrdList->pPrdCmdList);
		    //↓2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
			PrdCmdList_Setup(PrdOrd_pPrdCmdList(pPrdOrdCh->pPrdOrdList));
		    //}}2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		}
		/* 演出順序の、Endフラグがセットされていたら… */
		if((pPrdOrdCh->pPrdOrdList->Flag & PrdOrd_Flag_End) != 0) {
			break; /* 抜けます */
		}
		/* 演出順序リストを進めます。 */
		pPrdOrdCh->pPrdOrdList++;
	}
//}}2013/07/01:変更
	/* 演出順序制御チャネルをクリアします。 */
	memset(pPrdOrdCh, 0, sizeof(ST_PrdOrdCh));
L_EXIT:
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	PrdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	PrdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

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

//{{2012/09/19:追加
static void PrdOrdCh_Exec(int iPrdOrdCh);
//}}2012/09/19:追加

/* 演出順序制御チャネルに、演出順序リストをセットアップします。
 * [in]
 *	iPrdOrdCh	演出順序制御チャネル番号(0〜PrdOrdCh_Max)
 *	pPrdOrdList	演出順序リスト(NULL=不可)
 * [out]
 *	無し
 */
static void PrdOrdCh_SetupPrdOrdList(int iPrdOrdCh, const PrdOrd* pPrdOrdList) {
	ST_PrdOrdCh* pPrdOrdCh;

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

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

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

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

/* 演出順序制御チャネルを、実行します。
 * [in]
 *	iPrdOrdCh	演出順序制御チャネル番号(0〜PrdOrdCh_Max)
 * [out]
 *	無し
 */
static void PrdOrdCh_Exec(int iPrdOrdCh) {
	ST_PrdOrdCh* pPrdOrdCh;

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

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

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

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

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

/* 演出セット制御チャネルに、演出セットをセットアップします。
 * [in]
 *	iPrdSetCh	演出セット制御チャネル番号(0〜PrdSetCh_Max)
 *	pPrdSet	演出セット(NULL=不可)
 * [out]
 *	無し
 */
static void PrdSetCh_SetupPrdSet(int iPrdSetCh, const PrdSet* pPrdSet) {
	ST_PrdSetCh* pPrdSetCh;
	int i;

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

	if((unsigned)iPrdSetCh > PrdSetCh_Max) { DIE(); } /* 演出セット制御チャネル番号が範囲外 */
	if(pPrdSet == NULL) { DIE(); } /* NULL=不可 */
	/* 演出セット制御チャネルを取得します。 */
	pPrdSetCh = &stPrdSeq.TBL_PrdSetCh[iPrdSetCh];
	/* 演出セットバッファに残っている演出セットの、演出順序リストをセットアップしながら破棄して行くループです。
	 * この処理は必要です。個々の演出セットの保証時間が0でも、セットアップせずに破棄してはいけません。
	 * PrdOrd_Flag_Ensureフラグがセットされている演出順序を、確実に実行する必要があるからです。
	 */
	for(;;) {
		/* 保証時間カウンタが残っていたら… */
		if(pPrdSetCh->WarrantCounter > 0) {
			/* 演出セットバッファの末尾に、演出セットを追加します。 */
			for(i = 0; i < PrdSetCh_PrdSetBuffer_Size; i++) {
				if(pPrdSetCh->pPrdSetBuffer[i] == NULL) {
					pPrdSetCh->pPrdSetBuffer[i] = pPrdSet;
					goto L_EXIT; /* ここまで */
				}
			}
			/* 演出セットバッファに空きが無ければ、演出セットを破棄します。 */
			goto L_EXIT; /* ここまで */
		}
		/* 演出セットバッファが、空ならば… */
		if(pPrdSetCh->pPrdSetBuffer[0] == NULL) {
			/* 演出セットの演出順序リストをセットアップします。 */
		    //{{2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		    //	PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, pPrdSet->pPrdOrdList);
		    //↓2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
			PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, PrdSet_pPrdOrdList(pPrdSet));
		    //}}2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
			/* 保証時間カウンタを、設定します。 */
			pPrdSetCh->WarrantCounter = pPrdSet->Warrant;
			goto L_EXIT; /* ここまで */
		}
		/* 演出セットバッファの先頭にある、演出セットの演出順序リストをセットアップします。 */
	    //{{2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
	    //	PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, pPrdSetCh->pPrdSetBuffer[0]->pPrdOrdList);
	    //↓2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, PrdSet_pPrdOrdList(pPrdSetCh->pPrdSetBuffer[0]));
	    //}}2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		/* 保証時間カウンタを、設定します。 */
		pPrdSetCh->WarrantCounter = pPrdSetCh->pPrdSetBuffer[0]->Warrant;
		/* 演出セットバッファの先頭にある、演出セットを削除します。 */
		memmove(&pPrdSetCh->pPrdSetBuffer[0],
			&pPrdSetCh->pPrdSetBuffer[1],
			sizeof(PrdSet*) * (PrdSetCh_PrdSetBuffer_Size - 1));
		pPrdSetCh->pPrdSetBuffer[ (PrdSetCh_PrdSetBuffer_Size - 1)] = NULL;
	}
L_EXIT:
//{{2013/04/13:変更
//	/* 演出コマンドセットアップ処理のクリティカルセクションを抜けます。 */
//	PrdCmd_Setup_LeaveCS();
//↓2013/04/13:変更
	/* 演出コマンドリストセットアップ処理のクリティカルセクションを抜けます。 */
	PrdCmdList_Setup_LeaveCS();
//}}2013/04/13:変更
}

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

/* 演出セット制御チャネルを、実行します。
 * [in]
 *	iPrdSetCh	演出セット制御チャネル番号(0〜PrdSetCh_Max)
 * [out]
 *	無し
 */
static void PrdSetCh_Exec(int iPrdSetCh) {
	ST_PrdSetCh* pPrdSetCh;

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

	if((unsigned)iPrdSetCh > PrdSetCh_Max) { DIE(); } /* 演出セット制御チャネル番号が範囲外 */
	/* 演出セット制御チャネルを取得します。 */
	pPrdSetCh = &stPrdSeq.TBL_PrdSetCh[iPrdSetCh];
	/* 演出セットバッファが、空でなければ… */
	while(pPrdSetCh->pPrdSetBuffer[0] != NULL) {
		/* 保証時間カウンタが残っていたら… */
		if(pPrdSetCh->WarrantCounter > 0) {
			break; /* 抜けます */
		}
		/* 演出セットバッファの先頭にある、演出セットの演出順序リストをセットアップします。 */
	    //{{2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
	    //	PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, pPrdSetCh->pPrdSetBuffer[0]->pPrdOrdList);
	    //↓2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, PrdSet_pPrdOrdList(pPrdSetCh->pPrdSetBuffer[0]));
	    //}}2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		/* 保証時間カウンタを、設定します。 */
		pPrdSetCh->WarrantCounter = pPrdSetCh->pPrdSetBuffer[0]->Warrant;
		/* 演出セットバッファの先頭にある、演出セットを削除します。 */
		memmove(&pPrdSetCh->pPrdSetBuffer[0],
			&pPrdSetCh->pPrdSetBuffer[1],
			sizeof(PrdSet*) * (PrdSetCh_PrdSetBuffer_Size - 1));
		pPrdSetCh->pPrdSetBuffer[ (PrdSetCh_PrdSetBuffer_Size - 1)] = NULL;
	}
	/* 次回のために、保証時間カウンタを減らします。 */
	if(pPrdSetCh->WarrantCounter > 0) {
		pPrdSetCh->WarrantCounter--;
	}

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

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

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

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

	if((unsigned)iPrdSetCh > PrdSetCh_Max) { DIE(); } /* 演出セット制御チャネル番号が範囲外 */
	/* 演出セット制御チャネルを取得します。 */
	pPrdSetCh = &stPrdSeq.TBL_PrdSetCh[iPrdSetCh];
	/* 演出セットバッファが、空でなければ… */
	while(pPrdSetCh->pPrdSetBuffer[0] != NULL) {
		/* 演出セットバッファの先頭にある、演出セットの演出順序リストをセットアップします。 */
	    //{{2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
	    //	PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, pPrdSetCh->pPrdSetBuffer[0]->pPrdOrdList);
	    //↓2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		PrdOrdCh_SetupPrdOrdList(iPrdSetCh/*=iPrdOrdCh*/, PrdSet_pPrdOrdList(pPrdSetCh->pPrdSetBuffer[0]));
	    //}}2015/02/07追加:PrdDef_AddressOffset(),ST_PrdSeq.AddressOffsetを追加しました。
		/* 演出セットバッファの先頭にある、演出セットを削除します。 */
		memmove(&pPrdSetCh->pPrdSetBuffer[0],
			&pPrdSetCh->pPrdSetBuffer[1],
			sizeof(PrdSet*) * (PrdSetCh_PrdSetBuffer_Size - 1));
		pPrdSetCh->pPrdSetBuffer[ (PrdSetCh_PrdSetBuffer_Size - 1)] = NULL;
	}
	/* 保証時間カウンタを、クリアします。 */
	pPrdSetCh->WarrantCounter = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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