📄 ihex.cpp
字号:
/**************************************************************************
Project: WinAVRIDE Class: Read/Write Intel Hex
Copyright (C) 2005 Philipp Schober
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
History
19.Feb 2005 - First Release (V1.0)
****************************************************************************/
#include "ihex.h"
#define MAX_LINELEN 32 // Has to be 2,4,8,16,32,...
//---------------------------------------------------------------------------
int __fastcall TIHex::ReadFile (AnsiString name, unsigned char *buf,
int maxsize)
{
unsigned char line[512];
int offset, linoffs, segoffs, addr, reclen, i, temp, checksum, filesize = 0;
int rectype;
bool finished = false, r;
stream = new TFileStream(name, fmOpenRead);
if (stream == NULL) return 0;
linoffs = segoffs = 0;
while (!finished)
{
if (!ReadLine (line))
{
delete stream;
ErrorMessage ("Error reading File");
return 0;
}
if (line[0] == ':')
{
r = HexToBin (line + 1, &reclen, 2);
if (r) r = HexToBin (line + 3, &offset, 4);
if (r) r = HexToBin (line + 7, &rectype, 2);
if (!r)
{
delete stream;
return 0;
}
checksum = reclen + rectype;
checksum += (unsigned char)(offset & 0xff);
checksum += (unsigned char)((offset >> 8)& 0xff);
switch (rectype)
{
case 0: // Data Record
addr = offset + linoffs + segoffs;
if ((addr + reclen) > filesize) filesize = addr + reclen;
if (filesize > maxsize)
{
ErrorMessage ("File exceeds Maximum Size");
filesize = 0;
finished = true;
break;
}
for (i = 0;i < reclen;i++)
{
if (r) r = HexToBin (line + 9 + (2 * i), &temp, 2);
*(buf + addr + i) = (unsigned char)temp;
checksum += (unsigned char)temp;
}
if (r) r = HexToBin (line + 9 + (2 * i), &temp, 2);
checksum += (unsigned char)temp;
if (!r)
{
finished = true;
filesize = 0;
break;
}
if ((checksum & 0xff)!= 0)
{
ErrorMessage ("Checksum Error type 0");
filesize = 0;
finished = true;
}
break;
case 1: // End of File Record
r = HexToBin (line + 9, &temp, 2);
if (!r)
{
finished = true;
filesize = 0;
break;
}
if (reclen != 0 || offset != 0 || temp != 0xff)
{
ErrorMessage ("Invalid EOF Record");
filesize = 0;
}
finished = true;
break;
case 2: // Extended Segment Address Record
if (reclen != 2)
{
ErrorMessage ("Invalid Record Length for type 2");
filesize = 0;
finished = true;
break;
}
r = HexToBin (line + 9, &segoffs, 4);
if (r) r = HexToBin (line + 13, &temp, 2);
checksum += (unsigned char)(segoffs & 0xff);
checksum += (unsigned char)((segoffs >> 8) & 0xff);
checksum += (unsigned char)temp;
if (!r)
{
finished = true;
filesize = 0;
break;
}
if ((checksum & 0xff)!= 0)
{
ErrorMessage ("Checksum Error type 2");
filesize = 0;
finished = true;
}
segoffs <<= 4;
break;
case 3: // Start Segment Address Record
break;
case 4: // Extended Linear Address Record
if (reclen != 2)
{
ErrorMessage ("Invalid Record Length for type 4");
filesize = 0;
finished = true;
break;
}
r = HexToBin (line + 9, &linoffs, 4);
if (r) r = HexToBin (line + 13, &temp, 2);
checksum += (unsigned char)(linoffs & 0xff);
checksum += (unsigned char)((linoffs >> 8) & 0xff);
checksum += (unsigned char)temp;
if (!r)
{
finished = true;
filesize = 0;
break;
}
if ((checksum & 0xff)!= 0)
{
ErrorMessage ("Checksum Error type 4");
filesize = 0;
finished = true;
}
linoffs <<= 16;
break;
case 5: // Start Linear Address Record
break;
default: ErrorMessage ("Invalid Record type");
filesize = 0;
finished = true;
break;
}
}
else
{
ErrorMessage ("Illegal Line found");
filesize = 0;
finished = true;
}
}
delete stream;
return filesize;
}
//---------------------------------------------------------------------------
bool __fastcall TIHex::ReadLine (unsigned char *line)
{
int i;
long temppos;
// Workaround for the missing ReadLine Method
temppos = stream->Position;
if (stream->Read (line, 512) < 1)
{
ErrorMessage ("File Read Operation Failed");
return false;
}
for (i = 0;i < 512;i++)
{
if (*(line + i) == 10)
{
stream->Seek(temppos + i + 1, soFromBeginning);
*(line + i + 1) = 0;
break;
}
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TIHex::HexToBin (unsigned char *in, int *out, int len)
{
if (!isxdigit (*in) || !isxdigit (*(in + 1)))
{
ErrorMessage ("Illegal Char in File");
return false;
}
*out = 0;
while (len--)
{
*out *= 16;
if (*in <= '9') *out += *in - '0';
else if (*in >= 'A' && *in <= 'F') *out += *in -'A' + 10;
else *out += *in - 'a' + 10;
in++;
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TIHex::WriteFile (AnsiString name, unsigned char *buf,
int size)
{
unsigned char line[512];
int i, len, address = 0, pos, checksum, linoffs = 0, offset;
bool emptyline;
stream = new TFileStream(name, fmCreate);
if (stream == NULL) return false;
while (size)
{
if ((address - linoffs) > 0xffff)
{
linoffs = address & 0xffff0000;
line[0] = ':';
BinToHex (2, line + 1, 2);
BinToHex (0, line + 3, 4);
BinToHex (4, line + 7, 2);
BinToHex (linoffs >> 16, line + 9, 4);
checksum = 6 + ((linoffs >> 16) & 0xff) + ((linoffs >> 24) & 0xff);
checksum = 0x100 - (checksum & 0xff);
BinToHex (checksum & 0xff, line + 13, 2);
line[15] = '\r';
line[16] = '\n';
stream->Write (line, 17);
}
line[0] = ':';
if (size < MAX_LINELEN) len = size;
else len = MAX_LINELEN;
BinToHex (len, line + 1, 2);
checksum = len;
pos = 3;
offset = address - linoffs;
BinToHex (offset, line + pos, 4);
checksum += ((offset >> 8) & 0xff);
checksum += (offset & 0xff);
pos += 4;
BinToHex (0, line + pos, 2);
pos += 2;
emptyline = true;
for (i = 0;i < len;i++)
{
checksum += *(buf + address + i);
if (*(buf + address + i) != 0xff) emptyline = false;
BinToHex ((int)*(buf + address + i), line + pos, 2);
pos += 2;
}
checksum = 0x100 - (checksum & 0xff);
BinToHex (checksum & 0xff, line + pos, 2);
pos += 2;
*(line + pos++) = '\r';
*(line + pos++) = '\n';
if (!emptyline) stream->Write (line, pos);
if (size >= MAX_LINELEN) size -= MAX_LINELEN;
else size = 0;
address += MAX_LINELEN;
}
stream->Write (":00000001FF\r\n", 13); // Write EOF Record
delete stream;
return true;
}
//---------------------------------------------------------------------------
void __fastcall TIHex::BinToHex (int in, unsigned char *out, int len)
{
unsigned char t;
while (len--)
{
t = (unsigned char)(in % 16);
in /= 16;
if (t < 10) t += '0';
else t = (unsigned char)(t - 10 + 'A');
*(out + len) = t;
}
}
//---------------------------------------------------------------------------
void __fastcall TIHex::ErrorMessage (char *mess)
{
Application->MessageBox (mess, "Error", MB_OK | MB_ICONERROR);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -