#include "app.h"

/****************************************************************************
 *	定数定義
 ****************************************************************************/

/****************************************************************************
 *	構造体定義
 ****************************************************************************/
/* 回胴情報 */
typedef struct _ST_Reel {
	uint8_t		Stat;		/* 状態(0=停止中,1=回転中,2=減速中) */
	uint8_t		Ofs;		/* オフセット */		//0⇒15
	uint8_t		Pos;		/* 絵柄位置 */			//20⇒0
	uint8_t		StpPos;		/* 停止位置 */			//0〜20
} ST_Reel;
/*--------------------------------------------------------------------------*/
/* メインタスク */
typedef struct _ST_Main {
	TASK*		Task;		/* タスク */
	uint8_t		Credit;		/* 貯留枚数 */			//0〜50
	uint8_t		Replay;		/* 再遊技中 */			//0,1
	uint8_t		Bonus;		/* 役連遊技中 */		//0,1
	uint8_t		PayCnt;		/* 払出枚数カウンタ */		//0⇒ 11	//(ｲ)一回ﾉ入賞ﾆﾖﾘ獲得ｽﾙｺﾄｶﾞﾃﾞｷﾙ遊技ﾒﾀﾞﾙ等ﾉ数ﾊ､遊技ﾒﾀﾞﾙﾆｱﾂﾃﾊ十五枚ｦ､遊技球ﾆｱﾂﾃﾊ七十五個ｦ､ｿﾚｿﾞﾚ超ｴﾙﾓﾉﾃﾞﾅｸ､ｶﾂ､当該入賞ﾆ使用ｼﾀ遊技ﾒﾀﾞﾙ等ﾉ十五倍ｦ超ｴﾙﾓﾉﾃﾞﾅｲｺﾄ｡											⇒	11
	uint16_t	BnsCnt;		/* 役連払出枚数カウンタ */	//0⇒264	//(ﾜ)第二種特別役物ﾆ係ﾙ一ﾉ役物連続作動装置ﾊ､ｿﾉ作動中ﾆ､普通役物若ｼｸﾊ第一種特別役物ﾉ作動ﾆ係ﾙ条件装置ｶﾞ作動ｼﾀﾄｷ又ﾊ遊技ﾒﾀﾞﾙﾆｱﾂﾃﾊ253枚ｦ､遊技球ﾆｱﾂﾃﾊ1315個ｦ､ｿﾚｿﾞﾚ超ｴﾅｲ数ﾉｳﾁｶﾗｱﾗｶｼﾞﾒ定ﾒﾗﾚﾀ一ﾉ数ｦ超ｴﾙ遊技ﾒﾀﾞﾙ等ｶﾞ獲得ｻﾚﾀﾄｷﾊ､ｿﾉ作動ｦ終了ｽﾙﾓﾉﾃﾞｱﾙｺﾄ｡	⇒	11*23=253	⇒	役連遊技回数=23+1=24	⇒	11*24=264
	ST_Reel		Reel[3];	/* 回胴情報 */
	uint8_t		Sw;		/* スイッチ状態 */		//Sw_*
	uint8_t		SwEdge;		/* スイッチ押下エッジ */	//Sw_*
	uint16_t	Led;		/* LED */			//Led_*
	/*--- ここより下は、毎遊技クリアする ---*/
	uint8_t		ClrTop;
	uint16_t	DemTim;		/* 遊技待機デモ移行タイマ */	//SEC(60)⇒0
	uint8_t		MedTim;		/* メダル間隔タイマ */		//*⇒0
	uint8_t		Bet;		/* 投入枚数 */			//0⇒3
	uint8_t		CreBet;		/* 貯留投入枚数 */		//3⇒0
	uint8_t		HitCd;		/* 条件装置 */			//HitCd_*
	uint8_t		Order;		/* 押順 */			//Slot_Order_*
	uint8_t		StpCnt;		/* 回胴停止数 */		//0⇒3
	uint8_t		StpPic[3][3];	/* 枠内停止絵柄 */		//Pict_*
	uint8_t		HitFlg[5];	/* 絵柄組合せ */		//HitFlg_*
	uint8_t		Pay;		/* 払出枚数 */			//0,11
} ST_Main;

/****************************************************************************
 *	変数定義
 ****************************************************************************/
static ST_Main stMain;

/****************************************************************************
 *	関数宣言
 ****************************************************************************/
