// MSFManager.cpp: implementation of the CMSFManager class.
//


#include "stdafx.h"
#include "MSFManager.h"
#include "BKErrMsgSys.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction

#pragma warning(disable:4996)

CMSFManager::CMSFManager()
	: m_pMSFFile(nullptr)
	, m_bOpenForLoad(true)
	, m_header({ MSF_STATE_ID, MSF_VERSION_CURRENT, 0 })
{
}

CMSFManager::~CMSFManager()
{
	ReleaseFile();
}


bool CMSFManager::ReleaseFile()
{
	if (m_pMSFFile) //если файл был открыт
	{
		fclose(m_pMSFFile); //закрываем
		m_pMSFFile = nullptr;
		m_blocks.RemoveAll();
		return true;
	}

	return false;
}

bool CMSFManager::Seek(int nOffset, UINT nFrom)
{
	return (fseek(m_pMSFFile, nOffset, nFrom) == 0);
}

//проверка msf файла
bool CMSFManager::CheckFile(const CString &strPath, bool bSilent)
{
	bool bRet = true;
	ReleaseFile();
	m_pMSFFile = _tfopen(strPath, _T("rb"));

	if (m_pMSFFile) //если файл открылся
	{
		int nFilePos = 0;

		//прочитаем заголовок
		if (fread(&m_header, 1, sizeof(m_header), m_pMSFFile) == sizeof(m_header))
		{
			nFilePos += sizeof(m_header);

			if (m_header.type == MSF_STATE_ID) //если ид верный
			{
				//если старый msf файл
				if (m_header.version < MSF_VERSION_MINIMAL)
				{
					MSF_BLOCK_INFO_OLD bi_old;
					MSF_BLOCK_INFO bi;

					//начинаем читать заголовки блоков
					while (fread(&bi_old.header, 1, sizeof(MSF_BLOCK_HEADER_OLD), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER_OLD))
					{
						bi_old.offset = nFilePos;
						//сконвертируем старый заголовок в новый
						bi.offset = bi_old.offset;
						bi.header.type = bi_old.header.type;
						bi.header.id = -1;
						bi.header.length = bi_old.header.length;
						//и сохраним
						m_blocks.Add(bi);

						if (!Seek(bi_old.header.length - sizeof(MSF_BLOCK_HEADER_OLD), SEEK_CUR))
						{
							CBKMessageBox(g_pstrErrors[BK_ERROR_MSFCORRUPTMSF], MB_OK);
							bRet = false;
							break;
						}

						nFilePos += bi_old.header.length;
					}
				}
				else
				{
					MSF_BLOCK_INFO bi;

					//начинаем читать заголовки блоков
					while (fread(&bi.header, 1, sizeof(MSF_BLOCK_HEADER), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER))
					{
						bi.offset = nFilePos;   //заполняем смещение
						m_blocks.Add(bi);       //добавляем блок в список найденных блоков

						//переместимся к следующему блоку
						if (!Seek(bi.header.length - sizeof(MSF_BLOCK_HEADER), SEEK_CUR))
						{
							if (!bSilent)
							{
								CBKMessageBox(g_pstrErrors[BK_ERROR_MSFCORRUPTMSF], MB_OK);
							}

							bRet = false;
							break;
						}

						nFilePos += bi.header.length; //скорректируем смещение
					}
				}
			}
			else
			{
				if (!bSilent)
				{
					CBKMessageBox(g_pstrErrors[BK_ERROR_MSFNOMSFFILE], MB_OK);
				}

				bRet = false;
			}
		}
		else
		{
			if (!bSilent)
			{
				CBKMessageBox(g_pstrErrors[BK_ERROR_MSFREADHEADERRROR], MB_OK);
			}

			bRet = false;
		}

		ReleaseFile(); //закрываем файл и очищаем список блоков
	}
	else
	{
		if (!bSilent)
		{
			CBKMessageBox(g_pstrErrors[BK_ERROR_MSFOPENFILEERROR], MB_OK);
		}

		bRet = false;
	}

	return bRet;
}

