/*
 *	dpbmpcnv - BMP to PGD コンバータ
 *	Copyright (C) 2002-2017 Naoyuki Sawa
 *
 *	* ??? May 11 09:13:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- 1st リリース。
 *	* Sat Jun 01 11:42:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- 最大イメージサイズ(MAX_SIZE)を1024->4096に変更。
 *	* Tue Jun 18 19:00:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- アイコンデータ、スプライトデータ作成機能を実装。
 *	* Sat Jun 23 21:38:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- 画像サイズ調整時は、パディング部分を透明に。
 *	- 試験的な減色機能追加。透明色との併用はお勧めしません。
 *	* Sat Jun 27 22:14:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- カラー0〜3反転モード追加。(0:黒,1:暗,2:明,3:白とみなす)
 *	  P/ECE開発環境のsimpleサンプル付属のビットマップ(test.bmp)が、
 *	  上記のようなパレット構成になっていたので、対応しました。
 *	- バージョン表示を追加しました。
 *	* Tue Jul  9 03:34:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- バイナリ出力をデフォルトにしました。
 *	  プロジェクト名と同じ名前のアイコンファイルを生成しようとして、
 *	  うっかりproject.bmpからproject.c(テキスト形式のアイコンデータ)を生成してしまい、
 *	  project.c(メインプログラムソース)を上書きしてしまう事故が多発したからです。
 *	- 今回の変更により、テキスト出力をデフォルトと想定していたMakefileなどに
 *	  影響が出るかも知れません。気付いたら、適宜修正する予定です。
 *	* Tue Jul 16 19:00:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- 入力ファイル名のサフィックスによる、暗黙の出力フォーマット指定を追加しました。
 *	  "-f"オプションが指定された場合は、暗黙の出力フォーマット指定よりも優先します。
 *	- このように変更した理由は、Makefileの中で.bmpから.cへのサフィックスルールを一つ定義すれば、
 *	  ファイル名によって出力フォーマットを自動的に切り替えられるようにしたいと思ったからです。
 *	- これまでは、"-f"オプションが指定されなかった場合は、常に2ビットMASK付きで出力していました。
 *	  今回の変更により、"-f"オプションを指定しておらず、2ビットMASK付きの出力を期待していて、
 *	  かつ、たまたまサフィックスがフォーマット指定サフィックスに一致するような変換を行っていた
 *	  プロジェクトに影響が出るかも知れません。気付いたら、適宜修正する予定です。
 *	- メッセージを日本語に変更しました。
 *	* Thu Aug  8 06:48:00 JST 2002 Naoyuki Sawa <nsawa@north.hokkai.net>
 *	- フォーマット指定のためのファイル名サフィックスを変更。
 *	  これまでi,s,1,1m,2,2mでしたが、-i,-s,-1,-1m,-2,-2mに変更しました。
 *	- ファイル名サフィックスからフォーマットを自動決定し、かつ出力ラベルが明示されていないときは、
 *	  出力ラベルからファイル名サフィックスの部分を省くように変更しました。
 *	  例: ファイル名="test-2m.bmp"→フォーマット=2bitマスク付き、出力ラベル="TEST"
 *	- 入力ファイル名が"pat"で、出力フォーマットが明示されていなければ、スプライト形式としました。
 *	  たぶん、シンプルライブラリ用のスプライトデータと思われるからです。
 *	* Fri Nov 22 06:58:00 JST 2002 Naoyuki Sawa
 *	- ファイル名サフィックスによる指定「-2d」(2bitマスクなしへの減色)を追加しました。
 *	- 減色モードなら「OUT FMT:」の表示に"(DEC)"を追加するようにしました。
 *	* Mon Dec 2 05:48:00 JST 2002 Naoyuki Sawa
 *	- 入力ファイル名が"font"で、出力フォーマットが明示されていなければ、1ビットマスクなし形式としました。
 *	* Fri Apr 2 12:30:00 JST 2004 Naoyuki Sawa
 *	- CHIP-8/SCHIPスプライトデータ出力に対応しました。
 *	  コマンドラインオプション"-fc8","-fsc"または、ファイル名サフィックス"-c8","-sc"にて指定可能です。
 *	  これらの指定は暗黙に、Chipperアセンブラ用出力形式の指示も含んでいます。
 *	  TEXT/BINARYの出力形式指定と併用することはできません。
 *	* Sun Jun 6 21:21:00 JST 2004 Naoyuki Sawa
 *	- 16階調のPieceBitmap独自拡張形式(-4,-4m)に対応しました。
 *	* Fri Jun 25 05:30:00 JST 2004 Naoyuki Sawa
 *	- 2ビット4階調→4ビット16階調拡張形式を追加しました。(単独オプション-i、形式オプション-f4i-f4im、サフィックス-4i,-4im)
 *	  2ビット用のビットマップ画像から、4ビット用のPGDを作成します。
 *	  具体的には、入力ビットマップのカラーコード{0,1,2,3}を、カラーコード{0,5,10,15}に変換してから処理しているだけです。
 *	* Wed May 11 19:30:00 JST 2005 Naoyuki Sawa
 *	- Signetics 2637 UVI (バイダイ社アルカディアのCRTC) Graphics Mode = 1, Color Mode = 0 キャラクタ出力に対応しました。
 *	  コマンドラインオプション"-fuvi"または、ファイル名サフィックス"-uvi"にて指定可能です。
 *	  これらの指定は暗黙に、VACSアセンブラ用出力形式の指示も含んでいます。
 *	  TEXT/BINARYの出力形式指定と併用することはできません。
 *	* Thu Dec 27 13:11:37 JST 2007 Naoyuki Sawa
 *	- これまでの8->2bit減色に加えて、8->4bit減色を追加しました。
 *	* Wed Jan 29 17:20:15 JST 2014 Naoyuki Sawa
 *	- これまでの256色パレットBMPに加えて、2,16色パレットBMPの読み込みも可能としました。
 *	* Tue Feb 23 21:00:55 JST 2016 Naoyuki Sawa
 *	- パレット反転処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
 *	- 減色処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
 *	- パレットリマップ処理を追加しました。
 *	  (r,g,b)の輝度が同じピクセルに対してディザ無しの減色処理を行い、(r,g,b)の輝度が違うピクセルを透過とする処理に相当します。
 *	  この機能を追加した理由は、ImageMagickでパレット付きBMPを生成すると、パレットの順序が不定になるからです。
 *	  詳細は、/clip/tool/dpsprsht/app.c の、2016/02/22のコメントを参照して下さい。
 *	  ImageMagickが生成したBMPを扱う場合は、パレット番号ではなく、パレットの内容(色)を見てP/ECEの色番号に変換する必要が生じ、この機能を追加しました。
 *	  主な目的は上記の通りですが、手作業で作成するBMPでも、パレット番号を意識せずに色の見た目どおりに変換したい場合は、このオプションが利用出来ます。
 *	* Wed Mar 30 21:41:00 JST 2016 Naoyuki Sawa
 *	- dpsprsht.exeに'-p1','-p2','-p4'オプションを追加したことに伴い、dpbmpcnv.exeの'-m'オプションは当初の目的としては不要になりました。
 *	  しかし、'-m'は別の用途(ディザ無しの減色処理)にも利用出来るので、dpbmpcnv.exeの'-m'オプションも残しておくことにしました。
 *	  詳細は、/clip/tool/dpsprsht/app.c の、同日のコメントを参照して下さい。
 *	- 本日の、dpsprsht.exeに対する更新は、上記のコメント追加のみで、ソースコードの変更は有りません。
 *	  しかし、上記の件はdpsprsht.exeと連動しているのでバージョンを合わせておく方が判り易いと思ったので、dpsprsht.exeと同じVERSION日付に更新しました。
 *	* Mon Dec 19 21:58:37 JST 2016 Naoyuki Sawa
 *	- これまで長い間、当ツールは空のプロジェクトを元にしたプロジェクトでしたが、今回、/clip/test.win/を元にしたプロジェクトへ移行しました。
 *	  /clip/test.win/を元にしたプロジェクトへ移行した理由は、近々、clipvqtc.cモジュールのVQ圧縮テクスチャ形式への対応を行う予定だからです。	┐
 *	  今回はまだ、プロジェクトを移行しただけで、上記の対応は行っておらず、ツールの動作も変更していません。					┴→{{2016/12/20コメント追記:clipvqtc.cモジュールのVQ圧縮テクスチャ形式への対応を行いました。}}
 *	* Tue Dec 20 21:28:56 JST 2016 Naoyuki Sawa
 *	- clipvqtc.cモジュールのVQ圧縮テクスチャ形式への対応を行いました。
 *	  この対応に伴い、'-fvq'オプション,'-k<1〜256>'オプション，及び，ファイル名サフィックス'-vq'を追加しました。
 *	* Wed Dec 21 21:39:53 JST 2016 Naoyuki Sawa
 *	- clipvqtc.hにVQTC_DATAHEADER構造体の定義を追加した事に伴い、当ツールのソース内での定義を削除しました。
 *	* Fri Dec 23 23:24:50 JST 2016 Naoyuki Sawa
 *	- clipvqtc.cモジュールにて、コードブックの5バイトの圧縮データの1バイト目のビット詰めの順序を逆にした事に伴い、当ツールもリビルドしました。
 *	  当ツールのソースコードには変更有りません。
 *	* Sat Dec 24 21:19:40 JST 2016 Naoyuki Sawa
 *	- clipvqtc.cモジュールにて、コードブックに格納する色の値を「0=白〜3=黒,4=透明」⇒「0=透明,1=白〜4=黒」に変更した事に伴い、当ツールもリビルドしました。
 *	- '-d'(減色),'-m'(パレットリマップ),'-r'(パレット反転)オプションを、VQ圧縮テクスチャ形式とも併用出来るようにしました。
 *	- ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。
 *	  □使用例
 *	  ・ファイル名サフィックス'-vqd'    … オプション指定'-fvq -d'に相当します。
 *	  ・ファイル名サフィックス'-vq128'  … オプション指定'-fvq -k128'に相当します。
 *	  ・ファイル名サフィックス'-vq128d' … オプション指定'-fvq -d -k128'に相当します。
 *	* Sun Dec 25 21:14:35 JST 2016 Naoyuki Sawa
 *	- clipimg.cモジュールにて、動的メモリ割り当てを使って速度を改善したバージョンのk_means_clustering_init_r()を実装した事に伴い、当ツールもリビルドしました。
 *	  当ツールのソースコードには変更有りません。
 *	* Sun Dec 25 23:57:41 JST 2016 Naoyuki Sawa
 *	- clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。
 *	  '-k'オプションもファイル名サフィックスも指定しなければ、符号の数の目標値の既定値はこれまで通り256となります。
 *	* Mon Dec 26 21:39:12 JST 2016 Naoyuki Sawa
 *	- '-k'オプションもファイル名サフィックスも指定されなかった時の、符号の数の目標値の既定値を変更しました。
 *	  変更前は、'-k'オプションもファイル名サフィックスも指定しなければ、符号の数の目標値の既定値は256としていました。
 *	  変更後は、自動的に全セル数を計算し、全セルのうち重複しているセルを圧縮する(ただしclipvqtc.cの仕様により65536セルを上限とする)ようにしました。
 *	  変更前よりも、変更後の方が、画質優先となりました。
 *	  圧縮率優先とする場合は、明示的に'-k'オプション,又は,ファイル名サフィックスで指定して下さい。
 *	* Sun Jan 01 21:54:31 JST 2017 Naoyuki Sawa
 *	- ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
 *	  変更した理由は、ファイル名サフィックスを含むファイル名の素材ファイルに対し、形式オプションを明示的に指定して形式をオーバーライドして変換した時に、サフィックスがラベルに残ってしまうのを防ぐためです。
 *	  例えば、「dpbmpcnv.exe -fvq sample-2m.bmp」とした場合に、これまでは、自動生成される出力ラベルが(意図せず)"SAMPLE-2M"になってしまっていましたが、今後は(意図通り)"SAMPLE"になります。
 *	* Mon Jan 09 21:23:19 JST 2017 Naoyuki Sawa
 *	- 2017/01/01の変更時に二文字目以降の検査を正しくはiscsym()とすべきところ間違ってiscsymf()としており、ラベルに数字が含まれなくなってしまっていたバグを修正しました。
 */
