-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathintel-hex-parser.ts
More file actions
89 lines (76 loc) · 2.7 KB
/
intel-hex-parser.ts
File metadata and controls
89 lines (76 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
* Intel HEX File Parser
* Parses Intel HEX format files and merges segments into a single data array
*/
export interface HexParseResult {
data: Uint8Array;
address: number;
}
/**
* Verify checksum for an Intel HEX record line
* @param line The hex record line starting with ':'
* @returns true if checksum is valid
*/
function verifyChecksum(line: string): boolean {
// Remove the ':' prefix and parse hex pairs
const hexData = line.substring(1);
// Sum all bytes including the checksum
// The sum of all bytes (including checksum) should be 0 (mod 256)
let sum = 0;
for (let i = 0; i < hexData.length; i += 2) {
const byte = parseInt(hexData.substring(i, i + 2), 16);
sum += byte;
}
// Verify that the sum is 0 modulo 256
return (sum & 0xFF) === 0;
}
/**
* Parse Intel HEX file and merge segments into a single Uint8Array
*/
export async function parseHexFile(content: string): Promise<HexParseResult> {
const lines = content.split('\n')
.map(line => line.trim())
.filter(line => line.startsWith(':'));
const segments = new Map<number, number[]>();
for (const line of lines) {
// Verify checksum
if (!verifyChecksum(line)) {
throw new Error(`Invalid checksum in line: ${line}`);
}
const byteCount = parseInt(line.substring(1, 3), 16);
const address = parseInt(line.substring(3, 7), 16);
const recordType = parseInt(line.substring(7, 9), 16);
if (recordType === 0) {
// Data record
const hexData = line.substring(9, 9 + byteCount * 2);
if (!segments.has(address)) {
segments.set(address, []);
}
for (let i = 0; i < byteCount; i++) {
const byte = parseInt(hexData.substring(i * 2, i * 2 + 2), 16);
segments.get(address)!.push(byte);
}
} else if (recordType === 1) {
// End of file
break;
}
}
// Find the address range
let minAddr = Infinity;
let maxAddr = 0;
for (const addr of segments.keys()) {
minAddr = Math.min(minAddr, addr);
const endAddr = addr + segments.get(addr)!.length - 1;
maxAddr = Math.max(maxAddr, endAddr);
}
// Merge all segments into a single Uint8Array
const mergedSize = maxAddr - minAddr + 1;
const mergedData = new Uint8Array(mergedSize);
for (const [addr, bytes] of segments) {
const offset = addr - minAddr;
for (let i = 0; i < bytes.length; i++) {
mergedData[offset + i] = bytes[i];
}
}
return { data: mergedData, address: minAddr };
}