bool CMSFManager::OpenFile(const CString &strPath, bool bLoad)
{
	bool bRet = true;
	ReleaseFile();
	CString strFlag = _T("rb");

	if (!bLoad)
	{
		strFlag = _T("w+b");
	}

	m_pMSFFile = _tfopen(strPath, strFlag);

	if (m_pMSFFile) //если файл открылся
	{
		m_bOpenForLoad = bLoad;

		if (m_bOpenForLoad)
		{
			//если открываем для чтения
			//прочитаем заголовок
			if (fread(&m_header, 1, sizeof(m_header), m_pMSFFile) == sizeof(m_header))
			{
				int nFilePos = sizeof(m_header);

				if (m_header.type == MSF_STATE_ID)
				{
					//если старый msf файл
					if (m_header.version < MSF_VERSION_MINIMAL)
					{
						MSF_BLOCK_INFO_OLD bi_old;
						MSF_BLOCK_INFO bi;

						//начинаем читать заголовки блоков
						while (fread(&bi_old.header, 1, sizeof(MSF_BLOCK_HEADER_OLD), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER_OLD))
						{
							bi_old.offset = nFilePos;
							//сконвертируем старый заголовок в новый
							bi.offset = bi_old.offset;
							bi.header.type = bi_old.header.type;
							bi.header.id = -1;
							bi.header.length = bi_old.header.length;
							//и сохраним
							m_blocks.Add(bi);

							if (!Seek(bi_old.header.length - sizeof(MSF_BLOCK_HEADER_OLD), SEEK_CUR))
							{
								CBKMessageBox(g_pstrErrors[BK_ERROR_MSFCORRUPTMSF], MB_OK);
								bRet = false;
								break;
							}

							nFilePos += bi_old.header.length;
						}
					}
					else
					{
						MSF_BLOCK_INFO bi;

						//начинаем читать заголовки блоков
						while (fread(&bi.header, 1, sizeof(MSF_BLOCK_HEADER), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER))
						{
							bi.offset = nFilePos;
							m_blocks.Add(bi);

							if (!Seek(bi.header.length - sizeof(MSF_BLOCK_HEADER), SEEK_CUR))
							{
								CBKMessageBox(g_pstrErrors[BK_ERROR_MSFCORRUPTMSF], MB_OK);
								bRet = false;
								break;
							}

							nFilePos += bi.header.length;
						}
					}
				}
				else
				{
					CBKMessageBox(g_pstrErrors[BK_ERROR_MSFNOMSFFILE], MB_OK);
					bRet = false;
				}
			}
			else
			{
				CBKMessageBox(g_pstrErrors[BK_ERROR_MSFREADHEADERRROR], MB_OK);
				bRet = false;
			}
		}
		else
		{
			//если открываем для записи
			//запишем заголовок
			if (fwrite(&m_header, 1, sizeof(m_header), m_pMSFFile) != sizeof(m_header))
			{
				CBKMessageBox(g_pstrErrors[BK_ERROR_MSFWRITEHEADERRROR], MB_OK);
				bRet = false;
			}
		}
	}
	else
	{
		CBKMessageBox(g_pstrErrors[BK_ERROR_MSFOPENFILEERROR], MB_OK);
		bRet = false;
	}

	if (!bRet)
	{
		ReleaseFile();
	}

	return bRet;
}

//ищем нужный блок в массиве
bool CMSFManager::FindBlock(DWORD blockType, DWORD id, MSF_BLOCK_INFO *pBi)
{
	for (int n = 0; n < m_blocks.GetSize(); ++n)
	{
		if (id == -1)
		{
			if (m_blocks[n].header.type == blockType)
			{
				*pBi = m_blocks[n];
				return true;
			}
		}
		else
		{
			if (m_blocks[n].header.type == blockType && m_blocks[n].header.id == id)
			{
				*pBi = m_blocks[n];
				return true;
			}
		}
	}

	return false;
}


bool CMSFManager::SetBlockHeader(MSF_BLOCK_INFO *pBi)
{
	return (fwrite(&pBi->header, 1, sizeof(MSF_BLOCK_HEADER), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER));
}