#include "app.h"
#define VERSION		"20170109"	//最終更新日
/****************************************************************************
 *	main
 ****************************************************************************/
int main(int argc, char* argv[]) {
	int exitCode = EXIT_SUCCESS;
	SEH_init();
	app_init(argc, argv);
	exitCode = app_main(argc, argv);
	app_exit();
	return exitCode;
}
/****************************************************************************
 *	usage
 ****************************************************************************/
__declspec(noreturn) static void usage() {
	fprintf(stderr, "dpbmpcnv - BMP to PGD converter (%s)\n", VERSION);
	fprintf(stderr, "Copyright (C) 2002-2017 Naoyuki Sawa\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "USAGE:\n");
	fprintf(stderr, "    dpbmpcnv [options] <filename.bmp>\n");
	fprintf(stderr, "    （filename.bmpは、2,16,又は,256色パレットBMPであること。）\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "TYPE OPTIONS:\n");
	fprintf(stderr, "    -t         テキスト\n");
	fprintf(stderr, "  * -b         バイナリ\n");
	fprintf(stderr, "FORMAT OPTIONS:\n");
	fprintf(stderr, "    -fi        アイコン\n");
	fprintf(stderr, "    -fs        スプライト\n");
	fprintf(stderr, "    -f1        １ビット\n");
	fprintf(stderr, "    -f1m       １ビットマスク付き（独自拡張）\n");
	fprintf(stderr, "    -f2        ２ビット\n");
	fprintf(stderr, "  * -f2m       ２ビットマスク付き\n");
	fprintf(stderr, "    -f4        ４ビット（独自拡張）\n");
	fprintf(stderr, "    -f4m       ４ビットマスク付き（独自拡張）\n");
	fprintf(stderr, "    -f4i       ２ビット→４ビット拡張（独自拡張）\n");
	fprintf(stderr, "    -f4im      ２ビット→４ビット拡張、マスク付き（独自拡張）\n");
	fprintf(stderr, "    -fvq       VQ圧縮テクスチャ（独自拡張）\n");				//{{2016/12/20追加:VQ圧縮テクスチャを追加しました。}}
	fprintf(stderr, "    -fc8       CHIP-8（TYPE OPTIONSとの併用不可）\n");
	fprintf(stderr, "    -fsc       SCHIP （TYPE OPTIONSとの併用不可）\n");
	fprintf(stderr, "    -fuvi      Signetics 2637 UVI （TYPE OPTIONSとの併用不可）\n");
	fprintf(stderr, "    ファイル名サフィックスによるフォーマット指定も可能です。\n");
	fprintf(stderr, "    (-i,-s,-1,-1m,-2,-2m,-2d,-4,-4m,-4i,-4im,-4d,-vq,-vqd,-vq<1〜65536>,-vq<1〜65536>d,-c8,-sc,-uvi)\n");
	fprintf(stderr, "    オプション指定はサフィックス指定よりも優先されます。\n");
	fprintf(stderr, "OTHER OPTIONS:\n");
	fprintf(stderr, "    -d         ８ビットカラー→１/２/４ビット減色（試験的な実装）\n");		//{{2016/02/23変更:減色処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。}}
	fprintf(stderr, "    -i         ２ビット→４ビット拡張（試験的な実装）\n");
	fprintf(stderr, "    -m         パレットリマップ（主にImageMagickが生成したBMP用）\n");		//{{2016/02/23追加:パレットリマップ処理を追加しました。}}
	fprintf(stderr, "    -o<fname>  出力ファイル名\n");
	fprintf(stderr, "    -l<label>  ラベル名（テキスト時のみ）\n");
	fprintf(stderr, "    -p<prefix> ラベルプレフィクス（テキスト時のみ）\n");
	fprintf(stderr, "    -r         パレット反転\n");
	fprintf(stderr, "    -k<1〜65536> 符号の数の目標値（VQ圧縮テクスチャ時のみ。指定しなければ画質優先で自動調整します。）\n");	//{{2016/12/20追加:VQ圧縮テクスチャを追加しました。}}	//{{2016/12/25変更:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}	//{{2016/12/26変更:'-k'オプションもファイル名サフィックスも指定されなかった時の、符号の数の目標値の既定値を変更しました。}}
	fprintf(stderr, "    -q         メッセージ抑制\n");
	fprintf(stderr, "（* 初期値）\n");
	exit(EXIT_FAILURE);
}
/****************************************************************************
 *	
 ****************************************************************************/
#define NULDEV	"NUL"
FILE* msg = stdout;
/*--------------------------------------------------------------------------*/
#define TYPE_TEXT	0
#define TYPE_BINARY	1
#define TYPE_CHIPPER	2	/* 2004/04/02追加 */
#define TYPE_VACS	3	/* 2005/05/11追加 */
char* out_type_desc[] = {
	"TEXT",
	"BINARY",
	"CHIPPER",		/* 2004/04/02追加 */
	"VACS",			/* 2005/05/11追加 */
};
int out_type = -1;
/*--------------------------------------------------------------------------*/
#define FMT_ICON	 0
#define FMT_SPRITE	 1
#define FMT_1BIT	 2
#define FMT_1BITMASK	 3
#define FMT_2BIT	 4
#define FMT_2BITMASK	 5
#define FMT_4BIT	 6	/* 2004/06/06追加 */
#define FMT_4BITMASK	 7	/* 2004/06/06追加 */
#define FMT_VQTC	 8	/* 2016/12/20追加 */
#define FMT_CHIP8	 9	/* 2004/04/02追加 */
#define FMT_SCHIP	10	/* 2004/04/02追加 */
#define FMT_UVI		11	/* 2005/05/11追加 */
char* out_fmt_desc[] = {
	"ICON",
	"SPRITE",
	"1BIT",
	"1BIT MASK",
	"2BIT",
	"2BIT MASK",
	"4BIT",			/* 2004/06/06追加 */
	"4BIT MASK",		/* 2004/06/06追加 */
	"VQTC",			/* 2016/12/20追加 */
	"CHIP8",		/* 2004/04/02追加 */
	"SCHIP",		/* 2004/04/02追加 */
	"UVI",			/* 2005/05/11追加 */
};
int out_fmt = -1;
/*--------------------------------------------------------------------------*/
char out_label[32];
char out_prefix[32];
/*--------------------------------------------------------------------------*/
char in_path[_MAX_PATH];
char out_path[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
/*--------------------------------------------------------------------------*/
#define MAX_SIZE	4096
unsigned char in_data[MAX_SIZE][MAX_SIZE];
int in_width;
int in_height;
int out_width;
int out_height;
/*--------------------------------------------------------------------------*/
//{{2016/02/23追加:減色処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
const int DITHER1[16][16] = {
	  0,128, 32,160,  8,136, 40,168,  2,130, 34,162, 10,138, 42,170,
	192, 64,224, 96,200, 72,232,104,194, 66,226, 98,202, 74,234,106,
	 48,176, 16,144, 56,184, 24,152, 50,178, 18,146, 58,186, 26,154,
	240,112,208, 80,248,120,216, 88,242,114,210, 82,250,122,218, 90,
	 12,140, 44,172,  4,132, 36,164, 14,142, 46,174,  6,134, 38,166,
	204, 76,236,108,196, 68,228,100,206, 78,238,110,198, 70,230,102,
	 60,188, 28,156, 52,180, 20,148, 62,190, 30,158, 54,182, 22,150,
	252,124,220, 92,244,116,212, 84,254,126,222, 94,246,118,214, 86,
	  3,131, 35,163, 11,139, 43,171,  1,129, 33,161,  9,137, 41,169,
	195, 67,227, 99,203, 75,235,107,193, 65,225, 97,201, 73,233,105,
	 51,179, 19,147, 59,187, 27,155, 49,177, 17,145, 57,185, 25,153,
	243,115,211, 83,251,123,219, 91,241,113,209, 81,249,121,217, 89,
	 15,143, 47,175,  7,135, 39,167, 13,141, 45,173,  5,133, 37,165,
	207, 79,239,111,199, 71,231,103,205, 77,237,109,197, 69,229,101,
	 63,191, 31,159, 55,183, 23,151, 61,189, 29,157, 53,181, 21,149,
	255,127,223, 95,247,119,215, 87,253,125,221, 93,245,117,213, 85,
};
//}}2016/02/23追加:減色処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
const int DITHER2[8][8] = {
	 0,32, 8,40, 2,34,10,42,
	48,16,56,24,50,18,58,26,
	12,44, 4,36,14,46, 6,38,
	60,28,52,20,62,30,54,22,
	 3,35,11,43, 1,33, 9,41,
	51,19,59,27,49,17,57,25,
	15,47, 7,39,13,45, 5,37,
	63,31,55,23,61,29,53,21,
};
const int DITHER4[4][4] = {
	 0, 8, 2,10,
	12, 4,14, 6,
	 3,11, 1, 9,
	15, 7,13, 5,
};
int dec_color;	/* 「-d」オプションが指定されたら1 */
int inc_color;	/* 「-i」オプションが指定されたら1 */
int pal_remap;	/* 「-m」オプションが指定されたら1 */	//{{2016/02/23追加:パレットリマップ処理を追加しました。}}
int rev_pal;	/* 「-r」オプションが指定されたら1 */
int vqtc_k;	/* 「-k」オプションで指定された符号の数の目標値 */	//{{2016/12/20追加:VQ圧縮テクスチャを追加しました。}}
/****************************************************************************
 *	
 ****************************************************************************/
void app_init(int argc, char* argv[]) {
	/** no job **/
}
/*--------------------------------------------------------------------------*/
void app_exit() {
	/** no job **/
}
/*--------------------------------------------------------------------------*/
int app_main(int argc, char* argv[]) {
	FILE* fp;
	/* コマンドラインを解析します。 */
	cmdline(argc, argv);
	/* ビットマップを読み込みます。 */
	fp = fopen(in_path, "rb");
	if(fp == NULL) {
		fprintf(stderr, "### %s ファイルが開けません。\n", in_path);
		exit(1);
	}
	readbmp(fp);
	fclose(fp);
	/* 出力ファイルを作成します。 */
	switch(out_type) {
	case TYPE_TEXT:
	case TYPE_CHIPPER:	/* 2004/04/02追加 */
	case TYPE_VACS:		/* 2005/05/11追加 */
		fp = fopen(out_path, "wt");
		break;
	case TYPE_BINARY:
		fp = fopen(out_path, "wb");
		break;
	default:
		abort();
	}
	if(fp == NULL) {
		fprintf(stderr, "### %s ファイルが作成できません。\n", out_path);
		exit(1);
	}
	/* データを出力します。 */
	switch(out_fmt) {
	case FMT_ICON:
		writepid(fp);
		break;
	case FMT_SPRITE:
		writepsp(fp);
		break;
	case FMT_1BIT:
		writepgd(fp, 1, 0);
		break;
	case FMT_1BITMASK:
		writepgd(fp, 1, 1);
		break;
	case FMT_2BIT:
		writepgd(fp, 2, 0);
		break;
	case FMT_2BITMASK:
		writepgd(fp, 2, 1);
		break;
	case FMT_4BIT:		/* 2004/06/06追加 */
		writepgd(fp, 4, 0);
		break;
	case FMT_4BITMASK:	/* 2004/06/06追加 */
		writepgd(fp, 4, 1);
		break;
	case FMT_VQTC:		/* 2016/12/20追加 */
		writevqtc(fp);
		break;
	case FMT_CHIP8:		/* 2004/04/02追加 */
		writechip8(fp);
		break;
	case FMT_SCHIP:		/* 2004/04/02追加 */
		writeschip(fp);
		break;
	case FMT_UVI:		/* 2005/05/11追加 */
		writeuvi(fp);
		break;
	default:
		abort();
	}
	/* 出力ファイルを閉じます。 */
	fclose(fp);
	return EXIT_SUCCESS;
}
/****************************************************************************
 *	cmdline
 ****************************************************************************/
void cmdline(int argc, char* argv[]) {
	int i, len;
	char* opt;
	for(i = 1; i < argc; i++) {
		opt = argv[i];
		if(opt[0] != '-') {
			if(strlen(in_path) != 0) usage();
			strcpy(in_path, opt);
		} else {
			switch(opt[1]) {
			case 't':
				if(out_type != -1) usage();
				out_type = TYPE_TEXT;
				break;
			case 'b':
				if(out_type != -1) usage();
				out_type = TYPE_BINARY;
				break;
			case 'f':
				if(out_fmt != -1) usage();
				       if(strcmp(&opt[2], "i") == 0) {
					out_fmt = FMT_ICON;
				} else if(strcmp(&opt[2], "s") == 0) {
					out_fmt = FMT_SPRITE;
				} else if(strcmp(&opt[2], "1") == 0) {
					out_fmt = FMT_1BIT;
				} else if(strcmp(&opt[2], "1m") == 0) {
					out_fmt = FMT_1BITMASK;
				} else if(strcmp(&opt[2], "2") == 0) {
					out_fmt = FMT_2BIT;
				} else if(strcmp(&opt[2], "2m") == 0) {
					out_fmt = FMT_2BITMASK;
				} else if(strcmp(&opt[2], "4") == 0) {		/* 2004/06/06追加 */
					out_fmt = FMT_4BIT;
				} else if(strcmp(&opt[2], "4m") == 0) {		/* 2004/06/06追加 */
					out_fmt = FMT_4BITMASK;
				} else if(strcmp(&opt[2], "vq") == 0) {		/* 2016/12/20追加 */
					out_fmt = FMT_VQTC;
				} else if(strcmp(&opt[2], "c8") == 0) {		/* 2004/04/02追加 */
					if(out_type != -1) usage();
					out_type = TYPE_CHIPPER;
					out_fmt = FMT_CHIP8;
				} else if(strcmp(&opt[2], "sc") == 0) {		/* 2004/04/02追加 */
					if(out_type != -1) usage();
					out_type = TYPE_CHIPPER;
					out_fmt = FMT_SCHIP;
				} else if(strcmp(&opt[2], "uvi") == 0) {	/* 2005/05/11追加 */
					if(out_type != -1) usage();
					out_type = TYPE_VACS;
					out_fmt = FMT_UVI;
				} else {
					usage();
				}
				break;
			case 'd':
				if(dec_color) usage();
				dec_color = 1;
				break;
			case 'i':	/* 2004/06/25追加 */
				if(inc_color) usage();
				inc_color = 1;
				break;
			case 'm':	/* 2016/02/23追加 */
				if(pal_remap) usage();
				pal_remap = 1;
				break;
			case 'o':
				if(strlen(out_path) != 0) usage();
				strcpy(out_path, &opt[2]);
				break;
			case 'l':
				if(strlen(out_label) != 0) usage();
				strcpy(out_label, &opt[2]);
				break;
			case 'p':
				if(strlen(out_prefix) != 0) usage();
				strcpy(out_prefix, &opt[2]);
				break;
			case 'q':
				msg = fopen(NULDEV, "wt");
				break;
			case 'r':
				if(rev_pal) usage();
				rev_pal = 1;
				break;
			case 'k':						/* 2016/12/20追加 */
				vqtc_k = atoi(&opt[2]);
				if((vqtc_k < 1) || (vqtc_k > 65536)) usage();	//{{2016/12/25変更:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
				break;
			default:
				usage();
			}
		}
	}
	/* 入力ファイル名は必須です。 */
	if(strlen(in_path) == 0) usage();
	/* 入力ファイル名の拡張子が省略されていたら、「.bmp」とします。 */
	_splitpath(in_path, drive, dir, fname, ext);
	if(strlen(ext) == 0) {
		_makepath(in_path, drive, dir, fname, ".bmp");
	}
	/* 出力フォーマットが指定されていなければ... */
	if(out_fmt == -1) {
//{{2016/12/24追加:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
		regexp* prog_vq;
		prog_vq = regcomp("-vq([0-9]*)?(d)?$");
//}}2016/12/24追加:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
		_splitpath(in_path, drive, dir, fname, ext);
		/* 入力ファイル名のサフィックスから、出力フォーマットを決定します。
		 * 入力ファイル名のサフィックスから出力フォーマットを自動決定した場合は、
		 * 出力ラベルにサフィックス部分を含めません。
		 * * Fri Nov 22 06:58:00 JST 2002 Naoyuki Sawa
		 * - ファイル名サフィックスによる指定「-2d」(2bitマスクなしへの減色)を追加しました。
		 */
		len = strlen(fname);
		       if(len >= 2 && strcmpi(&fname[len - 2], "-i" ) == 0) {
			out_fmt = FMT_ICON;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 2);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 2 && strcmpi(&fname[len - 2], "-s" ) == 0) {
			out_fmt = FMT_SPRITE;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 2);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 2 && strcmpi(&fname[len - 2], "-1" ) == 0) {
			out_fmt = FMT_1BIT;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 2);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-1m") == 0) {
			out_fmt = FMT_1BITMASK;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 2 && strcmpi(&fname[len - 2], "-2" ) == 0) {
			out_fmt = FMT_2BIT;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 2);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-2m") == 0) {
			out_fmt = FMT_2BITMASK;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-2d") == 0) {	/* 2002/11/22追加 */
			out_fmt = FMT_2BIT;
			dec_color = 1;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 2 && strcmpi(&fname[len - 2], "-4" ) == 0) {	/* 2004/06/06追加 */
			out_fmt = FMT_4BIT;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 2);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-4m") == 0) {	/* 2004/06/06追加 */
			out_fmt = FMT_4BITMASK;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 2 && strcmpi(&fname[len - 3], "-4i" ) == 0) {	/* 2004/06/25追加 */
			out_fmt = FMT_4BIT;
			inc_color = 1;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 4], "-4im") == 0) {	/* 2004/06/25追加 */
			out_fmt = FMT_4BITMASK;
			inc_color = 1;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 4);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-4d") == 0) {	/* 2007/12/27追加 */
			out_fmt = FMT_4BIT;
			dec_color = 1;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//{{2016/12/24変更:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