static int  Main_TaskProc(void* pParam);
/*--------------------------------------------------------------------------*/
static void Main_Schedule();	/* 周期処理 */
static void Main_Update();	/* 画面更新 */
/*--------------------------------------------------------------------------*/
static void Main_PwrOn();	/* 電源投入処理 */
static void Main_GmSta();	/* 遊技開始処理 */
static void Main_MdBet();	/* メダル投入処理 */
static void Main_InLot();	/* 内部抽選処理 */
static void Main_RlSta();	/* 回胴開始処理 */
static void Main_RlStp();	/* 回胴停止処理 */
static void Main_PzChk();	/* 入賞判定処理 */
static void Main_MdPay();	/* メダル払出処理 */
static void Main_GmEnd();	/* 遊技終了処理 */

/****************************************************************************
 *	初期化
 ****************************************************************************/
void Main_Init() {
//{{`最初からやり直し'の機能を付けなかったので不要。
//	/* 既にタスクが存在する場合、削除する。 */
//	if(stMain.Task) { task_kill(stMain.Task); }
//	/* 構造体をクリアする。 */
//	memset(&stMain, 0, sizeof stMain);
//}}`最初からやり直し'の機能を付けなかったので不要。
	/* タスクを作成する。 */
	stMain.Task = task_create(0, Main_TaskProc, NULL, 0x600);
}

/****************************************************************************
 *	
 ****************************************************************************/
static int Main_TaskProc(void* pParam) {
	Main_PwrOn();		/* 電源投入処理 */
	for(;;) {
		Main_GmSta();	/* 遊技開始処理 */
		Main_MdBet();	/* メダル投入処理 */
		Main_InLot();	/* 内部抽選処理 */
		Main_RlSta();	/* 回胴開始処理 */
		Main_RlStp();	/* 回胴停止処理 */
		Main_PzChk();	/* 入賞判定処理 */
		Main_MdPay();	/* メダル払出処理 */
		Main_GmEnd();	/* 遊技終了処理 */
	}
}

/****************************************************************************
 *	周期処理
 ****************************************************************************/
static void Main_Schedule() {
	int iReel, iRow;
	ST_Reel* pReel;
	/* フレームイベントを待つ。 */
	event_wait(stApp.FrmEvt);
	/* 入力更新 */
	stMain.SwEdge = (stMain.Sw ^ stApp.Sw) & stApp.Sw;
	stMain.Sw = stApp.Sw;
	/* 各回胴について… */
	for(iReel = 0; iReel < 3; iReel++) {
		pReel = &stMain.Reel[iReel];
		/* 停止中(0)でなければ…(=回転中(1),又は,減速中(2)ならば) */
		if(pReel->Stat) {
			/* オフセットを進め、一絵柄を超えたら… */
			pReel->Ofs += Reel_Spd;
//{{アプリケーション処理
			if(stApp.ApExec == Ap_Fast) { pReel->Ofs += (Reel_Pic_OY * 4); }	//高速オートプレイ中ならば、即、引き込める速度とする。
//}}アプリケーション処理
			while(pReel->Ofs >= Reel_Pic_OY) {	//Reel_SpdとReel_Pic_OYの調整によっては、一度で二絵柄を超える可能性も有るので、ifでなくwhileで判定する。
				/* オフセットを戻し、絵柄位置を進める。 */
				pReel->Ofs -= Reel_Pic_OY;
				pReel->Pos = pReel->Pos ? (pReel->Pos - 1) : 20;
				/* 減速中(2)ならば、停止位置に達したら、停止する。 */
				if(pReel->Stat == 2/*減速中*/) {
					if(pReel->Pos == pReel->StpPos) {
						pReel->Stat = 0/*停止中*/;
						pReel->Ofs  = 0;
						/* コマンド(回胴停止) */
						SendCmd(((Cmd_RlStp_L+iReel)<<8)|
							(pReel->StpPos      <<0));	//停止位置(0〜20)
						/* 枠内停止絵柄を取得する。 */
						for(iRow = 0; iRow < 3; iRow++) {
							stMain.StpPic[iRow][iReel] = Slot_GetReelPict(TBL_Reel, stMain.Reel[iReel].StpPos + iRow, iReel);
						}
					}
				}
			}
		}
	}
	/* 画面更新 */
	Main_Update();
}

/****************************************************************************
 *	画面更新
 ****************************************************************************/
