//=============================================================================
// ChipMaker
// ビットマップ画像からBGの各種データを作り出す
//=============================================================================
#include "pch.h"
#include "framework.h"
#include "afxdialogex.h"

#include "ChipMaker.h"
#include "CRes.h"
#include "memory_map_buffer.h"
#include "LogFile.h"

int numberPattern[16][8][8] = {
	{
		{0,0,1,1,1,0,0,0},
		{0,1,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,0,1,2,1,0},
		{1,2,1,0,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{0,1,2,2,2,1,1,0},
		{0,0,1,1,1,1,0,0},
	}, {
		{0,0,0,1,0,0,0,0},
		{0,0,1,2,1,0,0,0},
		{0,0,1,2,1,0,0,0},
		{0,0,1,2,1,0,0,0},
		{0,0,1,2,1,0,0,0},
		{0,0,1,2,1,0,0,0},
		{0,0,1,2,1,0,0,0},
		{0,0,0,1,0,0,0,0},
	}, {
		{0,0,1,1,1,0,0,0},
		{0,1,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{0,1,0,0,1,2,1,0},
		{0,0,1,2,2,1,0,0},
		{0,1,2,1,1,1,0,0},
		{1,2,2,2,2,2,1,0},
		{0,1,1,1,1,1,0,0},
	}, {
		{0,1,1,1,1,0,0,0},
		{1,2,2,2,2,1,0,0},
		{0,1,1,1,1,2,1,0},
		{0,1,2,2,2,1,0,0},
		{0,0,1,1,1,2,0,0},
		{0,1,1,1,1,2,1,0},
		{1,2,2,2,2,1,0,0},
		{0,1,1,1,1,0,0,0},
	}, {
		{0,1,0,0,1,0,0,0},
		{1,2,1,1,2,1,0,0},
		{1,2,1,1,2,1,0,0},
		{1,2,1,1,2,1,1,0},
		{1,2,2,2,2,2,2,1},
		{1,1,1,1,2,1,1,0},
		{0,0,0,0,2,1,0,0},
		{0,0,0,0,1,0,0,0},
	}, {
		{1,1,1,1,1,1,0,0},
		{1,2,2,2,2,2,1,0},
		{1,2,1,1,1,1,0,0},
		{1,2,2,2,2,1,1,0},
		{0,1,1,1,1,2,1,0},
		{0,1,1,1,1,2,1,0},
		{1,2,2,2,2,1,0,0},
		{0,1,1,1,1,0,0,0},
	}, {
		{0,0,1,1,1,1,0,0},
		{0,1,2,2,2,2,1,0},
		{1,2,1,1,1,1,1,0},
		{1,2,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{0,1,2,2,2,1,0,0},
		{0,0,1,1,1,0,0,0},
	}, {
		{0,1,1,1,1,1,0,0},
		{1,2,2,2,2,2,1,0},
		{0,1,1,1,1,2,1,0},
		{0,0,0,0,1,2,1,0},
		{0,0,0,1,2,1,0,0},
		{0,0,1,2,1,0,0,0},
		{0,1,2,1,0,0,0,0},
		{0,0,1,0,0,0,0,0},
	}, {
		{0,0,1,1,1,0,0,0},
		{0,1,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{0,1,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{0,1,2,2,2,1,0,0},
		{0,0,1,1,1,0,0,0},
	}, {
		{0,0,1,1,1,0,0,0},
		{0,1,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{0,1,2,2,2,2,1,0},
		{0,1,1,1,1,2,1,0},
		{1,2,2,2,2,1,0,0},
		{0,1,1,1,1,1,0,0},
	}, {	// A
		{0,0,1,1,1,0,0,0},
		{0,1,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{1,2,2,2,2,2,1,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,0,0,2,1,0},
		{0,1,0,0,0,1,0,0},
	}, {	// B
		{1,1,1,1,1,0,0,0},
		{1,2,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,2,2,2,1,1,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{1,2,2,2,2,1,0,0},
		{0,1,1,1,1,1,0,0},
	}, {	// C
		{0,0,1,1,1,1,0,0},
		{0,1,2,2,2,2,1,0},
		{1,2,1,1,1,1,0,0},
		{1,2,1,0,0,0,0,0},
		{1,2,1,0,0,0,0,0},
		{1,2,1,1,1,1,0,0},
		{0,1,2,2,2,2,1,0},
		{0,0,1,1,1,1,0,0},
	}, {	// D
		{0,1,1,1,1,0,0,0},
		{1,2,2,2,2,1,0,0},
		{1,2,1,1,1,2,1,0},
		{1,2,1,0,1,2,1,0},
		{1,2,1,0,1,2,1,0},
		{1,2,1,1,1,2,1,0},
		{1,2,2,2,2,1,0,0},
		{0,1,1,1,1,0,0,0},
	}, {	// E
		{0,1,1,1,1,1,0,0},
		{1,2,2,2,2,2,1,0},
		{1,2,1,1,1,1,1,0},
		{1,2,2,2,2,1,0,0},
		{1,2,1,1,1,0,0,0},
		{1,2,1,1,1,1,1,0},
		{1,2,2,2,2,2,1,0},
		{0,1,1,1,1,1,0,0},
	}, {	// F
		{0,1,1,1,1,1,0,0},
		{1,2,2,2,2,2,1,0},
		{1,2,1,1,1,1,1,0},
		{1,2,2,2,2,1,0,0},
		{1,2,1,1,1,0,0,0},
		{1,2,1,0,0,0,0,0},
		{1,2,1,0,0,0,0,0},
		{0,1,0,0,0,0,0,0},
	}
};

//--------------------------------------------------------------------
//	[ 書式 ]
//		ChipMaker()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		なし
//
//	[ 解説 ]
//		デフォルトコンストラクタ
//--------------------------------------------------------------------
ChipMaker::ChipMaker()
{
	pDCSource = NULL;
	pDCConverted = NULL;
	pDCPalet = NULL;
	srcPictureRect = CRect();
	cnvPictureRect = CRect();
	srcBitmap.Free();
	cnvBitmap.Free();
	convertedChipCount = 0;
	bg_map = NULL;
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		virtual ~ChipMaker()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		なし
//
//	[ 解説 ]
//		デストラクタ
//--------------------------------------------------------------------
ChipMaker::~ChipMaker()
{
	// 解放
	Release();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes Initialize()
//
//	[ 引数 ]
//		CDC* pDCSource	ソースとなるビットマップの表示用DC
//		CRect& rSrcPictureRect
//		CRect& rCnvPicbureRect
//
//	[ 戻り値 ]
//		結果を格納したCResオブジェクト
//
//	[ 解説 ]
//		各種の初期化処理を実行します。
//		既に読み込まれているリソースがある場合は、すべて解放されます。
//--------------------------------------------------------------------
CRes ChipMaker::Initialize(CDC* pDCSource, CRect& rSrcPictureRect, CDC* pDCConverted, CRect& rCnvPictureRect, CDC* pDCPalet, CRect& rPalPictureRect)
{
	// 既存のリソースがある場合は解放する
	CRes res = Release();

	// DCを設定
	this->pDCSource = pDCSource;
	this->pDCConverted = pDCConverted;
	this->pDCPalet = pDCPalet;

	// ソース画像の描画範囲を保存
	this->srcPictureRect = rSrcPictureRect;
	this->cnvPictureRect = rCnvPictureRect;
	this->palPictureRect = rPalPictureRect;

	// 画像を初期化
	srcBitmap.Free();
	cnvBitmap.Free();
	palBitmap.Free();
	convertedChipCount = 0;
	return res;
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes Release()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		成功：true
//		失敗：false
//
//	[ 解説 ]
//		読み込まれているリソースを解放します
//--------------------------------------------------------------------
CRes ChipMaker::Release()
{
	pDCSource = NULL;
	srcBitmap.Free();
	cnvBitmap.Free();

	return CRes::CreateOk();
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes LoadSrcBitmap(const char* filename)
//
//	[ 引数 ]
//		const char* filename	ファイル名
//
//	[ 戻り値 ]
//		成功：true
//		失敗：false
//
//	[ 解説 ]
//		ビットマップファイルを読み込みます。
//--------------------------------------------------------------------
CRes ChipMaker::LoadSrcBitmap(const char* filename)
{
	bool bRes;
	CRes cRes;

	// 画像を一旦消す
	RECT clientRect;
	memset(&clientRect, 0, sizeof(RECT));
	//COLORREF bkColor = this->pDCSource->GetBkColor();
	this->pDCSource->GetWindow()->GetClientRect(&clientRect);
	this->pDCSource->FillSolidRect(&clientRect, 0);

	// 読み込み
	bRes = srcBitmap.Load(filename, this->pDCSource);
	if (!bRes) {
		return CRes::CreateError("ビットマップの読み込みに失敗しました。");
	}

	// データ確認
	if (srcBitmap.GetColorDepth() > 8) {
		srcBitmap.Free();
		return CRes::CreateError("256色以下のビットマップを指定してください。");
	}

	// 変換後ビットマップを初期化する
	cRes = InitializeConverted();
	if (!cRes.GetResult()) {
		return cRes;
	}

	// 読んだら描画
	this->DoDraw();

	// 正常終了
	return CRes::CreateOk();
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes LoadPresetBitmap(const char* filename)
//
//	[ 引数 ]
//		const char* filename	ファイル名
//
//	[ 戻り値 ]
//		成功：true
//		失敗：false
//
//	[ 解説 ]
//		Presetパターンのビットマップファイルを読み込みます。
//--------------------------------------------------------------------
CRes ChipMaker::LoadPresetBitmap(const char* filename)
{
	bool bRes;
	CRes cRes;

	// 画像を一旦消す
	RECT clientRect;
	memset(&clientRect, 0, sizeof(RECT));
	//COLORREF bkColor = this->pDCSource->GetBkColor();
	this->pDCConverted->GetWindow()->GetClientRect(&clientRect);
	this->pDCConverted->FillSolidRect(&clientRect, 0);

	// 読み込み
	bRes = cnvBitmap.Load(filename, this->pDCConverted);
	if (!bRes) {
		return CRes::CreateError("ビットマップの読み込みに失敗しました。");
	}

	// データ確認
	if (cnvBitmap.GetColorDepth() > 8) {
		cnvBitmap.Free();
		return CRes::CreateError("256色以下のビットマップを指定してください。");
	}

	if ((cnvBitmap.GetWidth() > 256) || (cnvBitmap.GetHeight() > 256)) {
		cnvBitmap.Free();
		return CRes::CreateError("256x256以下のサイズのビットマップを指定してください。");
	}

	// 読んだら描画
	this->DoDraw();

	// 正常終了
	return CRes::CreateOk();
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes ReadStepCSV(const char* filename, CLogFile* pLogFile)
//
//	[ 引数 ]
//		
//
//	[ 戻り値 ]
//		
//
//	[ 解説 ]
//		
//--------------------------------------------------------------------
CRes ChipMaker::ReadStepCSV(const char* filename, CLogFile* pLogFile)
{
	// 配列を初期化する
	stepCodesMap.RemoveAll();
	for (int i = 0; i < 256; i++) {
		stepCodesArrays[i].RemoveAll();
	}

	// ファイルを開く
	if (strlen(filename) == 0) {
		return CRes::CreateOk();
	}
	FILE* fn = fopen(filename, "rt");
	if (fn == NULL) {
		return CRes::CreateError("足場コード指定のCSVファイルを開けませんでした。");
	}

	// ログ
	pLogFile->Log("足場コード：");

	// 読み込んでパースする
	char* pRes;
	char buffer[256];
	int count = 0;
	while ((pRes = fgets(buffer, 255, fn)) != NULL) {
		// 先頭が # はコメント
		if (*buffer == '#') {
			continue;
		}

		// 1行取り込む
		CString line(buffer);
		int curPos = 0;
		CString elem = line.Tokenize(",", curPos);
		// 1行内のカンマ区切りの値を取り込む
		while (elem != "") {
			// トリムする
			elem.Trim();
			elem.Replace("0x", "");

			// 値を取り込む
			int pal, code;
			int val;
			int type;
			int resCount;
			resCount = sscanf((LPCTSTR)elem, "%x:%x:%d", &pal, &code, &type);
			if (resCount <= 0) {
				CString message;
				message.Format("コード値を取り込めませんでした。[%s]\n", (LPCTSTR)elem);
				fclose(fn);
				return CRes::CreateError(message);
			}

			// 配列に追加する
			val = ((pal & 0xF) << 8) + (code & 0xFF);
			stepCodesMap.SetAt(val, type);	// マップに追加
			stepCodesArrays[type].Add(val);	// リストに追加
			if (count > 0) {
				pLogFile->Log(", ");
			}
			pLogFile->Log("0x%03X:%d", val, type);

			// 次の値を得る
			elem = line.Tokenize(",", curPos);
			count++;
		}
	}

	// ファイルを閉じる
	fclose(fn);

	// 終了
	pLogFile->Log("\n");
	for (int i = 0; i < 256; i++) {
		if (stepCodesArrays[i].GetSize() == 0) {
			continue;
		}
		pLogFile->Log("[%d]", i);
		for (int c = 0; c < stepCodesArrays[i].GetSize(); c++) {
			if (c > 0) {
				pLogFile->Log(", ");
			}
			pLogFile->Log("0x%02X", stepCodesArrays[i].GetAt(c));
		}
		pLogFile->Log("\n");
	}
	return CRes::CreateOk();
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes InitializeConverted()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		CResオブジェクト
//
//	[ 解説 ]
//		変換後ビットマップファイルを初期化します
//--------------------------------------------------------------------
CRes ChipMaker::InitializeConverted()
{
	// 変換後ビットマップを初期化する
	cnvBitmap.Initialize(256, 256, 8, pDCConverted);
	RGBQUAD q;
	memset(&q, 0, sizeof(RGBQUAD));
	for (int i = 0; i < 256; i++) {
		cnvBitmap.SetPalet(i, q);
	}
	for (int y = 0; y < 256; y++) {
		for (int x = 0; x < 256; x++) {
			cnvBitmap.SetPixelIndex(x, y, 0);
		}
	}
	convertedChipCount = 0;

	// パレットのビットマップを初期化する
	palBitmap.Free();
	palBitmap.Initialize(this->palPictureRect.right - this->palPictureRect.left, palPictureRect.bottom - palPictureRect.top, 24, pDCPalet);

	// 正常終了
	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes Load(const char* filename)
//
//	[ 引数 ]
//		const char* filename	ファイル名
//
//	[ 戻り値 ]
//		成功：true
//		失敗：false
//
//	[ 解説 ]
//		ビットマップファイルを読み込みます。
//--------------------------------------------------------------------
CRes ChipMaker::DoDraw()
{
	// ソース画像を描画する
	if (this->srcBitmap.isReady()) {
		// 描画元の矩形を得る
		CRect source(0, 0, srcBitmap.GetWidth(), srcBitmap.GetHeight());

		// 描画先の矩形を導出
		double ratio = 1.0;
		if (srcBitmap.GetWidth() > srcBitmap.GetHeight()) {
			ratio = (double)srcPictureRect.Height() / (double)srcBitmap.GetWidth();
		}
		else {
			ratio = (double)srcPictureRect.Height() / (double)srcBitmap.GetHeight();
		}
		CRect dest(0, 0, (int)(srcBitmap.GetWidth() * ratio), (int)(srcBitmap.GetHeight()*ratio));
		//CRect dest(0, 0,100, 100);

		this->srcBitmap.StretchDraw(source, dest, pDCSource);
	}

	// 変換後画像を描画する
	if (this->cnvBitmap.isReady()) {
		this->cnvBitmap.NormalDraw(CPoint(0, 0), pDCConverted);
	}

	// パレットを描画する
	if (this->cnvBitmap.isReady()) {
		this->palBitmap.PrepareBitOperation();

		int cols = (int)( pow(2.0, (double)srcBitmap.GetColorDepth()) );
		for (int y = 0; y < cols; y++) {
			for (int x = 0; x < 16; x++) {
				RGBQUAD quad = cnvBitmap.GetPalet(y * 16 + x);

				for (int fx = x * 8; fx < x * 8 + 8; fx++) {
					for (int fy = y * 8; fy < y * 8 + 8; fy++) {
						palBitmap.SetPixelColor(fx, fy, quad);
					}
				}
			}
		}

		this->palBitmap.EndBitOperation(pDCPalet);
	}
	if (this->palBitmap.isReady()) {
		this->palBitmap.NormalDraw(CPoint(0, 0), pDCPalet);
	}

	// 正常終了
	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes Convert(int offset, bool presetExists, CMap<int, int, int, int>* pPalErrorMap, CLogFile* pLogFile)
//
//	[ 引数 ]
//		int offset	パターン定義のオフセット値
//		bool presetExists	プリセットパターンが指定されたときにtrue
//		CMap<int, int, int, int>* pPalErrorMap	パレットブロックエラーのマップ
//		CLogFile* pLogFile
//
//	[ 戻り値 ]
//		CResオブジェクト
//
//	[ 解説 ]
//		変換処理を実行します
//--------------------------------------------------------------------
CRes ChipMaker::Convert(int offset, bool presetExists, CMap<int, int, int, int>* pPalErrorMap, BOOL ckeckPaletBlock, CLogFile* pLogFile)
{
	CRes cRes;

	// 変換後ビットマップを初期化する
	if (presetExists == false) {
		cRes = InitializeConverted();
		if (!cRes.GetResult()) {
			return cRes;
		}
	}

	// DIB編集開始
	cnvBitmap.PrepareBitOperation();

	// パレットを転送する
	for (int i = 0; i < 256; i++) {
		RGBQUAD col = srcBitmap.GetPalet(i);
		cnvBitmap.SetPalet(i, col);
	}

	// １個目は必ず0埋めのパターンとする
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			cnvBitmap.SetPixelIndex(x, y, 0);
		}
	}
	convertedChipCount = 1;
	if (offset >= 1) {
		convertedChipCount = offset;
	}

	// 変換していく
	BG_DEF_UNIT bg_def;
	int srcChipWidth = srcBitmap.GetWidth() / 8;
	int srcChipHeight = srcBitmap.GetHeight() / 8;
	if (pLogFile != NULL) {
		pLogFile->Log("画像サイズ　　：(%d, %d)\n", srcBitmap.GetWidth(), srcBitmap.GetHeight());
		pLogFile->Log("BGマップサイズ：(%d, %d)\n", srcChipWidth, srcChipHeight);
	}

	bg_map = (BG_DEF_UNIT*)malloc(srcChipWidth * srcChipHeight * sizeof(BG_DEF_UNIT));
	int bg_map_index = 0;
	CString error = "";
	for (int y = 0; y < srcChipHeight; y+=2) {
		for (int x = 0; x < srcChipWidth; x+=2) {
			// n=0
			bg_def = ConvertChip(x, y, pPalErrorMap, ckeckPaletBlock, pLogFile);
			if (bg_def.code.bit.dummy != 0) {
				cnvBitmap.EndBitOperation(this->pDCConverted);
				error = "BG定義のパターンが1024を超えました。";
				break;
			}
			bg_map[(y * srcChipWidth) + x] = bg_def;

			// n=1
			if ((y + 1) < srcChipHeight) {
				bg_def = ConvertChip(x, y + 1, pPalErrorMap, ckeckPaletBlock, pLogFile);
				if (bg_def.code.bit.dummy != 0) {
					cnvBitmap.EndBitOperation(this->pDCConverted);
					error = "BG定義のパターンが1024を超えました。";
					break;
				}
				bg_map[((y+1) * srcChipWidth) + x] = bg_def;
			}

			// n=2
			if ((x + 1) < srcChipWidth) {
				bg_def = ConvertChip(x + 1, y, pPalErrorMap, ckeckPaletBlock, pLogFile);
				if (bg_def.code.bit.dummy != 0) {
					cnvBitmap.EndBitOperation(this->pDCConverted);
					error = "BG定義のパターンが1024を超えました。";
					break;
				}
				bg_map[(y * srcChipWidth) + (x+1)] = bg_def;
			}

			// n=3
			if (((x + 1) < srcChipWidth) && ((y + 1) < srcChipHeight)) {
				bg_def = ConvertChip(x + 1, y + 1, pPalErrorMap, ckeckPaletBlock, pLogFile);
				if (bg_def.code.bit.dummy != 0) {
					cnvBitmap.EndBitOperation(this->pDCConverted);
					error = "BG定義のパターンが1024を超えました。";
					break;
				}
				bg_map[((y+1) * srcChipWidth) + (x+1)] = bg_def;
			}
		}
		if (error.GetLength() > 0) {
			break;
		}
	}
	if (error.GetLength() > 0) {
		return CRes::CreateError(error);
	}
	
	// DIB編集終了
	cnvBitmap.EndBitOperation(this->pDCConverted);

	// 変換結果ログ
	if (pLogFile != NULL) {
		pLogFile->Log("定義パターン数：%d\n", this->convertedChipCount);
		if (this->convertedChipCount >= 256) {
			pLogFile->Log("※最大のBG定義数 256 を超えています。\n");
		}
	}

	// 終了
	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes ConvertChip(int mx, int my, CArray<int>* pPalErrorList, CLogFile* pLog)
//
//	[ 引数 ]
//		int mx	元画像を8x8ドットのメッシュとしたときの、メッシュのX座標
//		int my	元画像を8x8ドットのメッシュとしたときの、メッシュのY座標
//		CMap<int, int, int, int>* pPalErrorMap	パレットブロックエラーのコードのマップ
//		BOOL checkPaletBlock	パレットブロックの一致も条件とする
//		CLogFile* pLog	ログオブジェクトへのポインタ
//
//	[ 戻り値 ]
//		CResオブジェクト
//
//	[ 解説 ]
//		指定されたメッシュ位置のパターンについて、変換処理を実行します
//--------------------------------------------------------------------
BG_DEF_UNIT ChipMaker::ConvertChip(int mx, int my, CMap<int, int, int, int>* pPalErrorMap, BOOL checkPaletBlock, CLogFile* pLog)
{
	// 変換済パターンそれぞれと比較する
	BG_DEF_UNIT bg_def;
	memset(&bg_def, 0, sizeof(BG_DEF_UNIT));
	bg_def.code.bit.dummy = 1;
	for (int i = 0; i < this->convertedChipCount; i++) {
		bg_def = CompareChip(mx * 8, my * 8, i, checkPaletBlock, pLog);
		if (bg_def.code.bit.dummy == 0) {
			// 一致するものがあった場合は抜ける
			break;
		}
	}

	// 既に存在する場合は新たに追加せずに終わる
	if (bg_def.code.bit.dummy == 0) {
		return bg_def;
	}

//	if (convertedChipCount == 0x43) {
//		int a = 0;
//	}

	// パターンが存在しないのでパターンを転記する
	if (this->convertedChipCount >= 1023) {
		if (pLog != NULL) {
			pLog->Log("BG定義のパターンが1024を超えました。元画像メッシュ位置：(%d, %d)\n", mx, my);
		}
		bg_def.code.bit.dummy = 1;
		return bg_def;
	}

	// 変換後ビットマップ上の左上座標を得る
	int n = this->convertedChipCount & 3;
	int blockIndex = this->convertedChipCount / 4;
	int tx = (blockIndex & 15) * 2;
	int ty = (blockIndex / 16) * 2;
	if (n == 1) { ty += 1; }
	if (n == 2) { tx += 1; }
	if (n == 3) { tx += 1; ty += 1; }
	tx *= 8;
	ty *= 8;

	// パターンを転送する。色コードは16の余りとする。
	int sx = mx * 8;
	int sy = my * 8;
	int rx, ry, rblock, rdecided;
	rx = ry = rblock = rdecided = 0;
	// 参照のパレットブロックを得る
	for (int x = 0; x < 8; x++) {
		for (int y = 0; y < 8; y++) {
			int code = srcBitmap.GetPixelIndex(sx+x, sy+y);
			if ((code&15) != 0) {
				rx = x;
				ry = y;
				rblock = code / 16;
				rdecided = 1;
				break;
			}
		}
		if (rdecided == 1) {
			break;
		}
	}

	// パレットブロックの不整合をチェックする
	bool palError = false;
	int ex, ey, eblock;
	ex = ey = eblock = 0;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			//int colorIndex = srcBitmap.GetPixelIndex(sx + x, sy + y) & 15;
			int colorIndex = srcBitmap.GetPixelIndex(sx + x, sy + y);
			cnvBitmap.SetPixelIndex(tx + x, ty + y, colorIndex);

			// パレットブロックのチェック
			if(!palError) {
				int pixelPaletBlock = srcBitmap.GetPixelIndex(sx + x, sy + y) / 16;
				if ((pixelPaletBlock != rblock) && (colorIndex != 0)) {
					palError = true;
					ex = x;
					ey = y;
					eblock = pixelPaletBlock;
				}
			}
		}
	}
	if (palError) {
		if (pLog != NULL) {
			pLog->Log("パレットブロックに不整合があります。code：%02X, ピクセル位置：(%d, %d), BG位置：(%d, %d), 参照パレットブロック：%d (%d, %d), 不整合パレットブロック：%d (%d, %d)\n"	//
				, convertedChipCount	//
				, ex, ey	//
				, mx, my	//
				, rblock, rx, ry	//
				, eblock, ex, ey	//
			);
			if (pPalErrorMap != NULL) {
				pPalErrorMap->SetAt(this->convertedChipCount, 1);	// パレットブロック不正をマークする
			}
		}
	}

	// 結果を用意する
	bg_def.code.bit.code = this->convertedChipCount;
	bg_def.code.bit.color = rblock;
	bg_def.code.bit.dummy = 0;
	bg_def.code.bit.h_rev = 0;
	bg_def.code.bit.v_rev = 0;
	
	// 正常終了
	this->convertedChipCount += 1;
	return bg_def;
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		
//
//	[ 引数 ]
//		
//
//	[ 戻り値 ]
//		
//
//	[ 解説 ]
//		
//--------------------------------------------------------------------
CRes ChipMaker::CreateBGMapImage(CDC* pDC, const char* filename, CMap<int, int, int, int>* pPalErrorMap, CLogFile* pLogFile)
{
	// もと画像のサイズを得る
	int width = srcBitmap.GetWidth();
	int height = srcBitmap.GetHeight();
	int meshSizeY = height / 8;
	int meshSizeX = width / 8;

	// 出力用BMPを用意する
	Cfbmp bmp;
	bmp.Initialize(width * 2, height * 2, 24, pDC);

	// ビットマップの操作を開始する
	bmp.PrepareBitOperation();

	// ビットマップの画像を薄くしながら複製する（2x2拡大）
	for (int y = 0; y < srcBitmap.GetHeight(); y++) {
		for (int x = 0; x < srcBitmap.GetWidth(); x++) {
			RGBQUAD quad = srcBitmap.GetPixelColor(x, y);
			/*
			int r = quad.rgbRed;
			int g = quad.rgbGreen;
			int b = quad.rgbBlue;
			r = ((256 * 30000) + (r * 70000)) / 100000;
			g = ((256 * 30000) + (g * 70000)) / 100000;
			b = ((256 * 30000) + (b * 70000)) / 100000;
			quad.rgbRed = r;
			quad.rgbGreen = g;
			quad.rgbBlue = b;
			*/
			//
			bmp.SetPixelColor((x * 2) + 0, (y * 2) + 0, quad);
			bmp.SetPixelColor((x * 2) + 1, (y * 2) + 0, quad);
			bmp.SetPixelColor((x * 2) + 0, (y * 2) + 1, quad);
			bmp.SetPixelColor((x * 2) + 1, (y * 2) + 1, quad);
		}
	}

	// 線を描く
	RGBQUAD quad0;
	memset(&quad0, 0, sizeof(RGBQUAD));
	for (int y = 0; y < height * 2; y += 16) {
		for (int x = 0; x < width * 2; x++) {
			bmp.SetPixelColor(x, y, quad0);
		}
	}
	for (int x = 0; x < width * 2; x += 16) {
		for (int y = 0; y < height * 2; y++) {
			bmp.SetPixelColor(x, y, quad0);
		}
	}

	// パレットブロックエラーの位置を示す
	for (int my = 0; my < meshSizeY; my++) {
		for (int mx = 0; mx < meshSizeX; mx++) {
			int index = (meshSizeX * my) + mx;
			int code = bg_map[index].code.bit.code;
			if (pPalErrorMap == NULL) { continue; }

			int errorType = 0;
			BOOL isError;
			isError = pPalErrorMap->Lookup(code, errorType);
			if (!isError) { continue; }

			// 塗る
			for (int y = 0; y <= 16; y+=2) {
				for (int x = 0; x <= 16; x+=2) {
					int px = (mx * 8 * 2) + x;
					int py = (my * 8 * 2) + y;

					RGBQUAD quad;
					quad = bmp.GetPixelColor(px, py);
					quad.rgbRed = 0xFF;
					quad.rgbGreen = 0x00;
					quad.rgbBlue = 0x00;
					bmp.SetPixelColor(px, py, quad);
				}
			}
		}
	}

	// 文字を描く
	RGBQUAD colRed, colBlue;
	colRed.rgbRed = 0xFF;
	colRed.rgbGreen = 0x00;
	colRed.rgbBlue = 0x00;
	//
	colBlue.rgbRed = 0x00;
	colBlue.rgbGreen = 0x00;
	colBlue.rgbBlue = 0xFF;
	//
	CMap<int, int, int, int> codeMap;
	codeMap.RemoveAll();
	//
	for (int y = 0; y < meshSizeY / 2; y++) {
		for (int x = 0; x < meshSizeX / 2; x++) {
			int px, py;

			// n = 0
			px = (x << 1);
			py = (y << 1);
			DrawChipCodeNumber(px, py, meshSizeX, meshSizeY, &bmp, colBlue, colRed, &codeMap);

			// n = 1
			px = (x << 1);
			py = (y << 1)+1;
			DrawChipCodeNumber(px, py, meshSizeX, meshSizeY, &bmp, colBlue, colRed, &codeMap);

			// n = 2
			px = (x << 1)+1;
			py = (y << 1);
			DrawChipCodeNumber(px, py, meshSizeX, meshSizeY, &bmp, colBlue, colRed, &codeMap);

			// n = 3
			px = (x << 1)+1;
			py = (y << 1)+1;
			DrawChipCodeNumber(px, py, meshSizeX, meshSizeY, &bmp, colBlue, colRed, &codeMap);
		}
	}

	// ビット操作を終了する
	bmp.EndBitOperation(pDC);

	bmp.Save(filename);
	bmp.Free();

	// ログに結果を出す
	pLogFile->Log("コード出現回数：\n");
	for (int i = 1; i < 255; i++) {
		int count;
		if (!codeMap.Lookup(i, count)) {
			continue;
		}
		pLogFile->Log("[%02X] %d\n", i, count);
	}

	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		
//
//	[ 引数 ]
//		
//
//	[ 戻り値 ]
//		
//
//	[ 解説 ]
//		
//--------------------------------------------------------------------
CRes ChipMaker::DrawChipCodeNumber(int px, int py, int meshSizeX, int meshSizeY, Cfbmp* pBmp, RGBQUAD colNormal, RGBQUAD colFirst, CMap<int, int, int, int>* pMap) {
	// 色定義
	RGBQUAD boxQuad[8];
	boxQuad[0].rgbRed = 0x00; boxQuad[0].rgbGreen = 0x00; boxQuad[0].rgbBlue = 0xFF;
	boxQuad[1].rgbRed = 0x00; boxQuad[1].rgbGreen = 0xFF; boxQuad[1].rgbBlue = 0x00;
	boxQuad[2].rgbRed = 0x00; boxQuad[2].rgbGreen = 0xFF; boxQuad[2].rgbBlue = 0xFF;
	boxQuad[3].rgbRed = 0xFF; boxQuad[3].rgbGreen = 0x00; boxQuad[3].rgbBlue = 0x00;
	boxQuad[4].rgbRed = 0xFF; boxQuad[4].rgbGreen = 0x00; boxQuad[4].rgbBlue = 0xFF;
	boxQuad[5].rgbRed = 0xFF; boxQuad[5].rgbGreen = 0xFF; boxQuad[5].rgbBlue = 0x00;
	boxQuad[6].rgbRed = 0xFF; boxQuad[6].rgbGreen = 0xFF; boxQuad[6].rgbBlue = 0xFF;
	boxQuad[7].rgbRed = 0xFF; boxQuad[7].rgbGreen = 0x80; boxQuad[7].rgbBlue = 0x80;

	//
	int index, code, pal, val;
	if ((px < meshSizeX) && (py < meshSizeY)) {
		// コード番号を取得する
		index = (meshSizeX * py) + px;
		code = bg_map[index].code.bit.code;
		pal = bg_map[index].code.bit.color;
		val = ((pal & 0xF) << 8) + (code & 0xFF);

		// 足場は印をつける
		int r_code;	// 足場コード
		if (this->stepCodesMap.Lookup(val, r_code)) {
			// 足場だった
			for (int i = 0; i < 16; i++) {
				pBmp->SetPixelColor((px * 16) + i, (py * 16), boxQuad[r_code & 7]);
				pBmp->SetPixelColor((px * 16), (py * 16) + i, boxQuad[r_code & 7]);
				pBmp->SetPixelColor((px * 16) + i, (py * 16) + 15, boxQuad[r_code & 7]);
				pBmp->SetPixelColor((px * 16) + 15, (py * 16) + i, boxQuad[r_code & 7]);

				pBmp->SetPixelColor((px * 16) + i, (py * 16) + 1, boxQuad[r_code & 7]);
				pBmp->SetPixelColor((px * 16) + 1, (py * 16) + i, boxQuad[r_code & 7]);
				pBmp->SetPixelColor((px * 16) + i, (py * 16) + 14, boxQuad[r_code & 7]);
				pBmp->SetPixelColor((px * 16) + 14, (py * 16) + i, boxQuad[r_code & 7]);
			}
		}

		// 既存コードか否かにより色を選択する
		RGBQUAD col;
		int code_count;
		if (pMap->Lookup(code, code_count)) {
			// 値は既存だった（通常）
			col = colNormal;
			code_count += 1;
			pMap->SetAt(code, code_count);	// 値をカウントして更新
		}
		else {
			// 値は初めて見つかった
			col = colFirst;
			pMap->SetAt(code, 1); // 最初の値
		}

		// 描画する
		if (code != 0) {
			// パレットブロック
			DrawNumber(pBmp, (px * 16) + 1 + 6, (py * 16) + 0, (pal % 16) & 0xF, col);

			// コード番号
			DrawNumber(pBmp, (px * 16) + 1 + 0, (py * 16) + 8, (code / 16) & 0xF, col);
			DrawNumber(pBmp, (px * 16) + 1 + 6, (py * 16) + 8, (code % 16) & 0xF, col);
		}
	}

	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		
//
//	[ 引数 ]
//		
//
//	[ 戻り値 ]
//		
//
//	[ 解説 ]
//		
//--------------------------------------------------------------------
CRes ChipMaker::DrawNumber(Cfbmp* pBmp, int px, int py, int number, RGBQUAD& quad)
{
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			if (numberPattern[number][y][x] == 0) {
				continue;
			}

			RGBQUAD col;
			memset(&col, 0, sizeof(RGBQUAD));
			switch (numberPattern[number][y][x]) {
			case 1:
				col.rgbRed = 0xFF;
				col.rgbGreen = 0xFF;
				col.rgbBlue = 0xFF;
				break;
			case 2:
				col = quad;
				break;
			default:
				col.rgbRed = 0xFF;
				break;
			}
			pBmp->SetPixelColor(px + x, py + y, col);
		}
	}

	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		
//
//	[ 引数 ]
//		
//
//	[ 戻り値 ]
//		
//
//	[ 解説 ]
//		
//--------------------------------------------------------------------
CRes ChipMaker::CreateSPDefImage(CDC* pDC, const char* filename, CLogFile* pLogFile)
{
	// もと画像のサイズを得る
	int width = cnvBitmap.GetWidth();
	int height = cnvBitmap.GetHeight();

	// 出力用BMPを用意する
	Cfbmp bmp;
	bmp.Initialize(width * 2, height * 2, 24, pDC);

	// ビットマップの操作を開始する
	bmp.PrepareBitOperation();

	// ビットマップの画像を薄くしながら複製する（2x2拡大）
	for (int y = 0; y < cnvBitmap.GetHeight(); y++) {
		for (int x = 0; x < cnvBitmap.GetWidth(); x++) {
			RGBQUAD quad = cnvBitmap.GetPixelColor(x, y);
			/*
			int r = quad.rgbRed;
			int g = quad.rgbGreen;
			int b = quad.rgbBlue;
			r = ((256 * 30000) + (r * 70000)) / 100000;
			g = ((256 * 30000) + (g * 70000)) / 100000;
			b = ((256 * 30000) + (b * 70000)) / 100000;
			quad.rgbRed = r;
			quad.rgbGreen = g;
			quad.rgbBlue = b;
			*/
			//
			bmp.SetPixelColor((x * 2) + 0, (y * 2) + 0, quad);
			bmp.SetPixelColor((x * 2) + 1, (y * 2) + 0, quad);
			bmp.SetPixelColor((x * 2) + 0, (y * 2) + 1, quad);
			bmp.SetPixelColor((x * 2) + 1, (y * 2) + 1, quad);
		}
	}

	// 線を描く
	RGBQUAD quad0;
	memset(&quad0, 0, sizeof(RGBQUAD));
	for (int y = 0; y < height * 2; y += 16) {
		for (int x = 0; x < width * 2; x++) {
			bmp.SetPixelColor(x, y, quad0);
		}
	}
	for (int x = 0; x < width * 2; x += 16) {
		for (int y = 0; y < height * 2; y++) {
			bmp.SetPixelColor(x, y, quad0);
		}
	}

	// 文字を描く
	RGBQUAD colBlue, colRed;
	colBlue.rgbRed = 0x00;
	colBlue.rgbGreen = 0x00;
	colBlue.rgbBlue = 0xFF;
	//
	colRed.rgbRed = 0xFF;
	colRed.rgbGreen = 0x00;
	colRed.rgbBlue = 0x00;
	//
	int meshSizeY = height / 8;
	int meshSizeX = width / 8;
	//
	int code = 0;
	for (int y = 0; y < meshSizeY / 2; y++) {
		for (int x = 0; x < meshSizeX / 2; x++) {
			int px, py;
			RGBQUAD col;
			col = colBlue;
			if (y >= 4) {
				col = colRed;
			}

			// n = 0
			px = (x << 1);
			py = (y << 1);
			DrawDefCodeNumber(code++, px, py, meshSizeX, meshSizeY, &bmp, col);

			// n = 1
			px = (x << 1);
			py = (y << 1) + 1;
			DrawDefCodeNumber(code++, px, py, meshSizeX, meshSizeY, &bmp, col);

			// n = 2
			px = (x << 1) + 1;
			py = (y << 1);
			DrawDefCodeNumber(code++, px, py, meshSizeX, meshSizeY, &bmp, col);

			// n = 3
			px = (x << 1) + 1;
			py = (y << 1) + 1;
			DrawDefCodeNumber(code++, px, py, meshSizeX, meshSizeY, &bmp, col);
		}
	}

	// ビット操作を終了する
	bmp.EndBitOperation(pDC);

	bmp.Save(filename);
	bmp.Free();

	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		
//
//	[ 引数 ]
//		
//
//	[ 戻り値 ]
//		
//
//	[ 解説 ]
//		
//--------------------------------------------------------------------
CRes ChipMaker::DrawDefCodeNumber(int code, int px, int py, int meshSizeX, int meshSizeY, Cfbmp* pBmp, RGBQUAD col) {
	int index;
	index = (meshSizeX * py) + px;
	if (code != 0) {
		DrawNumber(pBmp, (px * 16) + 1 + 0, (py * 16) + 3, (code / 16) & 0xF, col);
		DrawNumber(pBmp, (px * 16) + 1 + 6, (py * 16) + 3, (code % 16) & 0xF, col);
	}

	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		BG_DEF_UNIT CompareChip(int sx, int sy, int targetBGCode, CLogFile* pLog)
//
//	[ 引数 ]
//		int sx	比較元画像の左上ピクセル位置X
//		int sy	比較元画像の左上ピクセル位置Y
//		int targetBGCode	比較先画像上でのBGコード番号
//		BOOL comparePaletBlock	パレットブロックの一致も条件に含める
//		CLogFile* pLog	ログオブジェクトへのポインタ
//
//	[ 戻り値 ]
//		BG_DEF_UNIT BGパターン定義の構造体
//		一致する番号が無い場合はdummyに1が入る
//
//	[ 解説 ]
//		比較元画像のsx, sy位置のブロックが、targetBGCodeで指定される
//		BGコードのパターンと一致するか否かをチェックします。
//		一致するパターンが見つかった場合は、BG_DEF_UNITに一致する
//		BGの情報を設定して返します。
//		一致するものがなかった場合はdummyに1を格納して返します。
//--------------------------------------------------------------------
BG_DEF_UNIT ChipMaker::CompareChip(int sx, int sy, int targetBGCode, BOOL comparePaletBlock, CLogFile* pLog)
{
	// 結果格納先を用意する
	BG_DEF_UNIT result;
	memset(&result, 0, sizeof(BG_DEF_UNIT));

	// <<<<< 変換先画像上の比較先ブロックの左上座標を導出 >>>>>
	int n = targetBGCode & 3;	// PCGコードオフセット
	int blockIndex = targetBGCode / 4;	// 16x16のSPコードに相当するインデックス番号
	int tx = (blockIndex & 15) * 2;	// 比較ターゲットのx座標
	int ty = (blockIndex / 16) * 2;	// 比較ターゲットのy座標
	if (n == 1) { ty += 1; }
	if (n == 2) { tx += 1; }
	if (n == 3) { tx += 1; ty += 1; }
	tx *= 8;
	ty *= 8;
	//TRACE("tx = %d, ty = %d, targetBGCode = %d\n", tx, ty, targetBGCode);

	// <<<<< パレットブロックを取得しておく >>>>>
	int ltColorIndex = srcBitmap.GetPixelIndex(sx, sy);
	int palBlock = ltColorIndex / 16;
	int dec = 0;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			int code = srcBitmap.GetPixelIndex(sx + x, sy + y);
			if ((code & 15) != 0) {
				// 0以外のピクセルの色で、始めて登場したブロックの番号を採用する
				palBlock = srcBitmap.GetPixelIndex(sx + x, sy + y) / 16;
				dec = 1;
				break;
			}
		}
		if (dec == 1) { break; }
	}

	// <<<<< 通常パターン >>>>>
	bool same = true;
	same = true;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			int targetCode = cnvBitmap.GetPixelIndex(tx + x, ty + y) & 15;
			int srcCode = srcBitmap.GetPixelIndex(sx + x, sy + y) & 15;
			int targetPalet = cnvBitmap.GetPixelIndex(tx + x, ty + y) / 16;
			int srcPalet = srcBitmap.GetPixelIndex(sx + x, sy + y) / 16;
			if ((targetCode != srcCode) || (comparePaletBlock && (targetPalet!=srcPalet))) {
				// 色コードが違う
				same = false;
				break;
			}
		}
		if (!same) {
			break;
		}
	}
	// 比較結果を確認
	if (same) {
		// 一致した
		result.code.bit.code = targetBGCode;
		result.code.bit.color = palBlock;
		result.code.bit.h_rev = 0;
		result.code.bit.v_rev = 0;
		return result;
	}

	// <<<<< 左右反転 >>>>>
	same = true;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			int targetCode = cnvBitmap.GetPixelIndex(tx + (7 - x), ty + y) & 15;
			int srcCode = srcBitmap.GetPixelIndex(sx + x, sy + y) & 15;
			int targetPalet = cnvBitmap.GetPixelIndex(tx + (7 - x), ty + y) / 16;
			int srcPalet = srcBitmap.GetPixelIndex(sx + x, sy + y) / 16;
			if ((targetCode != srcCode) || (comparePaletBlock && (targetPalet != srcPalet))) {
				// 色コードが違う
				same = false;
				break;
			}
		}
		if (!same) {
			break;
		}
	}
	// 比較結果を確認
	if (same) {
		// 一致した
		result.code.bit.code = targetBGCode;
		result.code.bit.color = palBlock;
		result.code.bit.h_rev = 1;
		result.code.bit.v_rev = 0;
		return result;
	}

	// <<<<< 上下反転 >>>>>
	same = true;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			int targetCode = cnvBitmap.GetPixelIndex(tx + x, ty + (7 - y)) & 15;
			int srcCode = srcBitmap.GetPixelIndex(sx + x, sy + y) & 15;
			int targetPalet = cnvBitmap.GetPixelIndex(tx + x, ty + (7 - y)) / 16;
			int srcPalet = srcBitmap.GetPixelIndex(sx + x, sy + y) / 16;
			if ((targetCode != srcCode) || (comparePaletBlock && (targetPalet != srcPalet))) {
				// 色コードが違う
				same = false;
				break;
			}
		}
		if (!same) {
			break;
		}
	}
	// 比較結果を確認
	if (same) {
		// 一致した
		result.code.bit.code = targetBGCode;
		result.code.bit.color = palBlock;
		result.code.bit.h_rev = 0;
		result.code.bit.v_rev = 1;
		return result;
	}

	// <<<<< 上下左右反転 >>>>>
	same = true;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 8; x++) {
			int targetCode = cnvBitmap.GetPixelIndex(tx + (7 - x), ty + (7 - y)) & 15;
			int srcCode = srcBitmap.GetPixelIndex(sx + x, sy + y) & 15;
			int targetPalet = cnvBitmap.GetPixelIndex(tx + (7 - x), ty + (7 - y)) / 16;
			int srcPalet = srcBitmap.GetPixelIndex(sx + x, sy + y) / 16;
			if ((targetCode != srcCode) || (comparePaletBlock && (targetPalet != srcPalet))) {
				// 色コードが違う
				same = false;
				break;
			}
		}
		if (!same) {
			break;
		}
	}
	// 比較結果を確認
	if (same) {
		// 一致した
		result.code.bit.code = targetBGCode;
		result.code.bit.color = palBlock;
		result.code.bit.h_rev = 1;
		result.code.bit.v_rev = 1;
		return result;
	}

	// 一致しなかった
	result.code.bit.dummy = 1;
	return result;
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CRes SaveFiles(CString bmpFilePath, CString mdtFilePath)
//
//	[ 引数 ]
//		CString bmpFilePath		変換後ビットマップ画像の保存先ファイルパス
//		CString mdtFilePath		BGMAPのマップデータの保存先ファイルパス
//		CString pworldFilePath	パラレルワールドマップのデータ保存先ファイルパス
//		CString csvFilePath		パラレルワールドマップのCSVデータ保存先ファイルパス
//
//	[ 戻り値 ]
//		CResオブジェクト
//
//	[ 解説 ]
//		変換後のデータをファイルに保存します。
//--------------------------------------------------------------------
CRes ChipMaker::SaveFiles(CString bmpFilePath, CString mdtFilePath, CString pworldFilePath, CString csvFilePath, CLogFile* pLog)
{
	BOOL bRes;

	// サイズを導出する
	int srcChipWidth = srcBitmap.GetWidth() / 8;
	int srcChipHeight = srcBitmap.GetHeight() / 8;

	// <<<<< ビットマップを保存する >>>>>
	bRes = cnvBitmap.Save(bmpFilePath);
	if (!bRes) {
		return CRes::CreateError("変換後ビットマップファイルの保存に失敗しました。");
	}

	// _aを付ける
	CString mainFilePath = bmpFilePath.Left(bmpFilePath.GetLength() - 4);
	CString stencilPath = mainFilePath + "_a.bmp";
	bRes = cnvBitmap.SaveStencil(stencilPath);
	if (!bRes) {
		return CRes::CreateError("変換後ビットマップファイルの保存に失敗しました。");
	}

	// <<<<< MDT, パラレルワールドマップを保存する >>>>>
	// ファイルを開く
	FILE* fn = fopen((LPCTSTR)mdtFilePath, "wb");
	if (fn == NULL) {
		return CRes::CreateError("MDTファイルを開けませんでした。");
	}
	FILE* fnP = fopen((LPCTSTR)pworldFilePath, "wb");
	if (fnP == NULL) {
		fclose(fn);
		return CRes::CreateError("datファイルを開けませんでした。");
	}
	FILE* fnC = fopen((LPCTSTR)csvFilePath, "wt");
	if (fnC == NULL) {
		fclose(fn);
		fclose(fnP);
		return CRes::CreateError("csvファイルを開けませんでした。");
	}

	// データを変換しながら書き込む
	int bgDefIndex = 0;
	for (int y = 0; y < srcChipHeight; y++) {
		for (int x = 0; x < srcChipWidth; x++) {
			// データを取る
			BG_DEF_UNIT bgDef = this->bg_map[bgDefIndex];
			int bgCode = (bgDef.code.bit.color<<8) + (bgDef.code.bit.code);	// パレットブロック*256 + コード
			int stepCode, stepCodeExists;
			stepCodeExists = this->stepCodesMap.Lookup(bgCode, stepCode);
			if (!stepCodeExists) { stepCode = 0; }

			// <<< MDTへ出力 >>>
			// 1バイト目
			BYTE one = 0;
			one |= (bgDef.code.bit.h_rev) << 6;
			one |= (bgDef.code.bit.v_rev) << 7;
			one |= (bgDef.code.bit.color + 1);		// パレットブロックは書き込み時に+1する
			fwrite(&one, sizeof(BYTE), 1, fn);
			if ((bgDef.code.bit.h_rev != 0) || (bgDef.code.bit.v_rev != 0)) {
				TRACE("h:%d, v:%d, one=%d\n", bgDef.code.bit.h_rev, bgDef.code.bit.v_rev, one);
			}

			// 2バイト目
			BYTE two = 0;
			two = bgDef.code.bit.code;
			fwrite(&two, sizeof(BYTE), 1, fn);

			// <<< datへ出力 >>>
			fputc(stepCode, fnP);
			 
			// <<< CSVへ出力 >>>
			CString csvElem;
			if (x > 0) { fputs(", ", fnC); }
			csvElem.Format("%02d", stepCode);
			fputs((LPCTSTR)csvElem, fnC);

			// 次へ
			bgDefIndex++;
		}
		fputs("\n", fnC);
	}
	fclose(fn);
	fclose(fnP);
	fclose(fnC);

	// <<<<< 正常終了 >>>>>
	return CRes::CreateOk();
}

//--------------------------------------------------------------------
//	[ 書式 ]
//		CString GetSrcBitmapInfo()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		ビットマップに関する情報を表現したテキスト
//
//	[ 解説 ]
//		読み込んだビットマップに関する情報を文字列にして返します。
//--------------------------------------------------------------------
CString ChipMaker::GetSrcBitmapInfo()
{
	// 未読み込みならその旨を返す
	if (!srcBitmap.isReady()) {
		return CString("未読込");
	}

	// 読み込み済なら情報を作って返す
	CString result;
	int bmpWidth = srcBitmap.GetWidth();
	int bmpHeight = srcBitmap.GetHeight();
	int colors = srcBitmap.GetColorNum();
	int bgWidth = bmpWidth / 8;
	int bgHeight = bmpHeight / 8;
	result.Format("サイズ：(%d, %d) 色数：%d, BGサイズ：(%d, %d)\n", bmpWidth, bmpHeight, colors, bgWidth, bgHeight);

	// 結果を返す
	return result;
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		bool IsSrcBitmapReady()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		変換元画像がReadyか否か
//
//	[ 解説 ]
//		変換元画像がReadyか否かを返します。
//--------------------------------------------------------------------
bool ChipMaker::IsSrcBitmapReady() {
	return this->srcBitmap.isReady();
}


//--------------------------------------------------------------------
//	[ 書式 ]
//		CString GetCnvBitmapInfo()
//
//	[ 引数 ]
//		なし
//
//	[ 戻り値 ]
//		変換結果のビットマップに関する情報を表現したテキスト
//
//	[ 解説 ]
//		変換結果のビットマップに関する情報を文字列にして返します。
//--------------------------------------------------------------------
CString ChipMaker::GetCnvBitmapInfo()
{
	// 未変換ならその旨を返す
	if (!cnvBitmap.isReady()) {
		return CString("未変換");
	}

	// 読み込み済なら情報を作って返す
	CString result;
	int count = this->convertedChipCount;
	result.Format("BGパターン数：%d", count);
	if (count > 256) {
		result.Append(" ※BG最大定義数を超過");
	}

	return result;
}