bool CMSFManager::GetBlockHeader(MSF_BLOCK_INFO *pBi)
{
	bool bRet = false;

	if (Seek(pBi->offset, SEEK_SET)) //сначала переместимся к началу блока
	{
		if (m_header.version < MSF_VERSION_MINIMAL /*&& pBi->header.type == MSF_BLOCKTYPE_WAVE*/)
		{
			MSF_BLOCK_HEADER_OLD hdr_old;
			MSF_BLOCK_HEADER hdr;

			//затем прочитаем заголовок
			if (fread(&hdr_old, 1, sizeof(MSF_BLOCK_HEADER_OLD), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER_OLD))
			{
				hdr.type = hdr_old.type;
				hdr.id = -1;
				hdr.length = hdr_old.length;

				if (pBi->header == hdr)
				{
					bRet = true;
				}
			}
		}
		else
		{
			MSF_BLOCK_HEADER hdr;

			//затем прочитаем заголовок
			if (fread(&hdr, 1, sizeof(MSF_BLOCK_HEADER), m_pMSFFile) == sizeof(MSF_BLOCK_HEADER))
			{
				if (pBi->header == hdr)
				{
					bRet = true;
				}
			}
		}
	}
	else
	{
		CBKMessageBox(g_pstrErrors[BK_ERROR_MSFSEEKERROR], MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockData(uint8_t *pBuff, DWORD length)
{
	if (length)
	{
		return (fwrite(pBuff, 1, length, m_pMSFFile) == length);
	}

	return true;
}


bool CMSFManager::GetBlockData(uint8_t *pBuff, DWORD length)
{
	if (length)
	{
		return (fread(pBuff, 1, length, m_pMSFFile) == length);
	}

	return true;
}


//проверка размера блока, перед его чтением. На тот случай, если я опять наизменял конфигурацию
//вход: bi - указатель на блок заголовка
//		size - sizeof структуры
//выход: true - всё нормально
//		false - размер не совпадает.
bool CMSFManager::CheckBlockSize(MSF_BLOCK_INFO *pbi, DWORD size)
{
	return (pbi->header.length == sizeof(MSF_BLOCK_HEADER) + size);
}

bool CMSFManager::SetBlockTape(uint8_t *pPackedWave, DWORD nBitsLength, DWORD nPackLength)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_WAVE;
	bi.header.id = -1;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + sizeof(DWORD) + nPackLength;

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(reinterpret_cast<uint8_t *>(&nBitsLength), sizeof(DWORD)))
		{
			if (SetBlockData(reinterpret_cast<uint8_t *>(pPackedWave), nPackLength))
			{
				bRet = true;
			}
			else
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKTAPE]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKTAPE]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKTAPE]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::GetBlockTape(uint8_t *pPackedWave, DWORD *pnBitsLength, DWORD *pnPackLength)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_WAVE, -1, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			DWORD nPackLength = bi.header.length - sizeof(MSF_BLOCK_HEADER) - sizeof(DWORD);

			if (GetBlockData(reinterpret_cast<uint8_t *>(pnBitsLength), sizeof(DWORD)))
			{
				if (!pPackedWave)
				{
					*pnPackLength = nPackLength;
					return true;
				}

				if (GetBlockData(reinterpret_cast<uint8_t *>(pPackedWave), nPackLength))
				{
					bRet = true;
				}
				else
				{
					str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKTAPE]);
					CBKMessageBox(str, MB_OK);
				}
			}
			else
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKTAPE]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKTAPE]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKTAPE]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockPlatformData(MSF_PLATFORM_DATA *pPD)
{
	ASSERT(pPD);    //по алгоритму, pPD никогда не должен быть null
	//pPD->pDevices допускается null, в этом случае оно в файл не сохраняется
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_PLATFORM;
	bi.header.id = -1;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) //размер заголовка
	                   + sizeof(DWORD) * 2 //размер двух первых двордов MSF_PLATFORM_DATA
	                   + sizeof(MSF_DEVICE_ID) * pPD->nDevNum; // размер MSF_DEVICE_ID по количеству устройств

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(reinterpret_cast<uint8_t *>(pPD), sizeof(DWORD) * 2)
		        && SetBlockData(reinterpret_cast<uint8_t *>(pPD->pDevices), sizeof(MSF_DEVICE_ID) * pPD->nDevNum))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKPLATFORMDATA]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKPLATFORMDATA]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::GetBlockPlatformData(MSF_PLATFORM_DATA *pPD)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_PLATFORM, -1, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (GetBlockData(reinterpret_cast<uint8_t *>(pPD), sizeof(DWORD) * 2))
			{
				if (pPD->nDevNum)
				{
					pPD->pDevices = new MSF_DEVICE_ID[pPD->nDevNum];

					if (pPD->pDevices)
					{
						if (GetBlockData(reinterpret_cast<uint8_t *>(pPD->pDevices), sizeof(MSF_DEVICE_ID) * pPD->nDevNum))
						{
							bRet = true;
						}
					}
					else
					{
						CBKMessageBox(g_pstrErrors[BK_ERROR_NOTENMEMR], MB_OK);
					}
				}
				else
				{
					pPD->pDevices = nullptr;
					bRet = true;
				}
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKPLATFORMDATA]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKPLATFORMDATA]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKPLATFORMDATA]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockPreview(HBITMAP hScreenshot)
{
	DIBSECTION ds;
	CString str;
	bool bRet = false;

	if (::GetObject(hScreenshot, sizeof(ds), &ds))
	{
		MSF_BLOCK_INFO bi;
		bi.header.type = MSF_BLOCKTYPE_PREVIEW;
		bi.header.id = -1;
		bi.header.length = sizeof(MSF_BLOCK_HEADER) + sizeof(ds.dsBmih) + ds.dsBmih.biSizeImage;

		if (SetBlockHeader(&bi))
		{
			if (SetBlockData(reinterpret_cast<uint8_t *>(&ds.dsBmih), sizeof(ds.dsBmih)))
			{
				ASSERT(ds.dsBm.bmBits);

				if (SetBlockData(reinterpret_cast<uint8_t *>(ds.dsBm.bmBits), ds.dsBmih.biSizeImage))
				{
					bRet = true;
				}
				else
				{
					str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
					CBKMessageBox(str, MB_OK);
				}
			}
			else
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		CBKMessageBox(g_pstrErrors[BK_ERROR_MSFPREVIEWBLK_OBJ]);
	}

	return bRet;
}


bool CMSFManager::GetBlockPreview(HBITMAP *hScreenshot)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_PREVIEW, -1, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			BITMAPINFOHEADER bmih;

			if (GetBlockData(reinterpret_cast<uint8_t *>(&bmih), sizeof(bmih)))
			{
				uint8_t *pBits = nullptr;
				HBITMAP hBm = nullptr;

				if ((hBm = ::CreateDIBSection(nullptr, (BITMAPINFO *)&bmih, DIB_RGB_COLORS, (void **)&pBits, nullptr, 0)))
				{
					if (GetBlockData(pBits, bmih.biSizeImage))
					{
						bRet = true;
					}
					else
					{
						str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
						CBKMessageBox(str, MB_OK);
					}
				}
				else
				{
					CBKMessageBox(g_pstrErrors[BK_ERROR_MSFPREVIEWBLK_DIB], MB_OK);
				}
			}
			else
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKPREVIEW]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::SetBlockConfig()
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_CONFIG;
	bi.header.id = -1;
	bi.header.length = sizeof(MSF_BLOCK_HEADER);  //+ длина блока. длина переменная
	UINT nSize = _MAX_PATH * 1000;
	auto pBlock = new uint8_t[nSize]; //размер будет достаточен наверняка

	if (pBlock)
	{
		ZeroMemory(pBlock, nSize);
		ULONGLONG len = g_Config.SaveConfig_ToMemory(pBlock, nSize);
		bi.header.length += (DWORD)len;

		if (SetBlockHeader(&bi))
		{
			if (SetBlockData(pBlock, (DWORD)len))
			{
				bRet = true;
			}
			else
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKCONFIG]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKCONFIG]);
			CBKMessageBox(str, MB_OK);
		}

		delete[] pBlock;
	}
	else
	{
		CBKMessageBox(g_pstrErrors[BK_ERROR_NOTENMEMR]);
	}

	return bRet;
}

bool CMSFManager::GetBlockConfig()
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_CONFIG, -1, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			DWORD nBlockLength = bi.header.length - sizeof(MSF_BLOCK_HEADER);
			auto pBlock = new uint8_t[nBlockLength];

			if (pBlock)
			{
				if (GetBlockData(pBlock, nBlockLength))
				{
					g_Config.LoadConfig_FromMemory(pBlock, nBlockLength);
					bRet = true;
				}
				else
				{
					str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKCONFIG]);
					CBKMessageBox(str, MB_OK);
				}

				delete[] pBlock;
			}
			else
			{
				CBKMessageBox(g_pstrErrors[BK_ERROR_NOTENMEMR]);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKCONFIG]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKCONFIG]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::SetBlockFrameData(MSF_FRAMEDATA *FDBlock)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_FRAMEDATA;
	bi.header.id = -1;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + sizeof(MSF_FRAMEDATA);

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(reinterpret_cast<uint8_t *>(FDBlock), sizeof(MSF_FRAMEDATA)))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKFRAMEDATA]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKFRAMEDATA]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::GetBlockFrameData(MSF_FRAMEDATA *FDBlock)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (m_header.version < MSF_VERSION_MINIMAL)
	{
		return bRet;
	}

	if (FindBlock(MSF_BLOCKTYPE_FRAMEDATA, -1, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (CheckBlockSize(&bi, sizeof(MSF_FRAMEDATA)))
			{
				bRet = GetBlockData(reinterpret_cast<uint8_t *>(FDBlock), sizeof(MSF_FRAMEDATA));
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKFRAMEDATA]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKFRAMEDATA]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKFRAMEDATA]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockCPURegisters(MSF_CPU_REGISTERS *pCPURegisters)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_CPU_REGISTERS;
	bi.header.id = -1;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + sizeof(MSF_CPU_REGISTERS);

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(reinterpret_cast<uint8_t *>(pCPURegisters), sizeof(MSF_CPU_REGISTERS)))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKCPUREGS]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKCPUREGS]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::GetBlockCPURegisters(MSF_CPU_REGISTERS *pCPURegisters)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_CPU_REGISTERS, -1, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (CheckBlockSize(&bi, sizeof(MSF_CPU_REGISTERS)))
			{
				bRet = GetBlockData(reinterpret_cast<uint8_t *>(pCPURegisters), sizeof(MSF_CPU_REGISTERS));
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKCPUREGS]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKCPUREGS]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKCPUREGS]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockMemMap(DWORD id, BKMEMBank_t *MBType)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_MEMMAP;
	bi.header.id = id;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + sizeof(BKMEMBank_t) * 8;

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(reinterpret_cast<uint8_t *>(MBType), sizeof(BKMEMBank_t) * 8))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKMEMMAPMGR]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKMEMMAPMGR]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::GetBlockMemMap(DWORD id, BKMEMBank_t *MBType)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_MEMMAP, id, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (CheckBlockSize(&bi, sizeof(BKMEMBank_t) * 8))
			{
				bRet = GetBlockData(reinterpret_cast<uint8_t *>(MBType), sizeof(BKMEMBank_t) * 8);
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKMEMMAPMGR]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKMEMMAPMGR]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		//в старых версиях этого блока не было,
		//поэтому старые версии будут не совместимы с новой. и ничего тут не поделать
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKMEMMAPMGR]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockBaseMemory(DWORD id, uint8_t *pMemory, int nSize)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_BASEMEMORY;
	bi.header.id = id;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + nSize;

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(pMemory, nSize))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKBASEMEM]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKBASEMEM]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::GetBlockBaseMemory(DWORD id, uint8_t *pMemory, int nSize)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_BASEMEMORY, id, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (CheckBlockSize(&bi, nSize))
			{
				bRet = GetBlockData(pMemory, nSize);
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKBASEMEM]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKBASEMEM]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKBASEMEM]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