static void Main_Update() {
	int iReel, iPos, iPict, x, y;
	ST_Reel* pReel;
	/*--- 回胴 ---*/
	/* クリッピング範囲を、窓枠の上端〜下端に設定する。 */
	render.top    = Reel_Wnd_Y;
	render.bottom = Reel_Wnd_Y + Reel_Wnd_H;
	x = (Reel_Wnd_X + Reel_Pic_X);	/* 左回胴の絵柄座標 */
	/* 各回胴について… */
	for(iReel = 0; iReel < 3; iReel++) {
		pReel = &stMain.Reel[iReel];
		iPos = pReel->Pos;				/* 上段の絵柄位置 */
		y = (Reel_Wnd_Y + Reel_Pic_Y) + pReel->Ofs;	/* 上段の絵柄座標 */
		/* 絵柄位置を上へ戻す。窓枠内の上端絵柄になったら、抜ける。 */
		do {
			if(--iPos < 0) { iPos = 20; }
		} while((y -= Reel_Pic_OY) > Reel_Wnd_Y);
		/* 絵柄を描画する。窓枠内の下端絵柄を描画したら、抜ける。 */
		do {
			iPict = Slot_GetReelPict(TBL_Reel, iPos, iReel);
			sprite_draw(x, y, SPR_PIC_SV + (iPict - Pict_Sv), 0);
			if(++iPos > 20) {
				iPos = 0;
				render_rectangle_fill(&render, x - 1, y + Reel_Pic_H, Reel_Wnd_W, 1, 2);	/* 帯の繋ぎ目 */
			}
		} while((y += Reel_Pic_OY) < (Reel_Wnd_Y + Reel_Wnd_H));
		x += Reel_Wnd_OX;	/* 次の回胴の絵柄座標 */
	}
	/* クリッピング範囲を解除する。 */
	render.top    = 0;
	render.bottom = DISP_Y;
	/*--- LED ---*/
	stApp.Led = stMain.Led;		/* アプリケーションタスクでの筐体描画用 */
	if(stMain.Led & Led_1bet) { render_point(&render, Led_1bet_X, Led_1bet_Y, 0); }
	if(stMain.Led & Led_2bet) { render_point(&render, Led_2bet_X, Led_2bet_Y, 0); }
	if(stMain.Led & Led_3bet) { render_point(&render, Led_3bet_X, Led_3bet_Y, 0); }
	if(stMain.Led & Led_Sta ) { render_point(&render, Led_Sta_X , Led_Sta_Y , 0); }
	if(stMain.Led & Led_Rep ) { render_point(&render, Led_Rep_X , Led_Rep_Y , 0); }
	if(stMain.Led & Led_Ins ) { render_point(&render, Led_Ins_X , Led_Ins_Y , 0); }
	/*--- 7SEG ---*/
	render_printf(&render, Seg_Cre_X, Seg_Cre_Y, 2, 0, "%2d", stMain.Credit);
	if(stMain.Bonus) { render_printf(&render, Seg_Bns_X, Seg_Bns_Y, 2, 0, "%3d", stMain.BnsCnt); }
	render_printf(&render, Seg_Pay_X, Seg_Pay_Y, 2, 0, "%2d", stMain.PayCnt);
}

/****************************************************************************
 *	遊技ロック
 ****************************************************************************/
static void Main_Delay(int i) {
//{{アプリケーション処理
	if(stApp.ApExec == Ap_Fast) { return; }	//高速オートプレイ中ならば、遊技ロック無しとする。
//}}アプリケーション処理
	while(--i > 0) { Main_Schedule(); }
}

/****************************************************************************
 *	電源投入処理
 ****************************************************************************/
static void Main_PwrOn() {
	/* 回胴の初期位置を設定する。 */
	stMain.Reel[0].Pos = 9;	//|ｾﾌﾞﾝ |ﾍﾞﾙ  |ｽｲｶ  |
	stMain.Reel[1].Pos = 8;	//|ﾁｪﾘｰ |ｾﾌﾞﾝ |ﾁｪﾘｰ |
	stMain.Reel[2].Pos = 9;	//|ｽｲｶ  |ﾁｪﾘｰ |ｾﾌﾞﾝ |
}

/****************************************************************************
 *	遊技開始処理
 ****************************************************************************/
