/*
 *	beatangl.c
 *
 *	「超昂天使エスカレイヤー」PGDコンバータ
 *	Copyright (C) 2002 Naoyuki Sawa
 *
 *	　　　　　　　　　　　　　　ＮＯＴＩＣＥ
 *	「System 3.5 for X Window System Version 1.5 (開発版)」のソースコード、
 *	およびドキュメントを利用・参考させて頂きました。
 *	「System 3.5 for X Window System」に関しては、以下のURLをご参照ください。
 *	http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/index.html
 *	「System 3.5 for X Window System Version 1.5 (開発版)」はGPLライセンスです。
 *	従いまして、本プログラムもGPLライセンスとなります。
 *	GPLライセンスに関しては、添付のCOPYINGファイルをご参照ください。
 *
 *	* Sun Oct 1 03:30:00 JST 2002 Naoyuki Sawa
 *	- 作成開始。
 */
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "zlib/zlib.h"
#pragma comment(lib, "zlibstat.lib")

#define REDUCE_LEVEL	(640 / 128)	/* 画像縮小率（一律） */
#define HEIGHT_LIMIT	88		/* 縮小後にこれより高かったら、下を切り捨てます */
#define ALPHA_CUTOFF	1		/* 透明カットオフレベル */
const int DITHER[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,
};

#define KEY_ESC		"Software\\AliceSoft\\超昂天使エスカレイヤー" /* インストールフォルダのレジストリキー */
#define ALD_QNT		"DOKI_GA.ALD"	/* QNTアーカイブファイル名 */

#define ZLIBBUF_MARGIN	(16 * 1024)	/* qnt.cでは5KBですが、安心のために16KB取ってみました */

/****************************************************************************/

typedef struct _ALDENT {
	int	prt;		/* データへのオフセット */
	int	size;		/* データサイズ */
	int	time_l;		/* 作成時刻 */
	int	time_h;		/* 作成時刻 */
	char	name[16];	/* ファイル名 */
} ALDENT;

#define QNTHDR_SIG	"QNT\0"
typedef struct _QNTHDR {
	char	sig[4];		/* 'QNT\0' */
	int	ver;		/* エスカレイヤーでは2 */
	int	header_size;	/* ヘッダサイズ(可変) */
	int	x0;		/* 画面上での表示位置X */
	int	y0;		/* 画面上での表示位置Y */
	int	width;		/* CGの幅[ピクセル] */
	int	height;		/* CGの高さ[ピクセル] */
	int	bpp;		/* 24固定 */
	int	rsv;		/* 不明(現在は1？) */
	int	pixel_size;	/* 圧縮時ピクセルデータサイズ */
	int	alpha_size;	/* 圧縮時アルファデータサイズ */
} QNTHDR;

typedef struct _CG {
	int w;			/* 幅[ピクセル] */
	int h;			/* 高さ[ピクセル] */
	unsigned char* pixel;	/* ピクセルプレーン(NULL:なし) */
	unsigned char* alpha;	/* アルファプレーン(NULL:なし) */
} CG;

/****************************************************************************/

/****************************************************************************/

void
err(const char* fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);

	abort();
}

/****************************************************************************/

/* エスカレイヤーのフォルダ名を取得 */
int
get_esc_path(char* path)
{
	int retval, n;
	HKEY hkey;

	retval = RegOpenKeyEx(HKEY_CURRENT_USER, KEY_ESC, 0, KEY_QUERY_VALUE, &hkey);
	if(retval == 0) {
		n = _MAX_PATH;
		retval = RegQueryValueEx(hkey, NULL, 0, NULL, (unsigned char*)path, (unsigned long*)&n);
		RegCloseKey(hkey);
	}

	return retval;
}

/****************************************************************************/