//		} else if(len >= 3 && strcmpi(&fname[len - 3], "-vq") == 0) {	/* 2016/12/20追加 */
//			out_fmt = FMT_VQTC;
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//↓2016/12/24変更:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
		} else if(regexec(prog_vq, fname)) {
			out_fmt = FMT_VQTC;
			if(prog_vq->startp[1] < prog_vq->endp[1]) {	//'<1〜65536>'の部分が有れば…	//{{2016/12/25変更:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
				char* tmp = strndup(prog_vq->startp[1], prog_vq->endp[1] - prog_vq->startp[1]);
				vqtc_k = atoi(tmp);
				if((vqtc_k < 1) || (vqtc_k > 65536)) { usage(); }			//{{2016/12/25変更:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
				free(tmp);
			}
			if(prog_vq->startp[2] < prog_vq->endp[2]) {	//'d'の部分が有れば…
				char* tmp = strndup(prog_vq->startp[2], prog_vq->endp[2] - prog_vq->startp[2]);
				if(strcmp(tmp, "d")) { DIE(); }	//起こり得ないはず。もしここで停止したらregexec()のバグです。
				dec_color = 1;
				free(tmp);
			}
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				strncpy(out_label, fname, prog_vq->startp[0] - fname);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//}}2016/12/24変更:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-c8") == 0) {	/* 2004/04/02追加 */
			if(out_type != -1) usage();
			out_type = TYPE_CHIPPER;
			out_fmt = FMT_CHIP8;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 3 && strcmpi(&fname[len - 3], "-sc") == 0) {	/* 2004/04/02追加 */
			if(out_type != -1) usage();
			out_type = TYPE_CHIPPER;
			out_fmt = FMT_SCHIP;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 3);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(len >= 4 && strcmpi(&fname[len - 4], "-uvi") == 0) {	/* 2005/05/11追加 */
			if(out_type != -1) usage();
			out_type = TYPE_VACS;
			out_fmt = FMT_UVI;
//{{2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
//			if(strlen(out_label) == 0) {
//				memcpy(out_label, fname, len - 4);
//				_strupr(out_label);
//			}
//}}2017/01/01削除:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		} else if(strcmpi(fname, "pat") == 0) { /* たぶんシンプルライブラリ用のスプライトデータ */
			out_fmt = FMT_SPRITE;
		} else if(strcmpi(fname, "font") == 0) { /* たぶんフォントデータなので1ビットマスクなし */
			out_fmt = FMT_1BIT;
		} else {
			fprintf(stderr, "### 警告 出力フォーマットが指定されていません。\n");
			out_fmt = FMT_2BITMASK; /* どれにも一致しなければデフォルト値を設定 */
		}
