from abc import ABC, abstractmethod import crcmod # pyright: ignore[reportMissingTypeStubs] from queue import Queue from flash.shared import FlashChip class DCCEmulatedHost(ABC): def __init__(self, loader: bytes | bytearray, loader_offset: int, loader_ram_size: int, breakpoint_loader: bool=False): self._is_bp_loader: bool = breakpoint_loader self._bp_loader_buf_in: Queue[int] = Queue() self._bp_loader_buf_out: list[int] = [] self._loader_data: bytes = bytes(loader) self._loader_start: int = loader_offset @abstractmethod def run(self): pass @abstractmethod def mount_flash_chip(self, chip: FlashChip, chip_offset: int, chip_size: int): pass @abstractmethod def _dcc_read(self) -> int: pass @abstractmethod def _dcc_write(self, data: int): pass @abstractmethod def _dcc_flush_buffer(self): pass def dcc_read_packet(self, progress: bool=False): read_item_count = self._dcc_read() crc_hash_func = crcmod.mkCrcFun(0x104c11db7, 0xffffffff, False, 0) # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType] read_data = bytearray() for i in range(read_item_count): get_data = self._dcc_read() get_index = i + 1 if progress and (((get_index % 50) == 0)): print(f"got {get_index} out of {read_item_count}", end="\r") read_data += get_data.to_bytes(4, "little") crc32_sum = self._dcc_read() crc32_hash = crc_hash_func(read_data) # pyright: ignore[reportUnknownVariableType] assert crc32_sum == crc32_hash, f"Packet checksum is invalid! 0x{crc32_sum:08x} != 0x{crc32_hash:08x}" return read_data def dcc_write_packet(self, data: list[int]): for p in data: self._dcc_write(p) if self._is_bp_loader: self._dcc_flush_buffer()