// HexFile.cpp: implementation of the CHexFile class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HexFile.h"

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

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

CHexFile::CHexFile()
{
	m_pDataBuffer = NULL;
	m_dwDataSize = 0;
	m_bDataValid = FALSE;
}

CHexFile::~CHexFile()
{
	Close();
}

BOOL CHexFile::Open(LPCTSTR lpszFileName)
{
	CStdioFile hFile;
	CString str;
	LPBYTE pData = NULL;
	DWORD dwLength;

	Close();
	if (!hFile.Open(lpszFileName, CFile::modeRead))
		return FALSE;
	m_bDataValid = TRUE;
	dwLength = 64*1024;
	pData = new BYTE[dwLength];
	memset(pData, 0, dwLength);
	dwLength = 0;
	while (hFile.ReadString(str))
	{
		WORD offset;
		int len;
		BYTE sum = 0;
		LPBYTE dat = NULL;
		if ((str[0] != ':') || (str.GetLength() < 11))
		{
			m_bDataValid = FALSE;
			break;
		}
		sscanf(str.Mid(1, 2), "%02X", &len);
		len += 5;
		dat = new BYTE[len];
		while (--len >= 0)
		{
			sscanf(str.Mid(len*2+1, 2), "%02X", &offset);
			sum += dat[len] = offset & 0xff;
		}
		if (sum)
		{
			m_bDataValid = FALSE;
			delete []dat;
			break;
		}
		len = dat[0];
		offset = MAKEWORD(dat[2], dat[1]);
		dwLength = max(dwLength, DWORD(offset + len));
		if (dwLength >= (DWORD)64*1024)
		{
			m_bDataValid = FALSE;
			delete []dat;
			break;
		}
		if (dat[3] == 0x01)
		{
			delete []dat;
			break;
		}
		if (dat[3] != 0x00)
		{
			delete []dat;
			continue;
		}
		memcpy(pData + offset, dat + 4, len);
		delete []dat;
	}
	hFile.Close();
	if (m_bDataValid)
	{
		m_dwDataSize = dwLength;
		m_pDataBuffer = new BYTE[m_dwDataSize];
		memcpy(m_pDataBuffer, pData, m_dwDataSize);
	}

	delete []pData;
	return m_bDataValid;
}

void CHexFile::Close()
{
	if (m_pDataBuffer)
	{
		delete []m_pDataBuffer;
		m_pDataBuffer = NULL;
	}
	m_dwDataSize = 0;
	m_bDataValid = FALSE;
}

DWORD CHexFile::GetLength()
{
	return m_dwDataSize;
}

DWORD CHexFile::ReadHuge(LPVOID pBuffer, DWORD nCount)
{
	if (!m_bDataValid) return 0;
	nCount = min(nCount, m_dwDataSize);
	memcpy(pBuffer, m_pDataBuffer, nCount);

	return nCount;
}