int
find_entry(FILE* fp, char* name)
{
	int i, size;
	int ptr;
	ALDENT ae;

	/* 指定された名前のエントリを探します。 */
	for(i = 1/*最初の1つはheader2へのポインタです*/; ; i++) {
		/* データポインタへシーク。 */
		if(fseek(fp, i * 3, SEEK_SET) != 0) return 0;
		/* データポインタ取得。 */
		if(fread(&ptr, 1, 3, fp) != 3) return 0;
		ptr = (ptr & 0xffffff) << 8;
		/* データヘッダへシーク。 */
		if(fseek(fp, ptr, SEEK_SET) != 0) return 0;
		/* データヘッダ取得。 */
		if(fread(&ae, 1, sizeof ae, fp) != sizeof ae) return 0;
		/* 名前が一致したら... */
		if(_strcmpi(ae.name, name) == 0) { /* 大文字小文字無視！ */
			/* データサイズ取得。 */
			size = ae.size;
			/* データ本体へシーク。 */
			if(fseek(fp, ae.prt - sizeof ae, SEEK_CUR)) return 0;
			/* データ本体のサイズを返す。 */
			return size;
		}
	}
	return 0;
}

/****************************************************************************/

/* ピクセル形式はまだあまり理解できていません。qnt.cのソースをほぼそのまま使わせて頂きました。 */
int
extract_pixel(QNTHDR* qnt, unsigned char* pixel, unsigned char* data)
{
	int i, j, x, y, w, h, ucbuf;
	unsigned char* raw;

	w = qnt->width;
	h = qnt->height;
	ucbuf = w * h * 3 + ZLIBBUF_MARGIN;
	raw = (unsigned char*)malloc(ucbuf);
	if(uncompress(raw, &ucbuf, data, qnt->pixel_size) != Z_OK) err("ピクセル展開失敗。");

	j = 0;
	for(i = 2; i >= 0; i--) {
		for(y = 0; y < (h-1); y+=2) {
			for(x = 0; x < (w-1); x+=2) {
				pixel[( y   *w+x)  *3 +i] = raw[j  ];
				pixel[((y+1)*w+x)  *3 +i] = raw[j+1];
				pixel[( y   *w+x+1)*3 +i] = raw[j+2];
				pixel[((y+1)*w+x+1)*3 +i] = raw[j+3];
				j+=4;
			}
			if(x != w) {
				pixel[( y   *w+x)*3 +i] = raw[j  ];
				pixel[((y+1)*w+x)*3 +i] = raw[j+1];
				j+=4;
			}
		}
		if(y != h) {
			for(x = 0; x < (w-1); x+=2) {
				pixel[(y*w+x  )*3+i] = raw[j  ];
				pixel[(y*w+x+1)*3+i] = raw[j+2];
				j+=4;
			}
		}
	}

	if(w > 1) {
		for(x = 1; x < w; x++) {
			pixel[x*3  ] = pixel[(x-1)*3  ] - pixel[x*3  ];
			pixel[x*3+1] = pixel[(x-1)*3+1] - pixel[x*3+1];
			pixel[x*3+2] = pixel[(x-1)*3+2] - pixel[x*3+2];
		}
	}

	if(h > 1) {
		for(y = 1; y < h; y++) {
			pixel[(y*w)*3  ] = pixel[((y-1)*w)*3  ] - pixel[(y*w)*3  ];
			pixel[(y*w)*3+1] = pixel[((y-1)*w)*3+1] - pixel[(y*w)*3+1];
			pixel[(y*w)*3+2] = pixel[((y-1)*w)*3+2] - pixel[(y*w)*3+2];
			
			for(x = 1; x < w; x++) {
				int px, py;
				py = pixel[((y-1)*w+x  )*3];
				px = pixel[( y   *w+x-1)*3];
				pixel[(y*w+x)*3  ] = ((py+px)>>1) - pixel[(y*w+x)*3  ];
				py = pixel[((y-1)*w+x  )*3+1];
				px = pixel[( y   *w+x-1)*3+1];
				pixel[(y*w+x)*3+1] = ((py+px)>>1) - pixel[(y*w+x)*3+1];
				py = pixel[((y-1)*w+x  )*3+2];
				px = pixel[( y   *w+x-1)*3+2];
				pixel[(y*w+x)*3+2] = ((py+px)>>1) - pixel[(y*w+x)*3+2];
			}
		}
	}

	free(raw);

	return 0;
}

/****************************************************************************/

