/*****************************************************
font.c : 
  μITRONトレーナcmtoy サンプルプログラム
  Copyright(C) 2019 佐々木芳

タスクの実装

Windowsのシミュレーション環境上で動作するアプリケーションプログラムのコンパイル時には以下のマクロ定義が必要
	_CMTOY
*****************************************************/
#ifdef _CMTOY
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS
#endif

#include "hal.h"
#include "itron.h"
#include "debug.h"
#include "test.h"
#include "font.h"

//フォントを配置するアドレス
BLOCK_TABLE* pFontSection;	//FindFontSectionで設定、見つからない時はNULL
int			BlockCount;//ブロック数

static const char Separators[] = " \t\r";		/*区切りコード*/

/*カスタムコマンド処理関数形式*/
CC_RESULT ExecCustomCommandLine(char* command_line, UINT wp, void* pv)
{
	CC_RESULT result = COM_ERROR;
	char* p;
	if(p = strtok(command_line, Separators)){
		if(stricmp(p, "ff") == 0){
			//ff <addr>
			int addr;
			int c;
			p = strtok(NULL, Separators);
			if(p){
				c = sscanf(p, "%x", &addr);
				if(c == 1){
					result = DisplayFontBlocks(addr);
				}else{
					DebugPrintf("NG : no address : ff <addr> " NEWLINE);
				}
			}else{
				DebugPrintf("NG : no address : ff <addr> " NEWLINE);
			}
			return result;//
		}else if(stricmp(p, "vf") == 0){
			//vf <code>
			int code = 0;
			int c;
			p = strtok(NULL, Separators);
			if(p){
				c = sscanf(p, "%x", &code);
				if(c == 1){
					result = DisplayFontImage(code);
				}else{
					DebugPrintf("NG : no code : vf <code> " NEWLINE);
				}
			}else{
				DebugPrintf("NG : no code : vf <code> " NEWLINE);
			}
			return result;//
		}else{
			//DebugPrintf("NG : font command not found." NEWLINE);
		}
	}

	return COM_NOT_FOUND;//no command
}



/////////////////////////////////////////////////////////////////////////
int GetBlockCount(BLOCK_TABLE* pTable)
{
	int count = PREAD_BYTE(pTable->nBlocks.count);
	return count;
}

WORD ExtractChecksum(BLOCK_TABLE* pBlockBase, int nBlock)
{
	return PREAD_WORD(pBlockBase->blk_loc[nBlock]);
}

BOOL FindFontSection(int addr)
{
	int nBlock;
	WORD sum, checksum;
	BLOCK_TABLE* pBlockBase = (BLOCK_TABLE*)addr;
	nBlock = GetBlockCount(pBlockBase);
	sum = CalcChecksum((BYTE*)pBlockBase->blk_loc, nBlock*2);
	checksum = ExtractChecksum(pBlockBase, nBlock);
	if(sum == checksum){
		pFontSection = pBlockBase;
		BlockCount = nBlock;
		return TRUE;
	}else{
		pFontSection = NULL;
		BlockCount = 0;
		DebugPrintf(" checksum error " NEWLINE);
		return FALSE;
	}
}

WORD CalcChecksum(BYTE* p, int count)
{
	int i;
	WORD sum = 0;
	for(i=0; i<count; ++i){
		sum += READ_BYTE(p++);
	}
	return sum;
}

void* CalcAddress(WORD offset)
{
	return (BYTE*)pFontSection + offset;
}

HANKAKU_BITMAP* FindHankakuFont(int code)
{
	int i;
	if(pFontSection == NULL) return NULL;
	for(i=0; i<BlockCount; ++i){
		WORD offset = PREAD_WORD(pFontSection->blk_loc[i]);
		HANFONT* pBlock = (HANFONT*)CalcAddress(offset);
		short type = PREAD_WORD(pBlock->header.type);
		if(type == BT_HANFONT){
			//半角フォント
			BYTE start = PREAD_BYTE(pBlock->code1);
			BYTE end = PREAD_BYTE(pBlock->code2);
			if((code >= start) && (code <= end)){
				int offset = (code - start);
				return &pBlock->font[offset];
			}
		}
	}
	return NULL;
}

//LSB が左、MSBが右
void DisplayBitImage(BYTE bit_image)
{
	int i;
	for(i=0; i<8; ++i){
		if(bit_image & 0x01){
			DebugPrintf("%s", "1");
		}else{
			DebugPrintf("%s", "0");
		}
		bit_image >>= 1;
	}
	DebugPrintf(NEWLINE);
}


CC_RESULT DisplayFontImage(code)
{
	HANKAKU_BITMAP* pFont;
	if(pFontSection == NULL){
		DebugPrintf("NG :no font defined." NEWLINE);
		return COM_ERROR;//error
	}
	pFont = FindHankakuFont(code);
	if(pFont){
		BYTE* pImage = (BYTE*)pFont;
		int i;
		DebugPrintf("Font(%02x) image @%04x." NEWLINE, code, pImage);
		for(i=0; i<HAN_SIZE; ++i){
			BYTE bit_image = READ_BYTE(pImage);
			DisplayBitImage(bit_image);
			++pImage;
		}
		DebugPutString("OK" NEWLINE);
		return COM_OK;
	}else{
		DebugPrintf("NG : Font(%02x) image not found." NEWLINE, code);
		return COM_ERROR;//error
	}
}


CC_RESULT DisplayFontBlocks(int addr)
{
	int i;
	BOOL result = FindFontSection(addr);
	if(result == FALSE){
		DebugPrintf("NG :no font blocks." NEWLINE);
		return COM_ERROR;//error
	}
	DebugPrintf("Font Blocks." NEWLINE);
	for(i=0; i<BlockCount; ++i){
		WORD offset = PREAD_WORD(pFontSection->blk_loc[i]);
		BLOCK_HEADER* pBH = (BLOCK_HEADER*)CalcAddress(offset);
		short type = PREAD_WORD(pBH->type);
		switch(type){
		case BT_CRTBLOCK:
			{
				CRTBLOCK* pBlock = (CRTBLOCK*)pBH;
				DebugPrintf(" %d %04xH : \"%s\"" NEWLINE, i, pBlock, CHAR_PTR(pBlock->creator));
			}
			break;
		case BT_TIMBLOCK:
			{
				TIMBLOCK* pBlock = (TIMBLOCK*)pBH;
				DebugPrintf(" %d %04xH : \"%s\"" NEWLINE, i, pBlock, CHAR_PTR(pBlock->timestamp));
			}
			break;
		case BT_HANFONT:
			//半角フォント
			{
				HANFONT* pBlock = (HANFONT*)pBH;
				BYTE start = PREAD_BYTE(pBlock->code1);
				BYTE end = PREAD_BYTE(pBlock->code2);
				DebugPrintf(" %d %04xH : hankaku %02xH - %02xH" NEWLINE, i, pBlock, start, end);
			}
			break;
		}
	}
	DebugPutString("OK" NEWLINE);
	return COM_OK;
}