static void Main_GmSta() {
	void *pStart, *pEnd;
	/* 毎遊技クリアする変数をクリアする。 */
	pStart = &stMain.ClrTop;
	pEnd   = &stMain + 1;
	memset(pStart, 0, pEnd - pStart);
	/* 再遊技中ならば… */
	if(stMain.Replay) {
		/* REPLAY LEDを点灯する。 */
		stMain.Led |= Led_Rep;
	/* 再遊技中でなければ… */
	} else {
		/* REPLAY LEDを消灯する。 */
		stMain.Led &= ~Led_Rep;
		/* 遊技待機デモ移行タイマを設定する。 */
		stMain.DemTim = SEC(60);
	}
	/* コマンド(遊技開始) */
	SendCmd((Cmd_GmSta    <<8)|
		(stMain.Bonus <<1)|	//[1]=役連遊技中フラグ
		(stMain.Replay<<0));	//[0]=再遊技中フラグ
}

/****************************************************************************
 *	メダル投入処理
 ****************************************************************************/
static void Main_MdBet() {
	/* メダル間隔タイマをクリアする。 */
	stMain.MedTim = 0;
	for(;;) {
		/* フレームイベントを待つ。 */
		Main_Schedule();
		/* メダル間隔タイマが動作中ならば、メダル間隔タイマを減らす。 */
		if(stMain.MedTim) { stMain.MedTim--; }
//{{アプリケーション処理
		if(stApp.ApExec == Ap_Fast) { stMain.MedTim = 0; }	//高速オートプレイ中ならば、メダル間隔タイマ無しとする。
//}}アプリケーション処理
		/* MAXBET LED,START LED,INSERT LEDを消灯しておく。この後の処理で点灯する。 */
		stMain.Led &= ~(Led_Max|Led_Sta|Led_Ins);
		/* 再遊技中ならば… */
		if(stMain.Replay) {
			/* 規定数投入済でなければ… */
			if(stMain.Bet < 3) {
				/* メダル間隔タイマが停止していたら… */
				if(!stMain.MedTim) {
					/* メダル間隔タイマを設定する。 */
					stMain.MedTim = 3;	//調整可
					/* 投入枚数を増やす。 */
					stMain.Bet++;
					/* コマンド(メダル投入) */
					SendCmd((Cmd_MdBet <<8)|
						(stMain.Bet<<0));	//投入枚数(0〜3)
				}
			}
		/* 再遊技中でなければ… */
		} else {
			/* メダルが投入されたら… */
			if(stMain.SwEdge & Sw_Med) {
				/* 投入枚数が限界でなければ… */
				if(stMain.Bet < 3) {
//{{アプリケーション処理
					/* 持ちメダル枚数を減らす。 */
					if(!stApp.Medal--) { stApp.Invest += 1000; stApp.Medal += 50; }
					/* メダル投入アニメーションを開始する。 */
					stApp.MedPos = 1;
//}}アプリケーション処理
					/* 投入枚数を増やす。 */
					stMain.Bet++;
					/* コマンド(メダル投入) */
					SendCmd((Cmd_MdBet <<8)|
						(stMain.Bet<<0));	//投入枚数(0〜3)
				/* 貯留枚数が限界でなければ… */
				} else if(stMain.Credit < 50) {
//{{アプリケーション処理
					/* 持ちメダル枚数を減らす。 */
					if(!stApp.Medal--) { stApp.Invest += 1000; stApp.Medal += 50; }
					/* メダル投入アニメーションを開始する。 */
					stApp.MedPos = 1;
//}}アプリケーション処理
					/* 貯留枚数を増やす。 */
					stMain.Credit++;
					/* コマンド(メダル貯留) */
					SendCmd((Cmd_MdCre    <<8)|
						(stMain.Credit<<0));	//貯留枚数(0〜50)
				}
			}
			/* 貯留投入中でなければ… */
			if(!stMain.CreBet) {
				/* 投入枚数が限界でなく,かつ,貯留枚数が有れば… */
				if((stMain.Bet < 3) && stMain.Credit) {
					/* MAXBETボタンとメダル投入以外の操作が行われていなければ… */
					if(!(stMain.Sw & ~(Sw_Max|Sw_Med))) {
						/* MAXBETボタンが押されたら… */
						if(stMain.SwEdge & Sw_Max) {
							/* 貯留投入枚数を設定する。 */
							stMain.CreBet = 3;	//ここでは常に3をセットする。貯留枚数が3未満だった場合は、貯留投入中の処理にて貯留投入を中止する。
						/* MAXBETボタンが押されなければ… */
						} else {
							/* MAXBET LEDを点灯する。 */
							stMain.Led |= Led_Max;
						}
					}
				}
			}
			/* 貯留投入中ならば… */
			if(stMain.CreBet) {
				/* 投入枚数が限界でなく,かつ,貯留枚数が有れば… */
				if((stMain.Bet < 3) && stMain.Credit) {
					/* メダル間隔タイマが停止していたら… */
					if(!stMain.MedTim) {
						/* メダル間隔タイマを設定する。 */
						stMain.MedTim = 3;	//調整可
						/* 貯留投入枚数を減らす。 */
						stMain.CreBet--;
						/* 貯留枚数を減らす。 */
						stMain.Credit--;
						/* 投入枚数を増やす。 */
						stMain.Bet++;
						/* コマンド(メダル投入) */
						SendCmd((Cmd_MdBet <<8)|
							(stMain.Bet<<0));	//投入枚数(0〜3)
					}
				/* 投入枚数が限界か,又は,貯留枚数が無ければ… */
				} else {
					/* 貯留投入を中止する。 */
					stMain.CreBet = 0;
				}
			}
			/* 投入枚数が限界でないか,又は,貯留枚数が最大でなければ… */
			if((stMain.Bet < 3) || (stMain.Credit < 50)) {
				/* INSERT LEDを点灯する。 */
				stMain.Led |= Led_Ins;
			}
			/* 投入枚数が有れば… */
			if(stMain.Bet) {
				/* 遊技待機デモ移行タイマを停止する。 */
				stMain.DemTim = 0;
			/* 投入枚数が無ければ… */
			} else {
				/* 遊技待機デモ移行タイマが動作中ならば、遊技待機デモ移行タイマを減らす。
				 * 遊技待機デモ移行タイマがタイムアウトにより停止したら… */
				if(stMain.DemTim && !--stMain.DemTim) {
					/* 遊技待機デモ移行する。 */
					/* コマンド(遊技待機デモ) */
					SendCmd(Cmd_DmSta<<8);	//コマンドパラメータ無し
				}
			}
		}
		/* 遊技待機デモ移行タイマが停止していたら…(メダル投入,又は,遊技待機デモ移行) */
		if(!stMain.DemTim) {
			/* 1BET,2BET,3BET LEDを消灯,又は,点灯する。 */
			stMain.Led &= ~(Led_1bet|Led_2bet|Led_3bet);
			if(stMain.Bet >= 1) { stMain.Led |= Led_1bet; }
			if(stMain.Bet >= 2) { stMain.Led |= Led_2bet; }
			if(stMain.Bet >= 3) { stMain.Led |= Led_3bet; }
			/* 払出枚数カウンタをクリアする。 */
			stMain.PayCnt = 0;
		}
		/* 貯留投入中でなければ… */
		if(!stMain.CreBet) {
			/* 投入枚数が限界ならば… */
			if(stMain.Bet >= 3) {
				/* スタートレバー以外の操作が行われていなければ… */
				if(!(stMain.Sw & ~Sw_Lev)) {
					/* スタートレバーが押されたら… */
					if(stMain.SwEdge & Sw_Lev) {
						break; /* 抜ける */
					/* スタートレバーが押されなければ… */
					} else {
						/* START LEDを点灯する。 */
						stMain.Led |= Led_Sta;
					}
				}
			}
		}
//{{アプリケーション処理
		/* 全ての操作が行われておらず、貯留投入中でもなければ… */
		if(!stMain.Sw && !stMain.CreBet) {
			switch(stMain.Bet) {
			case 0:
				if(!stMain.Replay) {
					switch(stMain.Credit) {
					case 0:  stApp.OkReady = Ok_Med_Med_Med; break;
					case 1:  stApp.OkReady = Ok_Max_Med_Med; break;
					case 2:  stApp.OkReady = Ok_Max_Med;     break;
					default: stApp.OkReady = Ok_Max;         break;
					}
				}
				break;
			case 1:
				if(!stMain.Replay) {
					switch(stMain.Credit) {
					case 0:  stApp.OkReady = Ok_Med_Med; break;
					case 1:  stApp.OkReady = Ok_Max_Med; break;
					default: stApp.OkReady = Ok_Max;     break;
					}
				}
				break;
			case 2:
				if(!stMain.Replay) {
					switch(stMain.Credit) {
					case 0:  stApp.OkReady = Ok_Med; break;
					default: stApp.OkReady = Ok_Max; break;
					}
				}
				break;
			default:
				stApp.OkReady = Ok_Lev;
				break;
			}
		}
//}}アプリケーション処理
	}
	/* MAXBET LED,START LED,INSERT LEDを消灯する。 */
	stMain.Led &= ~(Led_Max|Led_Sta|Led_Ins);
}