/* アルファ形式はまだあまり理解できていません。qnt.cのソースをほぼそのまま使わせて頂きました。 */
int
extract_alpha(QNTHDR* qnt, unsigned char* alpha, unsigned char* data)
{
	int i, x, y, w, h, ucbuf;
	unsigned char* raw;
	
	w = qnt->width;
	h = qnt->height;
	ucbuf = w * h + ZLIBBUF_MARGIN;
	raw = (unsigned char*)malloc(ucbuf);
	if(uncompress(raw, &ucbuf, data, qnt->alpha_size) != Z_OK) err("アルファ展開失敗。");

	i = 1;
	if(w > 1) {
		alpha[0] = raw[0];
		for(x = 1; x < w; x++) {
			alpha[x] = alpha[x-1] - raw[i];
			i++;
		}
	}

	if(h > 1) {
		for(y = 1; y < h; y++) {
			alpha[y*w] = alpha[(y-1) *w] - raw[i]; i++;
			for(x = 1; x < w; x++) {
				int pax, pay;
				pax = alpha[ y   * w + x -1];
				pay = alpha[(y-1)* w + x   ];
				alpha[y*w+x] = ((pax+pay) >> 1) - raw[i];
				i++;
			}
		}
	}

	free(raw);

	return 0;
}

/****************************************************************************/


CG*
qnt_extract(unsigned char* data)
{
	QNTHDR* qnt = (QNTHDR*)data;
	CG* cg;

	/* CG構造体を確保します。 */
	cg = (CG*)calloc(1, sizeof(CG));
	if(cg == NULL) err("メモリ不足です。");

	/* シグネチャ・サイズ・ビット深度。 */
	if(memcmp(qnt->sig, QNTHDR_SIG, 4) != 0) err("シグネチャが不正です。");
	cg->w = qnt->width;
	cg->h = qnt->height;
	if(qnt->bpp != 24) err("ビット深度が不正です。");

	/* ピクセル・アルファ。 */
	data += qnt->header_size;
	if(qnt->pixel_size != 0) {
		cg->pixel = (unsigned char*)malloc((cg->w+10) * (cg->h+10) * 3); /* +10は必要なのかな？→必要。+10しないとなぜかGPFで落ちることがあります */
		if(cg->pixel == NULL) err("メモリ不足です。");
		if(extract_pixel(qnt, cg->pixel, data) != 0) err("ピクセルデータの展開に失敗しました。");
		data += qnt->pixel_size;
	}
	if(qnt->alpha_size != 0) {
		cg->alpha = (unsigned char*)malloc(cg->w * cg->h * 1);
		if(cg->alpha == NULL) err("メモリ不足です。");
		if(extract_alpha(qnt, cg->alpha, data) != 0) err("アルファデータの展開に失敗しました。");
		data += qnt->alpha_size;
	}

	return cg;
}

/****************************************************************************/

int
reduce(CG* cg, int s)
{
	int dx, dy, sx, sy, dw, dh, sw, sh, r, g, b, a, n;
	unsigned char *pixel, *alpha;

	/* 縮小前・縮小後のサイズを求めます。 */
	sw = cg->w;
	sh = cg->h;
	dw = (sw + (s - 1)) / s;
	dh = (sh + (s - 1)) / s;

	/* 縮小後のバッファを確保します。 */
	if(cg->pixel != NULL) {
		pixel = (unsigned char*)malloc(dw * dh * 3);
		if(pixel == NULL) err("メモリ不足です。");
	} else {
		pixel = NULL;
	}
	if(cg->alpha != NULL) {
		alpha = (unsigned char*)malloc(dw * dh * 1);
		if(alpha == NULL) err("メモリ不足です。");
	} else {
		alpha = NULL;
	}

	/* 縮小処理。 */
	for(dy = 0; dy < dh; dy++) {
		for(dx = 0; dx < dw; dx++) {
			/* 縮小元のピクセルを加算。 */
			r = 0;
			g = 0;
			b = 0;
			a = 0;
			n = 0;
			for(sy = dy * s; sy < (dy + 1) * s; sy++) {
				if(sy > sh) continue;
				for(sx = dx * s; sx < (dx + 1) * s; sx++) {
					if(sx > sw) continue;
					if(cg->pixel != NULL) {
						r += cg->pixel[(sw * sy + sx) * 3 + 0];
						g += cg->pixel[(sw * sy + sx) * 3 + 1];
						b += cg->pixel[(sw * sy + sx) * 3 + 2];
					}
					if(cg->alpha != NULL) {
						a += cg->alpha[(sw * sy + sx) * 1 + 0];
					}
					n++;
				}
			}
			/* 平均して縮小後のピクセルへ。 */
			r /= n;
			g /= n;
			b /= n;
			a /= n;
			if(pixel != NULL) {
				pixel[(dw * dy + dx) * 3 + 0] = r;
				pixel[(dw * dy + dx) * 3 + 1] = g;
				pixel[(dw * dy + dx) * 3 + 2] = b;
			}
			if(alpha != NULL) {
				alpha[(dw * dy + dx) * 1 + 0] = a;
			}
		}
	}

	/* CGを縮小後のデータに置き換えます。 */
	cg->w = dw;
	cg->h = dh;
	free(cg->pixel); /* free(NULL)は安全 */
	cg->pixel = pixel;
	free(cg->alpha); /* free(NULL)は安全 */
	cg->alpha = alpha;

	return 0;
}

