Files
Sprinter-SDCC/toolchain/sdbg/image.py
T

52 lines
2.5 KiB
Python

"""Строгий разбор Intel HEX для проверки образа, загруженного в MAME."""
from __future__ import annotations
from pathlib import Path
def read_ihx(path: Path) -> dict[int, int]:
"""Возвращает разреженный образ и отвергает битые/конфликтующие записи."""
memory: dict[int, int] = {}
base = 0
eof = False
for number, raw in enumerate(Path(path).read_text().splitlines(), 1):
if not raw.startswith(':'):
raise ValueError(f'Intel HEX, строка {number}: отсутствует двоеточие')
try:
record = bytes.fromhex(raw[1:])
except ValueError as error:
raise ValueError(f'Intel HEX, строка {number}: неверные hex-цифры') from error
if len(record) < 5 or len(record) != record[0] + 5:
raise ValueError(f'Intel HEX, строка {number}: неверная длина')
if sum(record) & 0xff:
raise ValueError(f'Intel HEX, строка {number}: неверная контрольная сумма')
length = record[0]
address = int.from_bytes(record[1:3], 'big')
kind = record[3]
data = record[4:4 + length]
if eof:
raise ValueError(f'Intel HEX, строка {number}: данные после EOF')
if kind == 0:
for offset, value in enumerate(data):
absolute = base + address + offset
if absolute in memory and memory[absolute] != value:
raise ValueError(f'Intel HEX: конфликт по адресу {absolute:#x}')
memory[absolute] = value
elif kind == 1:
if length or address:
raise ValueError(f'Intel HEX, строка {number}: неверная EOF-запись')
eof = True
elif kind == 2:
if length != 2 or address:
raise ValueError(f'Intel HEX, строка {number}: неверная segment-запись')
base = int.from_bytes(data, 'big') << 4
elif kind == 4:
if length != 2 or address:
raise ValueError(f'Intel HEX, строка {number}: неверная linear-запись')
base = int.from_bytes(data, 'big') << 16
elif kind not in (3, 5):
raise ValueError(f'Intel HEX, строка {number}: неизвестный тип {kind}')
if not eof:
raise ValueError('Intel HEX: отсутствует EOF')
return memory