/****************************************************************************
 *	内部抽選処理
 ****************************************************************************/
static void Main_InLot() {
//{{アプリケーション処理
	/* 一般遊技中ならば… */
	if(!stMain.Bonus) {
		/* 総回転数を増やす。 */
		if(stApp.TotalG < 9999/*調整可*/) { stApp.TotalG++; }			//ボーナス中のG数は含めない
		/* スタート回転数を増やす。 */
		if(stApp.StartG < 9999/*調整可*/) { stApp.StartG++; }			//ボーナス中のG数は含めない
	}
	/* 差枚数履歴を格納する。 */
	if(stApp.SamHisG < (ARRAY_SIZE(stApp.SamHis) - 1)) { stApp.SamHisG++; }		//ボーナス中のG数も含める
	stApp.SamHis[stApp.SamHisG] = stApp.SamHis[stApp.SamHisG - 1] - stMain.Bet;
//}}アプリケーション処理
	/* 内部抽選を行う。 */
	stMain.HitCd = !stMain.Bonus ? LotHitCd() : HitCd_Zk;
	/* コマンド(条件装置) */
	SendCmd((Cmd_HitCd   <<8)|
		(stMain.HitCd<<0));	//条件装置(0〜HitCd_Size-1)
}

/****************************************************************************
 *	回胴開始処理
 ****************************************************************************/