/****************************************************************************/

int
export_bmp24(FILE* fp, CG* cg)
{
//#define ALPHA /* これを定義するとピクセルの代りにアルファを出力します */

	int x, y, w, h, line_bytes;
	unsigned char *line_buffer, *src, *dst;
	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;

	w = cg->w;
	h = cg->h;

	/* 4バイトアラインのためのラインバッファを確保します。 */
	line_bytes = w * 3 + 3 & ~3;
	line_buffer = (unsigned char*)malloc(line_bytes);
	if(line_buffer == NULL) err("メモリ不足です。");
	memset(line_buffer, 0, line_bytes); /* パディング部分を確実にクリア */

	/* ファイルヘッダ出力。 */
	memset(&bf, 0, sizeof bf);
	bf.bfType = 'MB';
	bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + line_bytes * h;
	bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	if(fwrite(&bf, 1, sizeof bf, fp) != sizeof bf) err("ファイルヘッダ出力失敗。");

	/* ビットマップヘッダ出力。 */
	memset(&bi, 0, sizeof bi);
	bi.biSize = sizeof bi;
	bi.biWidth = w;
	bi.biHeight = h;
	bi.biPlanes = 1;
	bi.biBitCount = 24;
	if(fwrite(&bi, 1, sizeof bi, fp) != sizeof bi) err("ビットマップヘッダ出力失敗。");

	/* データ出力。 */
	for(y = h - 1; y >= 0; y--) {
#ifdef ALPHA
		dst = line_buffer;
		src = cg->alpha + w * 1 * y;
		for(x = 0; x < w; x++) {
			dst[0] = src[0];
			dst[1] = src[0];
			dst[2] = src[0];
			dst += 3;
			src += 1;
		}
#else /*ALPHA*/
		dst = line_buffer;
		src = cg->pixel + w * 3 * y;
		for(x = 0; x < w; x++) {
			dst[0] = src[2];
			dst[1] = src[1];
			dst[2] = src[0];
			dst += 3;
			src += 3;
		}
#endif /*ALPHA*/
		if(fwrite(line_buffer, 1, line_bytes, fp) != (unsigned)line_bytes) err("データ出力失敗。");
	}

	/* ラインバッファを開放します。 */
	free(line_buffer);

	return 0;

#undef ALPHA
}

/****************************************************************************/