bool CMSFManager::SetBlockPortRegs(DWORD id, MSF_PORT_REGS *pPortRegs)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_PORT_REGS;
	bi.header.id = id;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + sizeof(MSF_PORT_REGS);

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(reinterpret_cast<uint8_t *>(pPortRegs), sizeof(MSF_PORT_REGS)))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKSYSREGS]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKSYSREGS]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::GetBlockPortRegs(DWORD id, MSF_PORT_REGS *pPortRegs)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (m_header.version < MSF_VERSION_MINIMAL)
	{
		return bRet;
	}

	if (FindBlock(MSF_BLOCKTYPE_PORT_REGS, id, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (CheckBlockSize(&bi, sizeof(MSF_PORT_REGS)))
			{
				bRet = GetBlockData(reinterpret_cast<uint8_t *>(pPortRegs), sizeof(MSF_PORT_REGS));
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKSYSREGS]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKSYSREGS]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKSYSREGS]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::SetBlockCustomData(DWORD id, uint8_t *pData, int nSize)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;
	bi.header.type = MSF_BLOCKTYPE_CUSTOM;
	bi.header.id = id;
	bi.header.length = sizeof(MSF_BLOCK_HEADER) + nSize;

	if (SetBlockHeader(&bi))
	{
		if (SetBlockData(pData, nSize))
		{
			bRet = true;
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_DTABLKWRERR], g_pstrErrors[BK_ERROR_BLKCUSTOM]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_HDRBLKWRERR], g_pstrErrors[BK_ERROR_BLKCUSTOM]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}

bool CMSFManager::GetBlockCustomData(DWORD id, uint8_t *pData, int nSize)
{
	MSF_BLOCK_INFO bi;
	CString str;
	bool bRet = false;

	if (FindBlock(MSF_BLOCKTYPE_CUSTOM, id, &bi))
	{
		if (GetBlockHeader(&bi))
		{
			if (CheckBlockSize(&bi, nSize))
			{
				bRet = GetBlockData(pData, nSize);
			}

			if (!bRet)
			{
				str.Format(g_pstrErrors[BK_ERROR_DTABLKRDERR], g_pstrErrors[BK_ERROR_BLKCUSTOM]);
				CBKMessageBox(str, MB_OK);
			}
		}
		else
		{
			str.Format(g_pstrErrors[BK_ERROR_HDRBLKRDERR], g_pstrErrors[BK_ERROR_BLKCUSTOM]);
			CBKMessageBox(str, MB_OK);
		}
	}
	else
	{
		str.Format(g_pstrErrors[BK_ERROR_BLKNOTFOUND], g_pstrErrors[BK_ERROR_BLKCUSTOM]);
		CBKMessageBox(str, MB_OK);
	}

	return bRet;
}