static void Main_RlSta() {
	int iReel;
	ST_Reel* pReel;
	/* 本来はここでウェイトだが省略 */
	/** no job **/
	/* 各回胴について… */
	for(iReel = 0; iReel < 3; iReel++) {
		pReel = &stMain.Reel[iReel];
		pReel->Stat = 1/*回転中*/;
	}
	/* コマンド(回胴開始) */
	SendCmd(Cmd_RlSta<<8);	//コマンドパラメータ無し
}

/****************************************************************************
 *	回胴停止処理
 ****************************************************************************/
static void Main_RlStp() {
	int iReel, iReel1, iReel2, iPos, iHkmCnt;
	ST_Reel* pReel;
	for(;;) {
		/* フレームイベントを待つ。 */
		Main_Schedule();
		/* 左,中,右停止ボタンLEDを消灯しておく。この後の処理で点灯する。 */
		stMain.Led &= ~(Led_1st|Led_2nd|Led_3rd);
		/* 全ての操作が行われていなければ… */
		if(!stMain.Sw) {
			/* 全ての回胴が停止したら抜ける。 */	//第三停止を長押ししている間は抜けない。
			if(!stMain.Reel[0].Stat && !stMain.Reel[1].Stat && !stMain.Reel[2].Stat) { break; }
			/* 回転中である回胴の停止ボタンLEDを点灯する。 */
			if(stMain.Reel[0].Stat == 1/*回転中*/) { stMain.Led |= Led_1st; }
			if(stMain.Reel[1].Stat == 1/*回転中*/) { stMain.Led |= Led_2nd; }
			if(stMain.Reel[2].Stat == 1/*回転中*/) { stMain.Led |= Led_3rd; }
		}
		/* 各回胴について… */
		for(iReel = 0; iReel < 3; iReel++) {
			pReel = &stMain.Reel[iReel];
			/* この回胴が回転中ならば… */
			if(pReel->Stat == 1/*回転中*/) {
				/* この回胴の停止ボタン以外の操作が行われていなければ… */
				if(!(stMain.Sw & ~(Sw_1st << iReel))) {
					/* この回胴の停止ボタンが押されたら… */
					if(stMain.SwEdge & (Sw_1st << iReel)) {
						pReel->Stat = 2/*減速中*/;
						iPos = (pReel->Pos ? : 21) - 1;	/* 1個上の絵柄位置を基準に引込む */
						/* コマンド(停止ボタン押下) */
						SendCmd(((Cmd_BtnOn_L+iReel)<<8)|
							(iPos               <<0));	//押下位置(0〜20)
						/* 停止数を増やす。 */
						switch(++stMain.StpCnt) {
						/* 第1停止 */
						case 1:
							/* 第1停止回胴番号を格納する。 */
							stMain.Order = iReel;
							/* 1リール停止制御を行う。 */
							iHkmCnt = Slot_GetStpCtl1(&stStpCtl, stMain.HitCd, iReel, iPos);
							break;
						/* 第2停止 */
						case 2:
							/* 第1停止と第2停止回胴番号から、押順番号を求める。 */
							stMain.Order = Slot_FindOrder(stMain.Order, iReel);
							/* 2リール停止制御を行う。 */
							iReel1 = Slot_GetOrderReel(stMain.Order, 0);
							iHkmCnt = Slot_GetStpCtl2(&stStpCtl, stMain.HitCd, iReel1, iReel, stMain.Reel[iReel1].StpPos, iPos);
							break;
						/* 第3停止 */
						case 3:
							/* 3リール停止制御を行う。 */
							iReel1 = Slot_GetOrderReel(stMain.Order, 0);
							iReel2 = Slot_GetOrderReel(stMain.Order, 1);
							iHkmCnt = Slot_GetStpCtl3(&stStpCtl, stMain.HitCd, iReel1, iReel2, iReel, stMain.Reel[iReel1].StpPos, stMain.Reel[iReel2].StpPos, iPos);
							break;
						default: DIE();
						}
						if((iPos -= iHkmCnt) < 0) { iPos += 21; }
						pReel->StpPos = iPos;
					}
				}
			}
		}
		/* 全ての操作が行われていなければ… */
		if(!stMain.Sw) {
			     if(stMain.Reel[0].Stat == 1/*回転中*/) { stApp.OkReady = Ok_1st; }
			else if(stMain.Reel[1].Stat == 1/*回転中*/) { stApp.OkReady = Ok_2nd; }
			else if(stMain.Reel[2].Stat == 1/*回転中*/) { stApp.OkReady = Ok_3rd; }
		}
	}
}