int
export_bmp8(FILE* fp, CG* cg)
{
	int x, y, w, h, line_bytes;
	int c, r, g, b, a;
	unsigned char *line_buffer, *src, *dst, *alp;
	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;
	RGBQUAD rgb[256];

	w = cg->w;
	h = cg->h;

	/* 4バイトアラインのためのラインバッファを確保します。 */
	line_bytes = w + 3 & ~3;
	line_buffer = (unsigned char*)malloc(line_bytes);
	if(line_buffer == NULL) err("メモリ不足です。");
	memset(line_buffer, 0, line_bytes); /* パディング部分を確実にクリア */

	/* ファイルヘッダ出力。 */
	memset(&bf, 0, sizeof bf);
	bf.bfType = 'MB';
	bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + line_bytes * h;
	bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256;
	if(fwrite(&bf, 1, sizeof bf, fp) != sizeof bf) err("ファイルヘッダ出力失敗。");

	/* ビットマップヘッダ出力。 */
	memset(&bi, 0, sizeof bi);
	bi.biSize = sizeof bi;
	bi.biWidth = w;
	bi.biHeight = h;
	bi.biPlanes = 1;
	bi.biBitCount = 8;
	if(fwrite(&bi, 1, sizeof bi, fp) != sizeof bi) err("ビットマップヘッダ出力失敗。");

	/* パレット出力。 */
	for(c = 0; c < 4; c++) {
		rgb[c].rgbRed       = 85 * (3 - c);
		rgb[c].rgbGreen     = 85 * (3 - c);
		rgb[c].rgbBlue      = 85 * (3 - c);
		rgb[c].rgbReserved  = 0;
	}
	for(c = 4; c < 256; c++) {
		rgb[c].rgbRed       = 0;
		rgb[c].rgbGreen     = 255;
		rgb[c].rgbBlue      = 0;
		rgb[c].rgbReserved  = 0;
	}
	if(fwrite(rgb, 1, sizeof rgb, fp) != sizeof rgb) err("パレット出力失敗。");

	/* データ出力。 */
	for(y = h - 1; y >= 0; y--) {
		dst = line_buffer;
		src = cg->pixel + w * 3 * y;
		alp = cg->alpha != NULL ? cg->alpha + w * 1 * y : NULL;
		for(x = 0; x < w; x++) {
			r = src[0];
			g = src[1];
			b = src[2];
			a = alp != NULL ? alp[0] : 0xff;
			if(a >= ALPHA_CUTOFF) {
				c = (r * 3 + g * 5 + b * 2) / 10;
				c = (c + DITHER[y & 7][x & 7] + (85 - 63) / 2) / 85;
				if(c > 3) c = 3;
				c = 3 - c;
			} else {
				c = 4;
			}
			dst[0] = c;
			dst += 1;
			src += 3;
			if(alp != NULL) alp += 1;
		}
		if(fwrite(line_buffer, 1, line_bytes, fp) != (unsigned)line_bytes) err("データ出力失敗。");
	}

	/* ラインバッファを開放します。 */
	free(line_buffer);

	return 0;
}

/****************************************************************************/

