diff --git a/src/teletext/io.py b/src/teletext/io.py index 82001e5..9092f3b 100644 --- a/src/teletext/io.py +++ b/src/teletext/io.py @@ -100,36 +100,63 @@ def encode_hamming_8_4(value): return res + +def decode_packet_header(b1, b2): + """ + Decodes the Magazine and Row from the first 2 bytes of a T42 packet. + """ + d1 = decode_hamming_8_4(b1) + d2 = decode_hamming_8_4(b2) + + mag = (d1 & 0b0111) + if mag == 0: mag = 8 + + row = (d2 << 1) | ((d1 >> 3) & 1) + return mag, row + def save_t42(file_path: str, service: TeletextService): with open(file_path, 'wb') as f: for packet in service.all_packets: - # Reconstruct header bytes from packet.magazine and packet.row - # Byte 1: M1 M2 M3 R1 - # Byte 2: R2 R3 R4 R5 + # Check if we can reuse the original header (preserving parity/integrity) + use_original_header = False - mag = packet.magazine - if mag == 8: mag = 0 # 0 encoded as 8 + if hasattr(packet, 'original_data') and len(packet.original_data) >= 2: + # Try to decode the original header + try: + orig_mag, orig_row = decode_packet_header(packet.original_data[0], packet.original_data[1]) + if orig_mag == packet.magazine and orig_row == packet.row: + use_original_header = True + except: + pass - # Bits: - # B1 data: M1(0) M2(1) M3(2) R1(3) - m1 = (mag >> 0) & 1 - m2 = (mag >> 1) & 1 - m3 = (mag >> 2) & 1 - r1 = (packet.row >> 0) & 1 - - b1_val = m1 | (m2 << 1) | (m3 << 2) | (r1 << 3) - b1_enc = encode_hamming_8_4(b1_val) - - # B2 data: R2(0) R3(1) R4(2) R5(3) - r2 = (packet.row >> 1) & 1 - r3 = (packet.row >> 2) & 1 - r4 = (packet.row >> 3) & 1 - r5 = (packet.row >> 4) & 1 - - b2_val = r2 | (r3 << 1) | (r4 << 2) | (r5 << 3) - b2_enc = encode_hamming_8_4(b2_val) - - header = bytes([b1_enc, b2_enc]) + if use_original_header: + header = packet.original_data[:2] + else: + # Reconstruct header bytes + mag = packet.magazine + if mag == 8: mag = 0 # 0 encoded as 8 + + # Bits: + # B1 data: M1(0) M2(1) M3(2) R1(3) + m1 = (mag >> 0) & 1 + m2 = (mag >> 1) & 1 + m3 = (mag >> 2) & 1 + r1 = (packet.row >> 0) & 1 + + b1_val = m1 | (m2 << 1) | (m3 << 2) | (r1 << 3) + b1_enc = encode_hamming_8_4(b1_val) + + # B2 data: R2(0) R3(1) R4(2) R5(3) + r2 = (packet.row >> 1) & 1 + r3 = (packet.row >> 2) & 1 + r4 = (packet.row >> 3) & 1 + r5 = (packet.row >> 4) & 1 + + b2_val = r2 | (r3 << 1) | (r4 << 2) | (r5 << 3) + b2_enc = encode_hamming_8_4(b2_val) + + header = bytes([b1_enc, b2_enc]) + f.write(header + packet.data) def decode_hamming_8_4(byte_val):