/****************************************************************************
 *	入賞判定処理
 ****************************************************************************/
static void Main_PzChk() {
	int iLine;
	/* 入賞判定を行う。 */
	Slot_CheckPrize(stMain.StpPic, TBL_HitFlg, HitFlg_Size, stMain.HitFlg);
	/* 各ラインについて… */
	for(iLine = 0; iLine < 5; iLine++) {
		/* 条件装置に含まれない絵柄組合せが入賞したら、不正入賞エラーとする。 */
		if(!GetHitCd_HitFlg(stMain.HitCd, stMain.HitFlg[iLine])) { DIE(); }
		/* 払出枚数を加算する。 */
		stMain.Pay += GetHitFlg_Pay(stMain.HitFlg[iLine]);
		/* コマンド(入賞判定) */
		SendCmd(((Cmd_HtFlg_T+iLine) <<8)|
			(stMain.HitFlg[iLine]<<0));	//絵柄組合せ番号
	}
	if(stMain.Pay > 11) { stMain.Pay = 11; } //当機種の1遊技の最大払出枚数は11枚 */
	/* コマンド(払出枚数) */
	SendCmd((Cmd_MdPay <<8)|
		(stMain.Pay<<0));	//払出枚数
}

/****************************************************************************
 *	メダル払出処理
 ****************************************************************************/
