Hola Alexander,
A ver si puedo ayudarte,
Formato general de un fichero en formato Intel HEX (8 bit)
Consta de sucesivos RECORDs (líneas a partir de ahora) que almacenan datos e información de como y donde van esos datos.
Cada línea comienza con un RECORD MARK que es un campo conteniendo 03AH, el código ASCII de los dospuntos (colon ) (’ : ’) .
Cada línea tirne un campo RECLEN que especifica el número de bytes de información o datosque siguen al campo RECTYPE (tipo de registro, o tipo de información contenida en la línea). Cada byte de datos se representa con dos caracteres ASCII y el valor máximo de RECLEN es de 255 o 'FF'.
Cada línea tiene un campo OFFSET (Load OFFSET) o dirección (ADDRESS) que especifica la dirección de 16 bit donde comienzan los datos que contiene la línea. Esto si la línea contiene datos, en caso de que no los contenga y contenga otros campos informativos entonces tiene que tener el valor '0000' o '30303030' hexadecimal.
Cada línea tiene un campo RECTYPE que indica el tipo de datos que contiene la línea. Este campo es usado para interpretar el resto de la línea. Los tipos de RECTYPE son:
’00’ Linea conteniendo datos <=Es el que usaremos
’01’ EOF fin de datos <=Tambien lo vamos a usar
’02’ Extended Segment Address Record ->De este pasamos
’03’ Start Segment Address Record ->De este tambien
’04’ Extended Linear Address Record -> Y de este
’05’ Start Linear Address Record -> y de estelo mismo
Cada linea tiene un numero variable de datos que pueden contener cero o más bytes codificados en pares de dígitos hexadecimales . La interpretación de estos datos se hace según lo que indique el campo RECTYPE.
Cada línea termina con un campo CHECKSUM que contiene la representación hexadecimal en ASCII del complemento a 2 en 8 bits resultante de convertir cada par de códigos ASCII en su correspondiente número hexadecimal desde el campo RECLEN hasta el último byte de datos de la línea.Asímismo la suma de todos los datos de una línea, desde RECLEN e incluyendo el Checksum es igual a cero.
Ejemplo:
:1005AA00000102030405060708090A0B0C0D0E0F88
^----- calculo del checksum -----^^^
||
Check sum__|RECLEN = 0x10 = 16
ADDRESS = 0x05AA
RECTYPE = 00
DATA = 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
CHKSUM = 0x88 = 256 -sum(0x00+..+0x0F)= 256- 0x78
Esta podría ser una rutina de lectura:
type buffer=array of byte; //Asignamos una matriz dinámica
var HexBuf:buffer;
function readline(HexLine:string; var Buf:buffer):integer;
var ADDR,count:integer;
CHKSUM,SUMLINE,RECLEN,RECTYPE,DATA:byte;
t:shortstring;
begin
// Longitud de la matriz (100000) se puede cambiar
SetLength(HexBuf,100000);
if HexLine[1]=':' then begin
t:='$'+copy(HexLine,2,2); // lee longitud (RECLEN)
RECLEN:=strtoint(t);
CHKSUM:=0;
CHKSUM:=CHKSUM+RECLEN;
t:='$'+copy(HexLine,4,4); // lee offset
ADDR:=strtoint(t);
CHKSUM:=CHKSUM+lo(ADDR)+hi(ADDR);
t:='$'+copy(HexLine,8,2);
RECTYPE:=strtoint(t);
CHKSUM:=CHKSUM+RECTYPE;
case RECTYPE of
0:begin // Bloque de datos
count:=0;
while (count < RECLEN) do begin
t:='$'+copy(HexLine,10+2*count,2);
DATA:=strtoint(t);
CHKSUM:=CHKSUM+DATA;
Buf[ADDR+count]:=DATA;
inc(count);
end;
t:='$'+copy(HexLine,10+2*count,2);
SUMLINE:=strtoint(t);
end;
1:begin // EOF o fin de fichero
t:='$'+copy(HexLine,10,2);
SUMLINE:=strtoint(t);
result:=1;
end;
else
begin
result := -2; // tipo de record inválido
exit;
end;
end; //fin de bloque case
// test checksum
DATA:=SUMLINE+CHKSUM;
if (DATA<>0) then result:=-3; // checksum error
end
else result:=-1; // no hay record
end;
Y un ejemplito de uso:
procedure TForm1.Button1Click(Sender: TObject);
var Fname,line:string;
Fp : textfile;
ErrorCode:integer;
begin
Fname:='test.hex';
AssignFile(Fp,Fname); //fichero test.hex
Reset(Fp);
while not eof(Fp) do
begin
Readln(Fp, line);//lee primera línea del fichero
ErrorCode := readline(line,HexBuf);
if (ErrorCode=0) then
begin
// Linea leída OK
// aquí va el código a pegar Hexbuf en tu control
end
else
begin
// Manejo de errores
// 0 = No error
// -1 = Fichero no es Intel Hex
// -2 = Tipo de record inválido
// -3 = Checksum error
break; // fin loop
end;
end;
CloseFile(Fp);
end;
Esto en cuanto a la lectura, para la escritura, puedes usar esta función:
function writeline(ADDR,RECLEN,RECTYPE:integer;
var buf:buffer):string;
var i:integer;
CHKSUM:byte;
begin
CHKSUM:=0;
result:=':'+inttohex(RECLEN,2)+
inttohex(ADDR,4)+inttohex(RECTYPE,2);
CHKSUM:=RECLEN+lo(ADDR)+hi(ADDR);
for i:=0 to RECLEN-1 do begin
result:=result+inttohex(buf[ADDR+i],2);
CHKSUM:=CHKSUM+buf[ADDR+i];
end;
result:=result+inttohex(256-CHKSUM,2);
end;
function write_eof:string;
begin
result:=':00'+'0000'+'01'+'FF'; // :00000001FF fin de fichero
end;
Y un ejemplo de uso:
procedure TForm1.Button2Click(Sender: TObject);
var Fname,line:string;
Fp : textfile;
ErrorCode,StartAddr,ByteCnt:integer;
A_Line,EOF_HEX:string;
begin
StartAddr:=$0000; //Direccion de inicio 0000
ByteCnt:=3; // 3 bytes
SetLength(HexBufOut,ByteCnt);
HexBufOut[0]:=$01;
HexBufOut[1]:=$02;
HexBufOut[2]:=$03;
Fname:='test1.hex';
AssignFile(Fp,Fname); //Guarda fichero test1.hex
Rewrite(Fp);
// escribe 16 bytes en HexBuf
A_Line:=writeline(StartAddr,ByteCnt,$00,HexBufOut);
EOF_HEX:=':00'+'0000'+'01'+'FF';// escribe EOF del fichero hex
writeln(Fp,A_Line);
writeln(Fp,EOF_HEX);
closefile(Fp); //cierra el fichero
end;
Ahora solo necesitas implementar el poner los datos de Hexbuf a tu control y sacarlos para hexbuf antes de escribir el fichero, incorporar un cuadro de diálogo de abrir fichero o guardar y ya está. ¿sencillo, no?

Espero haberte ayudado,
Salu2