Public
Edited
Nov 10, 2024
Insert cell
Insert cell
sample = `
:10800000C3AD1300000000000000000000000000ED
:027ffe0002037C
:00000001FF
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
records = parser.parse(file ? await file.text() : sample)
Insert cell
function processRecords(records) {
const segments = [];
let extendedLinearAddress = 0;
let executionStartAddress = null;

// First pass: Create individual data segments
for (const record of records) {
switch (record.type) {
case "extended_linear_address":
extendedLinearAddress = record.data;
break;

case "start_linear_address":
executionStartAddress = record.data;
break;

case "data":
const fullAddress = (extendedLinearAddress << 16) + record.addr;
segments.push({
startAddress: fullAddress,
data: record.data
});
break;

case "eof":
// End of file record, no action needed
break;

default:
throw new Error(`Unknown record type: ${record.type}`);
}
}

// Second pass: Merge adjacent segments
// Sort segments by their starting address
segments.sort((a, b) => a.startAddress - b.startAddress);

const mergedSegments = [];
let currentSegment = null;

for (const segment of segments) {
if (
currentSegment &&
currentSegment.startAddress + currentSegment.data.length ===
segment.startAddress
) {
// Extend the current segment
const newData = new Uint8Array(
currentSegment.data.length + segment.data.length
);
newData.set(currentSegment.data);
newData.set(segment.data, currentSegment.data.length);
currentSegment.data = newData;
} else {
// Start a new segment
currentSegment = {
startAddress: segment.startAddress,
data: segment.data
};
mergedSegments.push(currentSegment);
}
}

return {
segments: mergedSegments,
executionStartAddress
};
}
Insert cell
parser = peggy.generate(`
start
= Record*

Record
= [^:]* ":"
size:ByteCount
addr:Address
data:(
"00" bytes:HexPair|size| checksum:HexPair {
return { type: 'data',
data: new Uint8Array(bytes.map(hex => parseInt(hex, 16))) };
} /
"01" "ff"i {
return { type: 'eof', data: null };
} /
// upper 16 bits of the 32 bit absolute address for all subsequent type 00 records
// until the next 04 record
"04" bytes:HexPair|size| checksum:HexPair {
return { type: 'extended_linear_address',
data: parseInt(bytes.join(''), 16) };
} /
// this 32-bit address is the address at which execution should start
"05" bytes:HexPair|size| checksum:HexPair {
return { type: 'start_linear_address',
data: parseInt(bytes.join(''), 16) };
}
)
S? { return {type: data.type, addr, size, data: data.data} }

ByteCount
= h:HexPair { return parseInt(h, 16) }

Address
= h:$[0-9a-f]i |4| { return parseInt(h, 16) }

HexPair
= $[0-9a-f]i |2|
// Whitespace
S = $[ \\t\\r\\n]+
`)
Insert cell
peggy = require("peggy@4.0.3")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more