static void Main_MdPay() {
	/* メダル間隔タイマをクリアする。 */
	stMain.MedTim = 0;
	/* 払出枚数カウンタが、払出枚数未満ならば… */
	while(stMain.PayCnt < stMain.Pay) {
		/* 貯留枚数が最大でなければ… */
		if(stMain.Credit < 50) {
			/* メダル間隔タイマが停止していたら… */
			if(!stMain.MedTim) {
				/* メダル間隔タイマを設定する。 */
				stMain.MedTim = 2;	//調整可
				/* 貯留枚数を増やす。 */
				stMain.Credit++;
				/* 払出枚数カウンタを増やす。 */
				stMain.PayCnt++;
				/* 役連遊技中ならば、役連払出枚数カウンタを増やす。 */
				if(stMain.Bonus) { stMain.BnsCnt++; }
			}
		/* 貯留枚数が最大ならば… */
		} else {
			/* メダル間隔タイマが停止していたら… */	//本来、実機ではホッパーの速度に従う。ソフトでタイミングを計らない。
			if(!stMain.MedTim) {				//本来、実機ではホッパーの速度に従う。ソフトでタイミングを計らない。
				/* メダル間隔タイマを設定する。 */	//本来、実機ではホッパーの速度に従う。ソフトでタイミングを計らない。
				stMain.MedTim = 2;	//調整可	//本来、実機ではホッパーの速度に従う。ソフトでタイミングを計らない。
//{{アプリケーション処理
				/* 持ちメダル枚数を増やす。 */
				stApp.Medal++;
//}}アプリケーション処理
				/* 払出枚数カウンタを増やす。 */
				stMain.PayCnt++;
				/* 役連遊技中ならば、役連払出枚数カウンタを増やす。 */
				if(stMain.Bonus) { stMain.BnsCnt++; }
			}
		}
		/* フレームイベントを待つ。 */
		Main_Schedule();
		/* メダル間隔タイマが動作中ならば、メダル間隔タイマを減らす。 */
		if(stMain.MedTim) { stMain.MedTim--; }
//{{アプリケーション処理
		if(stApp.ApExec == Ap_Fast) { stMain.MedTim = 0; }	//高速オートプレイ中ならば、メダル間隔タイマ無しとする。
//}}アプリケーション処理
	}
}

/****************************************************************************
 *	遊技終了処理
 ****************************************************************************/
static void Main_GmEnd() {
	int iLine, iCmdL = 0;
//{{アプリケーション処理
	/* 小役当選回数を登録する。 */
	stApp.HitCnt[stMain.HitCd]++;	//本来は内部抽選処理で行うべきだが、そうするとメニュー画面を見ると先バレしてしまうので、遊技終了処理で行うことにした。
	/* 差枚数履歴を格納する。 */
	stApp.SamHis[stApp.SamHisG] += stMain.Replay ? stMain.Bet : stMain.Pay;
//}}アプリケーション処理
	/* 再遊技中フラグをクリアしておく。この後の処理でセットする。 */
	stMain.Replay = 0;
	/* 各ラインについて… */
	for(iLine = 0; iLine < 5; iLine++) {
		switch(stMain.HitFlg[iLine]) {
		case HitFlg_Rp:
			/* コマンドパラメータの、再遊技作動フラグをセットする。 */
			iCmdL |= (1<<0);
			break;
		case HitFlg_Bo:
			/* コマンドパラメータの、役連作動フラグをセットする。 */
			iCmdL |= (1<<1);
			break;
		}
	}
	/* 役連遊技中,かつ,役連払出枚数が253枚を超えたら… */
	if((stMain.Bonus) && (stMain.BnsCnt > 253)) {
		/* コマンドパラメータの、役連終了フラグをセットする。 */
		iCmdL |= (1<<2);
	}
	/* コマンド(遊技終了) */
	SendCmd((Cmd_GmEnd<<8)|
		(iCmdL    <<0));	//[0]=再遊技作動,[1]=役連作動,[2]=役連終了
	/* コマンドパラメータのフラグによって… */
	switch(iCmdL) {
	case (1<<0):	/* 再遊技作動 */
		/* 再遊技中フラグをセットする。 */
		stMain.Replay = 1;
		/* 遊技ロック(再遊技作動時) */
		Main_Delay(SEC(1.0));
		break;
	case (1<<1):	/* 役連作動 */
//{{アプリケーション処理
		/* ボーナス回数を増やす。 */
		stApp.Bonus++;
		/* ボーナス履歴を格納する。 */
		memmove(&stApp.BnsHis[1], &stApp.BnsHis[0], (sizeof stApp.BnsHis[0]) * (ARRAY_SIZE(stApp.BnsHis) - 1));
		stApp.BnsHis[0] = stApp.StartG;
//}}アプリケーション処理
		/* 役連遊技中フラグをセットし、役連払出枚数をクリアする。 */
		stMain.Bonus  = 1;
		stMain.BnsCnt = 0;
		/* 遊技ロック(役連作動時) */
		Main_Delay(SEC(1.0));
		break;
	case (1<<2):	/* 役連終了 */
		/* 遊技ロック(役連終了時) */
		Main_Delay(SEC(2.0));
		/* 役連遊技中フラグと、役連払出枚数をクリアする。 */
		stMain.Bonus  = 0;
		stMain.BnsCnt = 0;
//{{アプリケーション処理
		/* スタート回転数をクリアする。 */
		stApp.StartG  = 0;
//}}アプリケーション処理
		break;
	}
}

