public static void SaveAsIntelHex(string fileName, BinaryBlock[] blocks) { using (StreamWriter writer = new StreamWriter(fileName)) { foreach (BinaryBlock b in blocks) { byte[] data = b.GetBytes(); ushort high = (ushort)(b.Address >> 16); ushort low = (ushort)(b.Address & 0xFFFF); writer.WriteLine(IntelHexRecord.EncodeLine(eRecordType.ExtendedLinearAddress, 0, new byte[] { (byte)(high >> 8), (byte)high })); /* Align the data start addrss to hexLineDataLen bytes */ int datalinelen = hexLineDataLen - (int)b.Address % hexLineDataLen; writer.WriteLine(IntelHexRecord.EncodeLine(eRecordType.Data, low, data.SubArray(0, (datalinelen > data.Length)? data.Length : datalinelen))); for (int i = datalinelen; i < data.Length;) { /*Add last value*/ low += (ushort)datalinelen; datalinelen = ((data.Length - i) > hexLineDataLen) ? hexLineDataLen : (data.Length - i); if (low == 0) { high++; writer.WriteLine(IntelHexRecord.EncodeLine(eRecordType.ExtendedLinearAddress, 0, new byte[] { (byte)(high >> 8), (byte)high })); } writer.WriteLine(IntelHexRecord.EncodeLine(eRecordType.Data, low, data.SubArray(i, datalinelen))); i += datalinelen; } } /* Append end of file line */ writer.WriteLine(IntelHexRecord.EncodeLine(eRecordType.EndOfFile, 0, null)); } }
public void Load(string fileName, eHash hash = eHash.CRC32, bool append = false) { if (!append) { blocks.Clear(); } using (StreamReader reader = new StreamReader(fileName)) { UInt32 CurrentAddress = 0, LastAddress = 0xFFFFFFFF; BinaryBlock newblock = null; while (reader.Peek() > 0) { IntelHexRecord record = new IntelHexRecord(reader.ReadLine()); /* * I32HEX files use only record types 00, 01, 04, and 05 (32 bit addresses) * 00 : Data * 01 : End Of File * 04 : Extended Linear Address * 05 : Start Linear Address */ switch (record.RecordType) { case eRecordType.ExtendedLinearAddress: /* * Allows for 32 bit addressing (up to 4GiB). * The address field is ignored (typically 0000) and the byte count is always 02. * The two encoded, big endian data bytes specify the upper 16 bits of the 32 bit absolute address for * all subsequent type 00 records; these upper address bits apply until the next 04 record. * If no type 04 record precedes a 00 record, the upper 16 address bits default to 0000. * The absolute address for a type 00 record is formed by combining the upper 16 address bits of * the most recent 04 record with the low 16 address bits of the 00 record. */ CurrentAddress = (((UInt32)record.Bytes[0]) << 24) | (((UInt32)record.Bytes[1]) << 16); break; case eRecordType.Data: /* * Contains data and a 16-bit starting address for the data. * The byte count specifies number of data bytes in the record. */ CurrentAddress = CurrentAddress & 0xFFFF0000 | (UInt32)record.Address; if (LastAddress != CurrentAddress) { if (newblock != null) { newblock.UpdateHash(hash); } newblock = new BinaryBlock(CurrentAddress); int i = 0; for (; i < blocks.Count; i++) { if (blocks[i].Address > CurrentAddress) { break; } } blocks.Insert(i, newblock); } newblock.Append(record.Bytes); LastAddress = CurrentAddress + (UInt32)record.Bytes.Length; break; case eRecordType.EndOfFile: /* * Must occur exactly once per file in the last line of the file. * The data field is empty (thus byte count is 00) and the address field is typically 0000. */ if (newblock != null) { newblock.UpdateHash(hash); } return; case eRecordType.StartLinearAddress: case eRecordType.StartSegmentAddress: /* * The address field is 0000 (not used) and the byte count is 04. * The four data bytes represent the 32-bit value loaded into the EIP register of the 80386 and higher CPU. * * We ignore the record */ break; default: throw new NotSupportedException("Unsupported line present"); } } } }