//{{2016/12/24追加:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
		free(prog_vq);
//}}2016/12/24追加:ファイル名サフィックス'-vqd','-vq<1〜256>','-vq<1〜256>d'を追加しました。	//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
	}
	/* タイプが指定されていなければ、デフォルト値を設定します。 */
	if(out_type == -1) out_type = TYPE_BINARY;
	/* 出力ファイル名が省略されていたら、入力ファイル名から生成します。 */
	if(strlen(out_path) == 0) {
		_splitpath(in_path, drive, dir, fname, ext);
		switch(out_type) {
		case TYPE_TEXT:
			_makepath(out_path, drive, dir, fname, ".c");
			break;
		case TYPE_BINARY:
			switch(out_fmt) {
			case FMT_ICON:
				_makepath(out_path, drive, dir, fname, ".pid");
				break;
			case FMT_SPRITE:
				_makepath(out_path, drive, dir, fname, ".psp");
				break;
			default:
				_makepath(out_path, drive, dir, fname, ".pgd");
				break;
			}
			break;
		case TYPE_CHIPPER:	/* 2004/04/02追加 */
			_makepath(out_path, drive, dir, fname, ".chp");
			break;
		case TYPE_VACS:		/* 2005/05/11追加 */
			_makepath(out_path, drive, dir, fname, ".asm");
			break;
		default:
			abort();
		}
	}
	/* 出力ラベルが省略されていたら、入力ファイル名から生成します。 */
	if(strlen(out_label) == 0) {
		_splitpath(in_path, NULL, NULL, out_label, NULL);
		_strupr(out_label);
//{{2017/01/01追加:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
		if(iscsymf(out_label[0])) {		//一文字目がCシンボル文字ならば…
			char* tmp = out_label;
    //{{2017/01/09修正:2017/01/01の変更時に二文字目以降の検査を正しくはiscsym()とすべきところ間違ってiscsymf()としており、ラベルに数字が含まれなくなってしまっていたバグを修正しました。
    //			while(iscsymf(*tmp)) { tmp++; }	//非Cシンボル文字の位置まで進める。(終端文字も非Cシンボル文字に含まれる。)
    //↓2017/01/09修正:2017/01/01の変更時に二文字目以降の検査を正しくはiscsym()とすべきところ間違ってiscsymf()としており、ラベルに数字が含まれなくなってしまっていたバグを修正しました。
			while(iscsym(*tmp)) { tmp++; }	//非Cシンボル文字の位置まで進める。(終端文字も非Cシンボル文字に含まれる。)
    //}}2017/01/09修正:2017/01/01の変更時に二文字目以降の検査を正しくはiscsym()とすべきところ間違ってiscsymf()としており、ラベルに数字が含まれなくなってしまっていたバグを修正しました。
			*tmp = '\0';			//非Cシンボル文字で打ち切る。(終端文字だった場合はダミー処理となる。)
		} else {				//一文字目がCシンボル文字でなければ…
			error(EXIT_FAILURE, 0, "ファイル名の一文字目がCシンボル文字でないため、出力ラベルを自動生成出来ません。ファイル名を変更するか、又は、-lオプションでラベル名を指定して下さい。", out_label);
		}
//}}2017/01/01追加:ファイル名サフィックスが指定された場合にサフィックスよりも前の部分をラベルとする処理を、これまでは個別に行っていましたが、出力ラベルが省略時に入力ファイル名から生成する処理でまとめて行うようにしました。
	}
	/* 出力プレフィクスが指定されていたら、ラベルに追加します。 */
	if(strlen(out_prefix) != 0) {
		strcat(out_prefix, out_label);
		strcpy(out_label, out_prefix);
	}
	/* * Fri Nov 22 06:58:00 JST 2002 Naoyuki Sawa
	 * - 減色モードなら「OUT FMT:」の表示に"(DEC)"を追加するようにしました。
	 * * Fri Jun 25 05:30:00 JST 2004 Naoyuki Sawa
	 * - ２ビット→４ビット拡張モードなら「OUT FMT:」の表示に"(INC)"を追加するようにしました。
	 */
	fprintf(msg, "IN  FILE : %s\n", in_path);
	fprintf(msg, "OUT FILE : %s\n", out_path);
	fprintf(msg, "OUT TYPE : %s\n", out_type_desc[out_type]);
	if(dec_color) {
		fprintf(msg, "OUT FMT  : %s (DEC)\n", out_fmt_desc[out_fmt]);
	} else if(inc_color) {
		fprintf(msg, "OUT FMT  : %s (INC)\n", out_fmt_desc[out_fmt]);
	} else {
		fprintf(msg, "OUT FMT  : %s\n", out_fmt_desc[out_fmt]);
	}
	fprintf(msg, "OUT LABEL: %s\n", out_label);
}
/****************************************************************************
 *	readbmp
 ****************************************************************************/
