52 lines
2.5 KiB
Python
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
|