/*	
 *	cliplotr.h
 *
 *	抽選表ROM形式
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2015-2016 Naoyuki Sawa
 *
 *	* Wed Feb 18 21:49:13 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	- 当モジュールは、cliplot.cモジュールのラッパーとして動作し、以下の機能を追加します。
 *	  1. 抽選表を、アドレスでなく抽選表番号で指定する、関数インターフェイスを追加します。
 *	  2. 各抽選表の各列の各当選値が、何回当選したかをログとして記録する機能を追加します。
 *	     ログ機能は、LotRom_BeginLog()〜LotRom_EndLog()の間のみ有効となります。
 *	     LotRom_BeginLog()を呼び出さなければ、余分なメモリ消費も処理負荷も生じません。
 *	* Mon Mar 02 21:47:20 JST 2015 Naoyuki Sawa
 *	- ST_LotRom構造体のm_LotTblNo_Max,m_TBL_LotTblフィールドを削除しました。LotRom_Init()の_LotTblNo_Max引数を削除しました。
 *	  やや大幅な変更になので、変更前のコードは残していません。変更前のコードを見返したい場合は、前回のアーカイブを参照してください。
 *	  dLotTblC.exeがTBL_LotTblNo[0]に(LotTblNo_Max+1)を格納するようなったので、アプリケーションから明示的に指定する必要が無くなったからです。
 *	  詳細は/clip/tool/dLotTblC/winapp.hの同日のコメントを参照してください。
 *	* Fri Sep 11 21:09:04 JST 2015 Naoyuki Sawa
 *	- LotRom_DumpLog()が標準出力以外にも出力出来るよう、ストリームを指定する引数を追加しました。
 *	* Mon Oct 12 15:21:03 JST 2015 Naoyuki Sawa
 *	- USE_LOTROM_SEHシンボルを定義すると、cliplotr.c内のDIE()を全て、SEH_throw(LotRomException)に置き換えるようにしました。
 *	  使用方法はclipprp.hのUSE_PRP_SEHと同様です。clipprp.hの2015/10/11のコメントを参照してください。
 *	* Mon Oct 12 16:53:24 JST 2015 Naoyuki Sawa
 *	- LOT_draw_table_a(),LOT_draw_table_v()の引数順序を変更した事に伴い、LotRom_draw_v()の実装も変更しました。
 *	  LOT_get_table_weight_a(),LOT_get_table_weight_v()の引数順序を変更した事に伴い、LotRom_get_weight_a(),LotRom_get_weight_v()の引数順序と実装も変更しました。
 *	- LotRom_draw_l(),LotRom_draw_a()をアセンブラ化しました。
 *	  LotRom_get_weight_l(),LotRom_get_weight_a()をアセンブラ化しました。
 *	* Wed Oct 14 21:50:46 JST 2015 Naoyuki Sawa
 *	- clipseh.hにてSEH_info構造体に'msg'フィールドを追加した事に伴い、当モジュールのLotRom_throw()の実装も変更しました。
 *	* Fri Nov 06 21:43:13 JST 2015 Naoyuki Sawa
 *	- '_equally'版の関数を追加しました。
 *	  '_equally'版の関数は、抽選データのテスト用であり、高速化は不要だと思うので、アセンブラ化していません。	⇒{{2016/07/17追記:'_equally'版の関数をアセンブラ化しました。}}
 *	  詳細は、cliplot.hの同日のコメントを参照して下さい。
 *	- cliplot.hのUSE_LOT_EQUALLYシンボル定義の有無を参照して、当モジュールの関数宣言,及び,'_equally'版の関数のビルドを切り替えます。
 *	  Win32プロジェクトは、cliplotr.hよりも先に、cliplot.hをインクルードして下さい。
 *	  P/ECEプロジェクトならば、/clip/clip.h をインクルードするだけなので、インクルードの順序を気にする必要は有りません。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Sun Jul 17 22:34:56 JST 2016 Naoyuki Sawa
 *	- '_equally'版の関数をアセンブラ化しました。
 *	  今回アセンブラ化した関数は、LotRom_draw_equally_l(),LotRom_draw_equally_a()です。
 *	  LotRom_draw_equally_v()は、USE_LOTROM_LOGの条件コンパイルが有りアセンブラ化しづらいので、今回はアセンブラ化していません。
 *	* Sat Jul 23 21:58:20 JST 2016 Naoyuki Sawa
 *	- 抽選表ログの構造体を廃止し、ワークシート(多階層ハッシュテーブル)を利用するように変更しました。
 *	  この変更によってログ機能の実装が大幅に単純になり、もし今後ログ機能を変更する時も変更し易くなったと思います。
 *	  尚、変更前は抽選列毎の抽選回数を記録していましたが、変更後はその代わりに非当選回数を記録するようにしました。
 *	  特定の抽選列の階層以下に対してWorksheet_sum_l()を行えば、変更前と同様に抽選列毎の抽選回数を得ることも可能です。
 *	- LotRom_DumpLog()の抽選ログ出力形式を変更しました。
 *	  変更前は、抽選表を転置したような表形式で出力していましたが、実際には、あまり使いみちがありませんでした。
 *	  変更後は、「当選回数,抽選表番号(1〜65535),当選値(-1〜65535)[,抽選列id(0〜65535)[,抽選列id(0〜65535)...]」という形式になりました。
 *	  そうした理由は、dLotTblC.exeのクロスリファレンスとの照合を、行い易くするためです。
 *	  両者の違いは、クロスリファレンスは一列目が参照表現であるのに対し、LotRom_DumpLog()の抽選ログは一列目が当選回数である事のみです。
 *	  クロスリファレンスと抽選ログを照合し、クロスリファレンスの全ての参照表現の箇所に、抽選ログの当選回数(一致する抽選ログが無ければ0と見なす)を書き込めば、取り込み元の抽選表をそのまま集計表の雛形として利用出来るはずです。
 *	  2016/07/23現在ではまだ、上記の処理を行うツールを作成していませんが、そのうち作成しようと思っています。	←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←※TODO:
 *	  尚、抽選ログには当選値として非当選(-1)の回数も記録していますが、クロスリファレンスには該当する行は存在しないので、無視して構いません。
 *	* Mon Sep 05 21:24:05 JST 2016 Naoyuki Sawa
 *	- 64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
 *	  setjmp()/longjmp()のパラメータは(int)であり、(void*)や(intptr_t)を使えないからです。
 *	  尚、32ビット版も64ビット版と共通に変更しても良いのですが、万一既存のコードに影響が生じる事を防ぐために、32ビット版はこれまで通りとしました。
 */