void readbmp(FILE* fp) {
	int retval, pitch, x, y, n, c, r, g, b;
	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;
	RGBQUAD palette[256];
//{{2014/01/29追加:2,16色パレットBMP対応
	unsigned char linebuf[MAX_SIZE];
//}}2014/01/29追加:2,16色パレットBMP対応
	/* サイズ調整された場合、パディング部分を透明にするために、
	 * in_dataを透明値でクリアしておきます。
	 */
	memset(in_data, -1, sizeof in_data);
	/* ファイルヘッダを読みます。 */
	retval = fread(&bf, 1, sizeof(BITMAPFILEHEADER), fp);
	if(retval != sizeof(BITMAPFILEHEADER)) goto L_ERR;
	if(strncmp((char*)&bf.bfType, "BM", 2) != 0) goto L_ERR;
	/* ビットマップヘッダを読みます。 */
	retval = fread(&bi, 1, sizeof(BITMAPINFOHEADER), fp);
	if(retval != sizeof(BITMAPINFOHEADER)) goto L_ERR;
	if(bi.biSize < sizeof(BITMAPINFOHEADER)) goto L_ERR;
	if(bi.biWidth > MAX_SIZE) goto L_ERR;
	if(bi.biHeight > MAX_SIZE) goto L_ERR;
//{{2014/01/29変更:2,16色パレットBMP対応
//	if(bi.biPlanes != 1) goto L_ERR;   /* 256色パレットBMPのみ対応 */
//	if(bi.biBitCount != 8) goto L_ERR; /* 256色パレットBMPのみ対応 */
//↓2014/01/29変更:2,16色パレットBMP対応
	if(bi.biPlanes != 1) goto L_ERR;     /* 2,16,256色パレットBMPのみ対応 */
	if((bi.biBitCount != 1) &&
	   (bi.biBitCount != 4) &&
	   (bi.biBitCount != 8)) goto L_ERR; /* 2,16,256色パレットBMPのみ対応 */
//}}2014/01/29変更:2,16色パレットBMP対応
	if(bi.biCompression != BI_RGB) goto L_ERR;
//{{2016/02/23追加:パレットリマップ処理を追加しました。
//	/* 減色ありなら、パレットを読み込みます。 */
//	if(dec_color) {
//↓2016/02/23追加:パレットリマップ処理を追加しました。
	/* 減色あり,又は,パレットリマップありなら、パレットを読み込みます。 */
	if(dec_color || pal_remap) {
//}}2016/02/23追加:パレットリマップ処理を追加しました。
		n = bi.biClrUsed != 0 ? bi.biClrUsed
		                      : bi.biPlanes << bi.biBitCount;
		if(n < 0 || 256 < n) goto L_ERR; /* 壊れてる？ */
		retval = fread(palette, sizeof(RGBQUAD), n, fp);
		if(retval != n) goto L_ERR;
	}
	/* 入力画像サイズとラインストライドを求めます。 */
	in_width = bi.biWidth;
	in_height = bi.biHeight;
//{{2014/01/29変更:2,16色パレットBMP対応
//	pitch = in_width + 3 & ~3; /* DIBの仕様 */
//↓2014/01/29変更:2,16色パレットBMP対応
	pitch = (((in_width * bi.biBitCount) + 31) & ~31) / 8;
	if(pitch > MAX_SIZE) abort(); /* 既にbi.biPlanesとbi.biBitCountを検査済みなのでこうなることは無いはず。 */
//}}2014/01/29変更:2,16色パレットBMP対応
	/* 入力画像を読み込みます。 */
	retval = fseek(fp, bf.bfOffBits, SEEK_SET);
	if(retval != 0) goto L_ERR;
	for(y = in_height - 1; y >= 0; y--) { /* ボトムアップ */
//{{2014/01/29変更:2,16色パレットBMP対応
//		retval = fread(&in_data[y][0], 1, in_width, fp); /* pitch[byte]読んでしまうとゴミが入る恐れアリ */
//		if(retval != in_width) goto L_ERR;
//		retval = fseek(fp, pitch - in_width, SEEK_CUR);
//		if(retval != 0) goto L_ERR;
//↓2014/01/29変更:2,16色パレットBMP対応
		retval = fread(linebuf, 1, pitch, fp);
		if(retval != pitch) goto L_ERR;
		for(x = 0; x < in_width; x++) {
			in_data[y][x]   = linebuf[ x /  (8  / bi.biBitCount)];
			in_data[y][x] >>=       ((~x & ((8  / bi.biBitCount) - 1)) * bi.biBitCount);
			in_data[y][x]  &=              ((1 << bi.biBitCount) - 1);
		}
//}}2014/01/29変更:2,16色パレットBMP対応
	}
	/* 減色処理。 */
	if(dec_color) {
		for(y = 0; y < in_height; y++) {
			for(x = 0; x < in_width; x++) {
				c = in_data[y][x];			/* c=色番号(0〜255) */
				r = palette[c].rgbRed;			/* r=赤成分(0〜255) */
				g = palette[c].rgbGreen;		/* g=緑成分(0〜255) */
				b = palette[c].rgbBlue;			/* b=青成分(0〜255) */
				c = (r * 3 + g * 5 + b * 2) / 10;	/* c=輝度  (0〜255) */
				switch(out_fmt) {
//{{2016/02/23追加:減色処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
				case FMT_1BIT:
				case FMT_1BITMASK:
					c = (c + DITHER1[y & 15][x & 15] + (255 - 255) / 2) / 255;	/* c=輝度  (0〜 1) */
					if(c >  1) c =  1;	//      除数~~~   ~~~DITHER1の最大値	/* ありえないはずだが、念のため */
					c =  1 - c;							/* 液晶では輝度が逆 */
					break;
//}}2016/02/23追加:減色処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
				case FMT_VQTC:	//{{2016/12/24追加:'-d'(減色),'-m'(パレットリマップ),'-r'(パレット反転)オプションを、VQ圧縮テクスチャ形式とも併用出来るようにしました。}}
				case FMT_2BIT:
				case FMT_2BITMASK:
					c = (c + DITHER2[y &  7][x &  7] + ( 85 -  63) / 2) /  85;	/* c=輝度  (0〜 3) */
					if(c >  3) c =  3;	//      除数~~~   ~~~DITHER2の最大値	/* ありえないはずだが、念のため */
					c =  3 - c;							/* 液晶では輝度が逆 */
					break;
				case FMT_4BIT:
				case FMT_4BITMASK:
					c = (c + DITHER4[y &  3][x &  3] + ( 17 -  15) / 2) / 17;	/* c=輝度  (0〜15) */
					if(c > 15) c = 15;	//      除数~~~   ~~~DITHER4の最大値	/* ありえないはずだが、念のため */
					c = 15 - c;							/* 液晶では輝度が逆 */
					break;
				default:
					/** ※TODO: 2007/12/27現在は、何もしません。 */
					break;
				}
				in_data[y][x] = c;
			}
		}
	}
//{{2016/02/23追加:パレットリマップ処理を追加しました。(r,g,b)の輝度が同じピクセルに対してディザ無しの減色処理を行い、(r,g,b)の輝度が違うピクセルを透過とする処理に相当します。
	/* パレットリマップ処理。 */
	if(pal_remap) {
		for(y = 0; y < in_height; y++) {
			for(x = 0; x < in_width; x++) {
				c = in_data[y][x];			/* c=色番号(0〜255) */
				r = palette[c].rgbRed;			/* r=赤成分(0〜255) */
				g = palette[c].rgbGreen;		/* g=緑成分(0〜255) */
				b = palette[c].rgbBlue;			/* b=青成分(0〜255) */
				if((r == g) && (g == b)) {		/* (r,g,b)の輝度が同じならば、不透明色と見なす。 */
					switch(out_fmt) {
					case FMT_1BIT:
					case FMT_1BITMASK:
						c = (r + (255 / 2)) / 255;
						if(c >  1) c =  1;	/* ありえないはずだが、念のため */
						c =  1 - c;		/* 液晶では輝度が逆 */
						break;
					case FMT_VQTC:	//{{2016/12/24追加:'-d'(減色),'-m'(パレットリマップ),'-r'(パレット反転)オプションを、VQ圧縮テクスチャ形式とも併用出来るようにしました。}}
					case FMT_2BIT:
					case FMT_2BITMASK:
						c = (r + ( 85 / 2)) /  85;
						if(c >  3) c =  3;	/* ありえないはずだが、念のため */
						c =  3 - c;		/* 液晶では輝度が逆 */
						break;
					case FMT_4BIT:
					case FMT_4BITMASK:
						c = (r + ( 17 / 2)) /  17;
						if(c > 15) c = 15;	/* ありえないはずだが、念のため */
						c = 15 - c;		/* 液晶では輝度が逆 */
						break;
					default:
						/** ※TODO: 2007/12/27現在は、何もしません。 */
						break;
					}
				} else {			/* (r,g,b)の輝度が同じでなければ、透明色と見なす。 */
					c = 255;
				}
				in_data[y][x] = c;
			}
		}
	}
//}}2016/02/23追加:パレットリマップ処理を追加しました。(r,g,b)の輝度が同じピクセルに対してディザ無しの減色処理を行い、(r,g,b)の輝度が違うピクセルを透過とする処理に相当します。
	/* パレット反転処理。 */
	if(rev_pal) {
		for(y = 0; y < in_height; y++) {
			for(x = 0; x < in_width; x++) {
				c = in_data[y][x];
				switch(out_fmt) {
//{{2016/02/23追加:パレット反転処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
				case FMT_1BIT:
				case FMT_1BITMASK:
					if(0 <= c && c <= 1) { /* カラー0〜1のみ反転 */
						c = 1 - c;
					}
					break;
//}}2016/02/23追加:パレット反転処理において、これまでは2ビット,4ビットのみを処理対象としていましたが、1ビットも処理対象に含めるように変更しました。
				case FMT_VQTC:	//{{2016/12/24追加:'-d'(減色),'-m'(パレットリマップ),'-r'(パレット反転)オプションを、VQ圧縮テクスチャ形式とも併用出来るようにしました。}}
				case FMT_2BIT:
				case FMT_2BITMASK:
					if(0 <= c && c <= 3) { /* カラー0〜3のみ反転 */
						c = 3 - c;
					}
					break;
				case FMT_4BIT:
				case FMT_4BITMASK:
					if(0 <= c && c <= 15) { /* カラー0〜15のみ反転 */
						c = 15 - c;
					}
					break;
				default:
					/** ※TODO: 2007/12/27現在は、何もしません。 */
					break;
				}
				in_data[y][x] = c;
			}
		}
	}
	/* ２ビット→４ビット拡張処理。 */
	if(inc_color) {
		for(y = 0; y < in_height; y++) {
			for(x = 0; x < in_width; x++) {
				c = in_data[y][x];
				if(c >= 0 && c <= 3) {
					c = c << 2 | c;	/* {0,1,2,3}→{0,5,10,15} */
				} else {
					c = 255;	/* {4〜255}→{255} */
				}
				in_data[y][x] = c;
			}
		}
	}
	/* サイズ調整。 */
	switch(out_fmt) {
	case FMT_ICON:
		/* アイコンの仕様により、32x32ピクセルに固定します。
		 * 元データの大きい部分は無視、足りない部分はゴミが入ります。
		 */
		out_width  = 32;
		out_height = 32;
		break;
	case FMT_SPRITE:
		/* スプライトの仕様により、幅と高さを8ピクセル単位に切り上げます。
		 * 元データの足りない部分は、ゴミが入ります。
		 */
		out_width  = in_width  + 7 & ~7;
		out_height = in_height + 7 & ~7;
		break;
	case FMT_1BIT:
	case FMT_1BITMASK:
	case FMT_2BIT:
	case FMT_2BITMASK:
	case FMT_4BIT:		/* 2004/06/06追加 */
	case FMT_4BITMASK:	/* 2004/06/06追加 */
		/* PIECE_BMPの仕様により、幅を8ピクセル単位に切り上げます。
		 * 元データの足りない部分は、ゴミが入ります。
		 * 高さは自由なので、元データそのままとします。
		 */
		out_width  = in_width + 7 & ~7;
		out_height = in_height;
		break;
	case FMT_VQTC:		/* 2016/12/20追加 */
		/* VQ圧縮テクスチャは、PBMP_FILEHEADERヘッダを利用していますが、独自形式です。
		 * PIECE_BMPの仕様とは違って、幅も高さも自由なので、元データそのままとします。
		 * 厳密には、4×4ピクセルのセル単位で圧縮しますが、PBMP_FILEHEADERヘッダには、元データの幅と高さをそのまま格納します。
		 */
		out_width  = in_width;
		out_height = in_height;
		break;
	case FMT_CHIP8:		/* 2004/04/02追加 */
		/* CHIP-8の"DRW VX,VY,Nibble"命令の仕様により、幅を8ピクセル単位に切上げます。
		 * 元データの足りない部分は、ゴミが入ります。
		 * 高さは自由なので、元データそのままとします。
		 */
		out_width  = in_width + 7 & ~7;
		out_height = in_height;
		break;
	case FMT_SCHIP:		/* 2004/04/02追加 */
		/* SCHIPの"DRW VX,VY,0"命令の仕様により、幅と高さを16ピクセル単位に切上げます。
		 * 元データの足りない部分は、ゴミが入ります。
		 */
		out_width  = in_width  + 15 & ~15;
		out_height = in_height + 15 & ~15;
		break;
	case FMT_UVI:		/* 2005/05/11追加 */
		/* UVIのGraphics Modeの仕様により、幅を3ピクセル単位、高さを2ピクセル単位に切り上げます。
		 * 元データの足りない部分は、ゴミが入ります。
		 */
		out_width  = (in_width  + 2) / 3 * 3;
		out_height = (in_height + 1) / 2 * 2;
		break;
	default:
		abort();
	}
	if(out_width != in_width || out_height != in_height) {
		fprintf(stderr, "### 警告 出力イメージサイズを調整しました。\n");
		/* 継続 */
	}
	return;
L_ERR:
	fprintf(stderr, "### ビットマップの読み込みに失敗しました。\n");
	exit(1);
}
/****************************************************************************
 *	writepid
 ****************************************************************************/