void
usage()
{
	fprintf(stderr, "使い方：\n");
	fprintf(stderr, "  beatangl [options] <qnt-entry-name[.qnt]>\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "オプション：\n");
	fprintf(stderr, "  -b        24ビットBMPファイルを出力  （初期値＝PGDファイルを出力 ）\n");
	fprintf(stderr, "  -d<path>  エスカレイヤーフォルダ指定 （初期値＝レジストリから取得）\n");
	exit(1);
}

/****************************************************************************/

char esc_path[_MAX_PATH];	/* エスカレイヤーのフォルダ名 */
char ald_path[_MAX_PATH];	/* ALDファイルのフルパス名 */
char qnt_path[_MAX_PATH];	/* 取り出すQNTのエントリ名(CG0002.QNTなど) */
char qnt_fname[_MAX_FNAME];	/* QNTのファイル名(CG0002など) */
char qnt_ext[_MAX_EXT];		/* QNTの拡張子(.QNTなど) */
char bmp_path[_MAX_PATH];	/* BMP出力ファイル名 */

int opt_bmp24;			/* 24ビットBMP出力(テスト用) */

int
main(int argc, char* argv[])
{
	int retval, i, size;
	char *p, cmd[256];
	unsigned char* data;
	FILE* fp;
	CG* cg;

	/* コマンドライン解析。 */
	for(i = 1; i < argc; i++) {
		p = argv[i];
		if(p[0] == '-') { /* オプション */
			switch(p[1]) {
			case 'b': /* 24ビットBMP出力 */
				if(opt_bmp24) usage(); /* 二重指定 */
				opt_bmp24 = 1;
				break;
			case 'd': /* 「エスカレイヤー」フォルダ指定 */
				if(strlen(esc_path) != 0) usage(); /* 二重指定 */
				strncpy(esc_path, &p[2], sizeof esc_path);
				break;
			default:
				usage();
			}
		} else {
			/* 抽出するQNTエントリ名 */
			if(strlen(qnt_path) != 0) usage(); /* 二重指定 */
			strncpy(qnt_path, p, sizeof qnt_path);
		}
	}

	/* QNTエントリ名を取得します。 */
	if(strlen(qnt_path) == 0) usage(); /* 抽出エントリ未指定 */
	_splitpath(qnt_path, NULL, NULL, qnt_fname, qnt_ext);
	if(strlen(qnt_ext) == 0) strcpy(qnt_ext, ".qnt");
	_makepath(qnt_path, NULL, NULL, qnt_fname, qnt_ext);

	/* ALDファイル名を取得します。 */
	if(strlen(esc_path) == 0) { /* フォルダが明示されていなければレジストリから取得 */
		retval = get_esc_path(esc_path);
		if(retval != 0) err("「超昂天使エスカレイヤー」がインストールされていないようです。");
	}
	_makepath(ald_path, NULL, esc_path, ALD_QNT, NULL);

	/* ALDファイルを開きます。 */
	fp = fopen(ald_path, "rb");
	if(fp == NULL) err("%sが開けません。", ald_path);

	/* 目的のQNTエントリを探します。 */
	size = find_entry(fp, qnt_path);
	if(size == 0) err("%sが見つかりません。", qnt_path);

	/* QNTデータを読み込みます。 */
	data = (unsigned char*)malloc(size);
	if(data == NULL) err("%sを読み込むためのメモリが足りません。", qnt_path);
	if(fread(data, 1, size, fp) != (unsigned)size) err("%sが読み込めません。", qnt_path);

	/* QNTデータを展開します。 */
	fprintf(stderr, "%s展開中...", qnt_path);
	cg = qnt_extract(data);
	if(cg == NULL) err("ERR");
	fprintf(stderr, "OK\n");

	/* QNTデータを開放します。 */
	free(data);

	/* ALDファイルを閉じます。 */
	fclose(fp);

	/* 縮小。 */
	if(reduce(cg, REDUCE_LEVEL) != 0) err("%sの縮小に失敗しました。", qnt_path);
	if(cg->h > HEIGHT_LIMIT) cg->h = HEIGHT_LIMIT; /* P/VNSは下揃え。上が切れるより下が切れる方がいい。 */

	if(opt_bmp24) {
		/* 24ビットBMPを出力。 */
		_makepath(bmp_path, NULL, NULL, qnt_fname, ".bmp");
		fp = fopen(bmp_path, "wb");
		if(fp == NULL) err("%sが作成できません。");
		fprintf(stderr, "%s出力中...", bmp_path);
		if(export_bmp24(fp, cg) != 0) err("ERR");
		fprintf(stderr, "OK\n");
		fclose(fp);
	} else {
		/* 8ビットBMPを出力。 */
		_makepath(bmp_path, NULL, NULL, qnt_fname, ".bmp");
		fp = fopen(bmp_path, "wb");
		if(fp == NULL) err("%sが作成できません。");
		fprintf(stderr, "%s出力中...", bmp_path);
		if(export_bmp8(fp, cg) != 0) err("ERR");
		fprintf(stderr, "OK\n");
		fclose(fp);
		/* PGDに変換。 */
		if(cg->alpha != NULL) { /* 2bitマスク付き */
			sprintf(cmd, "dpbmpcnv -q -b -f2m \"%s\"", bmp_path); /* -q必要! */
		} else { /* 2bitマスクなし */
			sprintf(cmd, "dpbmpcnv -q -b -f2  \"%s\"", bmp_path); /* -q必要! */
		}
		if(system(cmd) != 0) err("PGD変換に失敗しました。");
		remove(bmp_path); /* BMPはもういらないので削除 */
	}

	return 0;
}