#ifndef __CLIP_LOTR_H__
#define __CLIP_LOTR_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
//USE_LOTROM_LOGシンボルを定義しなければ、ログ機能を含めずにビルドします。
//ログ機能はLotRom_BeginLog()〜LotRom_EndLog()の間のみ有効となるので、ログ機能が不要な場合であっても、ログ機能を含めてビルドしてもプログラムの動作に影響は無いのですが、
//ログ機能を使用しない事が確実な場合(例えば動的メモリ割り当ての無い実行環境など)で、ログ機能のコードも節約したい場合はUSE_LOTROM_LOGの定義をコメントアウトしてください。
//P/ECE用に使用する場合も、Windows用に使用する場合も、ログ機能を利用可能です。
#ifndef __RENESAS__
#define USE_LOTROM_LOG
#endif//__RENESAS__
//{{2015/10/12追加:USE_LOTROM_SEHシンボルを定義すると、cliplotr.c内のDIE()を全て、SEH_throw(LotRomException)に置き換えるようにしました。
#define USE_LOTROM_SEH		//このシンボルを定義すると、cliplotr.c内のDIE()を全て、SEH_throw(LotException)に置き換えます。
#ifdef  USE_LOTROM_SEH
//{{2016/09/05変更:64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
//extern const char LotRomException[1/*dummy*/];
//↓2016/09/05変更:64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
#ifndef _WIN64
extern const char LotRomException[1/*dummy*/];		//32ビット版
#else //_WIN64
#define LotRomException MAKEFOURCC('L','o','t','R')	//64ビット版
#endif//_WIN64
//}}2016/09/05変更:64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
#endif//USE_LOTROM_SEH
//}}2015/10/12追加:USE_LOTROM_SEHシンボルを定義すると、cliplotr.c内のDIE()を全て、SEH_throw(LotRomException)に置き換えるようにしました。
//──────────────────────────────────────
//■「抽選表ROM形式」について
//│struct 抽選表ROM {
//│  int            TBL_LotTblNo[LotTblNo_Max+1];
//│  unsigned short TBL_LotTbl[〜];
//│}
//MkLotTbl.batとMkLotTblNo.batで出力したLotTbl.cとLotTblNo.cをコンパイルして、
//『LotTblNo.o,LotTbl.o』の順でリンクすれば、「抽選表ROM形式」になります。
//──────────────────────────────────────
/****************************************************************************
 *	構造体定義
 ****************************************************************************/