void writepid(FILE* fp) {
	int x, y, i;
	unsigned char in_byte, out_byte;
	/* C言語配列の開始。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "const unsigned char %s[] = {\n", out_label);
	}
	/* カラーデータを出力します。 */
	for(y = 0; y < out_height; y++) {
		for(x = 0; x < out_width; x += (8 / 2)) {
			out_byte = 0;
			for(i = 0; i < (8 / 2); i++) {
				out_byte <<= 2;
				in_byte = in_data[y][x + i];
				if(in_byte < 4) {
					out_byte |= in_byte;
				}
			}
			if(out_type == TYPE_TEXT) {
				fprintf(fp, "0x%02x,", out_byte);
			} else {
				fwrite(&out_byte, 1, 1, fp);
			}
		}
		if(out_type == TYPE_TEXT) {
			fprintf(fp, "\n");
		}
	}
	/* C言語配列の終了。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "};\n");
	}
}
/****************************************************************************
 *	writepsp
 ****************************************************************************/
void writepsp(FILE* fp) {
	int i, x1, y1, x2, y2;
	unsigned char in_byte, out_bit0, out_bit1, out_mask;
	/* C言語配列の開始。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "const unsigned char %s[] = {\n", out_label);
	}
	/* 各キャラクタについて... */
	i = 0;
	for(y1 = 0; y1 < out_height; y1 += 8) {
		for(x1 = 0; x1 < out_width; x1 += 8) {
			/* 各ラインについて... */
			for(y2 = 0; y2 < 8; y2++) {
				out_bit0 = 0;
				out_bit1 = 0;
				out_mask = 0;
				/* 各ピクセルについて... */
				for(x2 = 0; x2 < 8; x2++) {
					in_byte = in_data[y1 + y2][x1 + x2];
					/* 左:LSB<->MSB:右 */
					out_bit0 >>= 1;
					out_bit1 >>= 1;
					out_mask >>= 1;
					if(in_byte < 4) {
						if(in_byte & 1) out_bit0 |= 0x80;
						if(in_byte & 2) out_bit1 |= 0x80;
					} else {
						out_mask |= 0x80; /* 透明が1 */
					}
				}
				/* bit0と1の順番に注意！bit1が先。直感と逆です。 */
				if(out_type == TYPE_TEXT) {
					fprintf(fp, "0x%02x,", out_bit1);
					fprintf(fp, "0x%02x,", out_bit0);
					fprintf(fp, "0x%02x,", out_mask);
				} else {
					fwrite(&out_bit1, 1, 1, fp);
					fwrite(&out_bit0, 1, 1, fp);
					fwrite(&out_mask, 1, 1, fp);
				}
			}
			if(out_type == TYPE_TEXT) {
				fprintf(fp, " /*%03x*/\n", i++);
			}
		}
	}
	/* C言語配列の終了。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "};\n");
	}
}
/****************************************************************************
 *	writepgd
 ****************************************************************************/
/* /usr/piece/include/piece_bmp.hより */
typedef struct _PBMP_FILEHEADER {
	unsigned long head;		/* + 0,4 シグネチャ'PBMP' */
	unsigned long fsize;		/* + 4,4 ファイルサイズ   */
	unsigned char bpp;		/* + 8,1 ビット深度       */
	unsigned char mask;		/* + 9,1 マスク深度       */
	short w;			/* +10,2 幅               */
	short h;			/* +12,2 高さ             */
					/* +14,2 パディング       */
	unsigned long buf_size;		/* +16,4 データサイズ     */
					/* =20                    */
} PBMP_FILEHEADER;
/*--------------------------------------------------------------------------*/
void writepgd(FILE* fp, int bpp, int mask) {
	PBMP_FILEHEADER hdr;
	int x, y, i;
	unsigned char in_byte, out_byte;
	/* C言語配列の開始。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "const unsigned char %s[] = {\n", out_label);
	}
	/* ヘッダを出力します。 */
	memset(&hdr, 0, sizeof hdr);
	memcpy(&hdr.head, "PMBP", 4); /* シグネチャ */
	         hdr.fsize = sizeof hdr + out_width * out_height / (8 / bpp); /* ヘッダとカラーのサイズ */
	if(mask) hdr.fsize +=             out_width * out_height /  8;        /* マスクのサイズを追加   */
	hdr.bpp  = bpp;
	hdr.mask = mask;
	hdr.w = out_width;
	hdr.h = out_height;
	         hdr.buf_size =  out_width * out_height / (8 / bpp); /* カラーのサイズ       */
	if(mask) hdr.buf_size += out_width * out_height /  8;        /* マスクのサイズを追加 */
	if(out_type == TYPE_TEXT) {
		for(i = 0; i < sizeof hdr; i++) {
			fprintf(fp, "0x%02x,", ((unsigned char*)&hdr)[i]);
		}
		fprintf(fp, "\n");
	} else {
		fwrite(&hdr, 1, sizeof hdr, fp);
	}
	/* カラーデータを出力します。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "/*buf*/\n");
	}
	for(y = 0; y < out_height; y++) {
		for(x = 0; x < out_width; x += (8 / bpp)) {
			out_byte = 0;
			for(i = 0; i < (8 / bpp); i++) {
				out_byte <<= bpp;
				in_byte = in_data[y][x + i];
				//if(in_byte < 4) {
				//	if(bpp == 1 && in_byte != 0) in_byte = 1; /* 1bit時は、色1〜3は1と見なす */
				//	out_byte |= in_byte;
				//}
				//↓2004/06/06変更。1bit時の色2以降は透過色とみなすようになりました。
				if(in_byte < (1 << bpp)) {
					out_byte |= in_byte;
				}
			}
			if(out_type == TYPE_TEXT) {
				fprintf(fp, "0x%02x,", out_byte);
			} else {
				fwrite(&out_byte, 1, 1, fp);
			}
		}
		if(out_type == TYPE_TEXT) {
			fprintf(fp, "\n");
		}
	}
	/* マスクデータを出力します。 */
	if(mask) {
		if(out_type == TYPE_TEXT) {
			fprintf(fp, "/*mask*/\n");
		}
		for(y = 0; y < out_height; y++) {
			for(x = 0; x < out_width; x += 8) {
				out_byte = 0;
				for(i = 0; i < 8; i++) {
					out_byte <<= 1;
					in_byte = in_data[y][x + i];
					//if(in_byte < 4) {
					//	out_byte |= 1;
					//}
					//↓2004/06/06変更
					if(in_byte < (1 << bpp)) {
						out_byte |= 1;
					}
				}
				if(out_type == TYPE_TEXT) {
					fprintf(fp, "0x%02x,", out_byte);
				} else {
					fwrite(&out_byte, 1, 1, fp);
				}
			}
			if(out_type == TYPE_TEXT) {
				fprintf(fp, "\n");
			}
		}
	}
	/* C言語配列の終了。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "};\n");
	}
}
/****************************************************************************
 *	writechip8
 ****************************************************************************/
void writechip8(FILE* fp) {	/* 2004/04/02追加 */
	int i, y, x1, x2;
	unsigned char in_byte, out_byte;
	if(out_type != TYPE_CHIPPER) abort();
	/* サイズ出力。 */
	fprintf(fp, "%s_W = %d\n", out_label, out_width);
	fprintf(fp, "%s_H = %d\n", out_label, out_height);
	/* ラベル出力。 */
	fprintf(fp, "%s:\n", out_label);
	/* 各カラムについて... */
	i = 0;
	for(x1 = 0; x1 < out_width; x1 += 8) {
		/* 各ラインについて... */
		for(y = 0; y < out_height; y++) {
			out_byte = 0;
			/* 各ピクセルについて... */
			for(x2 = 0; x2 < 8; x2++) {
				in_byte = in_data[y][x1 + x2];
				if(in_byte) in_byte = 1; /* カラー0以外は全て1と見なす */
				/* 左:MSB<->LSB:右 */
				out_byte = (out_byte << 1) | in_byte;
			}
			/* 1バイト出力。16バイト毎に改行します。 */
			if(!(i & 15)) {
				fprintf(fp, "\tdb ");
			} else {
				fprintf(fp, ",");
			}
			fprintf(fp, "#%02x", out_byte); /* ChipperではHex定数を「#xx」と表記します */
			i++;
			if(!(i & 15)) {
				fprintf(fp, "\n");
			}
		}
	}
	/* 最終行が未改行ならば、改行を付加します。 */
	if(i & 15) {
		fprintf(fp, "\n");
	}
}
/****************************************************************************
 *	writeschip
 ****************************************************************************/
void writeschip(FILE* fp) {	/* 2004/04/02追加 */
	int i, y, x1, x2;
	unsigned char in_byte;
	unsigned short out_half;
	if(out_type != TYPE_CHIPPER) abort();
	/* サイズ出力。 */
	fprintf(fp, "%s_W = %d\n", out_label, out_width);
	fprintf(fp, "%s_H = %d\n", out_label, out_height);
	/* ラベル出力。 */
	fprintf(fp, "%s:\n", out_label);
	/* 各カラムについて... */
	i = 0;
	for(x1 = 0; x1 < out_width; x1 += 16) {
		/* 各ラインについて... */
		for(y = 0; y < out_height; y++) {
			out_half = 0;
			/* 各ピクセルについて... */
			for(x2 = 0; x2 < 16; x2++) {
				in_byte = in_data[y][x1 + x2];
				if(in_byte) in_byte = 1; /* カラー0以外は全て1と見なす */
				/* 左:MSB<->LSB:右 */
				out_half = (out_half << 1) | in_byte;
			}
			/* 1ハーフワード出力。16ハーフワード毎に改行します。 */
			if(!(i & 15)) {
				fprintf(fp, "\tdw ");
			} else {
				fprintf(fp, ",");
			}
			fprintf(fp, "#%04x", out_half); /* ChipperではHex定数を「#xxxx」と表記します */
			i++;
			if(!(i & 15)) {
				fprintf(fp, "\n");
			}
		}
	}
	/* 最終行が未改行ならば、改行を付加します。 */
	if(i & 15) {
		fprintf(fp, "\n");
	}
}
/****************************************************************************
 *	writeuvi
 ****************************************************************************/
void writeuvi(FILE* fp) {	/* 2005/05/11追加 */
	int i;
	int c;
	int x0;
	int y0;
	int x1;
	int y1;
	int out_byte;
	int count[8];	/* カラー8未満(前景色:Cc)の出現カウント */
	int opaque;	/* 不透明キャラクタ? */
	if(out_type != TYPE_VACS) abort();
	/* サイズ出力。 */
	fprintf(fp, "%s_W\tequ\t%d\n", out_label, out_width  / 3);
	fprintf(fp, "%s_H\tequ\t%d\n", out_label, out_height / 2);
	/* ラベル出力。 */
	fprintf(fp, "%s:\n", out_label);
	/* 各ROWについて... */
	for(y0 = 0; y0 < out_height; y0 += 2) {
		fprintf(fp, "\tdb\t");
		/* 各COLについて... */
		for(x0 = 0; x0 < out_width; x0 += 3) {
			/*
			 *	Graphics mode character code B7 B6 D5 D4 D3 D2 D1 D0
			 *				     --+-- --------+--------
			 *	 M = 0: Color mode 0	       |           |
			 *	+-------------------+	       |           |
			 *	| Font              |	       |           |
			 *	| Video C1  C2  C3  |	       |           |
			 *	| ----------------- |          |           |
			 *	|    1  B7  B6  Cc3 | <--------+	   |
			 *	|    0  Cs1 Cs2 Cs3 |	                   |
			 *	+-------------------+	                   |
			 *				                   |
			 *	+----+----+----+	                   |
			 *	| D2 | D1 | D0 |	                   |
			 *	+----+----+----+ <-------------------------+
			 *	| D5 | D4 | D3 |
			 *	+----+----+----+
			 *
			 *	------	------
			 *	コード	カラー
			 *	------	------
			 *	 0	 白
			 *	 1	 黄
			 *	 2	 空色
			 *	 3	 緑
			 *	 4	 紫色
			 *	 5	 赤
			 *	 6	 青
			 *	 7	 黒
			 *	 8	 不透明背景色 ... 独自仕様
			 *	 9以上	 透明(背景色) ... 独自仕様
			 *	------	------
			 */
			opaque = 0;
			out_byte = 0;
			memset(count, 0, sizeof count);
			for(y1 = 1; y1 >= 0; y1--) {		/* y1 = 1,0   */
				for(x1 = 0; x1 <= 2; x1++) {	/* x1 = 0,1,2 */
					c = in_data[y0 + y1][x0 + x1];
					out_byte <<= 1;
					if(c < 9) {
						/* カラーコード#8は、不透明背景色と見なすことにします。
						 * (このツールの独自仕様です。UVIの仕様ではありません。)
						 * カラーコード#0..7を含むキャラは、もちろん不透明です。
						 */
						opaque = 1;
						if(c < 8) { /* 前景色(#0..7)ならば、出現数をカウント */
							out_byte |= 1;
							count[c]++;
						}
					}
				}
			}
			/* 前景色(0..7)のうち、最多出現色を求めます。 */
			c = 0;
			for(i = 1; i <= 7; i++) {
				if(count[i] > count[c]) {
					c = i;
				}
			}
			/* 最多出現色のD2:1を、キャラクタコードのD7:6とします。 */
			out_byte |= (c & 6) << 5;
			/* キャラ全体が不透明背景色の場合は、不透明を示すためにD7:6にダミービットを立てます。 */
			if(!out_byte && opaque) {
				out_byte |= 0xc0;
			}
			/* 1バイト出力します。 */
			if(x0) {
				fprintf(fp, ",", out_byte);
			}
			fprintf(fp, "$%02x", out_byte);
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "\tend\n");
}
/****************************************************************************
 *	writevqtc
 ****************************************************************************/
//{{2016/12/21削除:clipvqtc.hにVQTC_DATAHEADER構造体の定義を追加した事に伴い、当ツールのソース内での定義を削除しました。
////VQ圧縮テクスチャ形式のデータヘッダ
//typedef struct _VQTC_DATAHEADER {
//	unsigned short	sig;	//+ 0, 2 シグネチャ	"QV"固定	PBMP_FILEHEADER.headの流儀に従って、リトルエンディアンで読み込んだ時に'VQ'となるように、文字列の並びとしては逆順にする事にした。
//	unsigned short	k_1;	//+ 2, 2 符号の数-1	0〜255		//{{2016/12/25コメント追記:clipvqtc.cモジュールにて、符号の数の上限を256⇒65536に変更した事に伴い、当ツールの'-k'オプション,及び,ファイル名サフィックスによる符号の数の目標値の指定も、上限を65536に変更しました。}}
//} VQTC_DATAHEADER;		//= 4
//}}2016/12/21削除:clipvqtc.hにVQTC_DATAHEADER構造体の定義を追加した事に伴い、当ツールのソース内での定義を削除しました。
/*--------------------------------------------------------------------------*/
void writevqtc(FILE* fp) {	/* 2016/12/20追加 */
	PBMP_FILEHEADER hdr;
	VQTC_DATAHEADER dathdr;
	int c, i, k, codeBytes;
	unsigned char *codebook, *code;
	//圧縮データを作成する。
//{{2016/12/26変更:'-k'オプションもファイル名サフィックスも指定されなかった時の、符号の数の目標値の既定値を変更しました。
//	k = vqtc_k ? vqtc_k : 256/*既定値*/;	//{{2016/12/25コメント追記:符号の数の上限を256⇒65536に変更しましたが、'-k'オプションもファイル名サフィックスも指定しなければ、符号の数の目標値の既定値はこれまで通り256となります。}}
//↓2016/12/26変更:'-k'オプションもファイル名サフィックスも指定されなかった時の、符号の数の目標値の既定値を変更しました。
	if(vqtc_k) {
		k = vqtc_k;
	} else {
		int cols = (in_width  + 3) / 4;	//セル列数
		int rows = (in_height + 3) / 4;	//セル行数
		k = (cols * rows);		//全セル数
		if(k > 65536) { k = 65536; }	//全セルのうち重複しているセルを圧縮する。ただしclipvqtc.cの仕様により65536セルを上限とする。
	}
//}}2016/12/26変更:'-k'オプションもファイル名サフィックスも指定されなかった時の、符号の数の目標値の既定値を変更しました。
	codebook = malloc(k * 5);
	if(!codebook) { DIE(); }
	code = malloc(VqTc_CalculateCodeBytes(out_width, out_height, k));
	if(!code) { DIE(); }
	k = VqTc_EncodeImage(&in_data[0][0], out_width, out_height, MAX_SIZE, codebook, k, code);
	codeBytes = VqTc_CalculateCodeBytes(out_width, out_height, k);
	/* C言語配列の開始。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "const unsigned char %s[] = {\n", out_label);
	}
	/* ヘッダを出力します。 */
	memset(&hdr, 0, sizeof hdr);
	memcpy(&hdr.head, "PMBP", 4); /* シグネチャ */
	hdr.fsize     = sizeof hdr;		//┬ヘッダ
	hdr.fsize    += sizeof dathdr;		//│データヘッダ
	hdr.fsize    += ((k * 5) + 3) & ~3;	//│コードブック＋ワードアライメント
	hdr.fsize    += codeBytes;		//┘符号配列
	hdr.bpp       = 0;			//┬VQ圧縮テクスチャは、PBMP_FILEHEADERヘッダを利用していますが、独自形式です。
	hdr.mask      = 0;			//┘独自形式のPBMP_FILEHEADERヘッダはbppとmaskフィールドを0とし、データ本体の先頭部分に「データヘッダ」を埋め込んで、個々の形式(2016/12/20現在はVQ圧縮テクスチャ形式しか有りませんが)を識別する事にしました。
	hdr.w         = out_width;
	hdr.h         = out_height;
	hdr.buf_size  = sizeof dathdr;		//┬データヘッダ
	hdr.buf_size += ((k * 5) + 3) & ~3;	//│コードブック＋ワードアライメント
	hdr.buf_size += codeBytes;		//┘符号配列
	for(i = 0; i < sizeof hdr; i++) {
		c = ((unsigned char*)&hdr)[i];
		if(out_type == TYPE_TEXT) {
			fprintf(fp, "0x%02x,", c);
		} else {
			fwrite(&c, 1, 1, fp);
		}
	}
	/* データヘッダを出力します。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "\n/*dathdr*/\n");
	}
	memset(&dathdr, 0, sizeof dathdr);
	memcpy(&dathdr.sig, "QV", 2); /* シグネチャ */
	dathdr.k_1 = k - 1;
	for(i = 0; i < sizeof dathdr; i++) {
		c = ((unsigned char*)&dathdr)[i];
		if(out_type == TYPE_TEXT) {
			fprintf(fp, "0x%02x,", c);
		} else {
			fwrite(&c, 1, 1, fp);
		}
	}
	/* コードブック＋ワードアライメントを出力します。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "\n/*codebook*/\n");
	}
	for(i = 0; i < (((k * 5) + 3) & ~3); i++) {
		c = (i < (k * 5)) ? codebook[i]/*コードブック*/ : 0/*ワードアライメント*/;
		if(out_type == TYPE_TEXT) {
			if(i && !(i & 31/*調整可*/)) {
				fprintf(fp, "\n");
			}
			fprintf(fp, "0x%02x,", c);
		} else {
			fwrite(&c, 1, 1, fp);
		}
	}
	/* 符号配列を出力します。 */
	if(codeBytes) {	//'-k1'が指定された場合，又は，元データがベタ絵で符号1個に圧縮された場合、(codeBytes=0)になります。その場合、以下の処理を行わない事にしました。バイナリ出力の場合は以下の処理を行っても同じ結果になりますが、テキスト出力の場合に無駄な空行が出力されて見栄えが悪くなるのを防ぐためです。
		if(out_type == TYPE_TEXT) {
			fprintf(fp, "\n/*code*/\n");
		}
		for(i = 0; i < codeBytes; i++) {
			c = code[i]/*符号配列*/;
			if(out_type == TYPE_TEXT) {
				if(i && !(i & 31/*調整可*/)) {
					fprintf(fp, "\n");
				}
				fprintf(fp, "0x%02x,", c);
			} else {
				fwrite(&c, 1, 1, fp);
			}
		}
	}
	/* C言語配列の終了。 */
	if(out_type == TYPE_TEXT) {
		fprintf(fp, "\n};\n");
	}
	//圧縮データを解放する。
	free(codebook);
	free(code);
}