typedef struct _ST_LotRom {
	const int*			m_TBL_LotTblNo/*[LotTblNo_Max+1]*/;	//抽選表アドレステーブルへのポインタ	[抽選表番号]⇒TBL_LotTbl[]に対するインデクス
	int				(*m_fnRnd)(/*void* fnRndArg*/);		//乱数ジェネレータ関数へのポインタ	引数の無い関数も警告無く指定可能とするために、引数を明示しない型定義にしておく。
	void*				m_fnRndArg;				//乱数ジェネレータ関数への引数		引数の無い関数を指定した場合は、引数はダミーとなる。('cdecl呼出規約'なので安全。)
#ifdef  USE_LOTROM_LOG
//{{2016/07/23変更:抽選表ログの構造体を廃止し、ワークシート(多階層ハッシュテーブル)を利用するように変更しました。
//	struct _ST_LotRom_TblLog*	m_TBL_TblLog/*[LotTblNo_Max+1]*/;	//抽選表ログ				NULL=ログが開始していない事を示す。
//↓2016/07/23変更:抽選表ログの構造体を廃止し、ワークシート(多階層ハッシュテーブル)を利用するように変更しました。
	struct _ST_Worksheet*		m_wsLog;				//抽選表ログ				NULL=ログが開始していない事を示す。
//}}2016/07/23変更:抽選表ログの構造体を廃止し、ワークシート(多階層ハッシュテーブル)を利用するように変更しました。
#endif//USE_LOTROM_LOG
} ST_LotRom;
/****************************************************************************
 *	グローバル関数
 ****************************************************************************/
void LotRom_Init(const int* _TBL_LotTblNo/*[LotTblNo_Max+1]*/, int (*_fnRnd)(/*void* fnRndArg*/), void* _fnRndArg);
void LotRom_Free();
#ifdef  USE_LOTROM_LOG
void LotRom_BeginLog();
void LotRom_DumpLog(FILE* fp);
void LotRom_EndLog();
#endif//USE_LOTROM_LOG
int LotRom_draw_l(int LotTblNo, ...);
int LotRom_draw_a(int LotTblNo, va_list ap);
int LotRom_draw_v(int LotTblNo, const int* pid);
//{{2015/11/06追加:'_equally'版の関数を追加しました。
#ifdef  USE_LOT_EQUALLY
int LotRom_draw_equally_l(int LotTblNo, ...);
int LotRom_draw_equally_a(int LotTblNo, va_list ap);
int LotRom_draw_equally_v(int LotTblNo, const int* pid);
#endif//USE_LOT_EQUALLY
//}}2015/11/06追加:'_equally'版の関数を追加しました。
//{{2015/10/12変更:LOT_get_table_weight_a(),LOT_get_table_weight_v()の引数順序を変更した事に伴い、LotRom_get_weight_a(),LotRom_get_weight_v()の引数順序と実装も変更しました。
//int LotRom_get_weight_l(int LotTblNo, int hitval_sel, ...);
//int LotRom_get_weight_a(int LotTblNo, va_list ap, int hitval_sel);
//int LotRom_get_weight_v(int LotTblNo, const int* pid, int hitval_sel);
//↓2015/10/12変更:LOT_get_table_weight_a(),LOT_get_table_weight_v()の引数順序を変更した事に伴い、LotRom_get_weight_a(),LotRom_get_weight_v()の引数順序と実装も変更しました。
int LotRom_get_weight_l(int LotTblNo, int hitval_sel, ...);
int LotRom_get_weight_a(int LotTblNo, int hitval_sel, va_list ap);
int LotRom_get_weight_v(int LotTblNo, int hitval_sel, const int* pid);
//}}2015/10/12変更:LOT_get_table_weight_a(),LOT_get_table_weight_v()の引数順序を変更した事に伴い、LotRom_get_weight_a(),LotRom_get_weight_v()の引数順序と実装も変更しました。
int LotRom_get_size(int LotTblNo);
int LotRom_get_id_size(int LotTblNo);
void LotRom_get_column_id(int LotTblNo, int i_column, int* pid);
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__CLIP_LOTR_H__
