import struct, sys, io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
DUMP = r"C:/Users/vikto/Documents/Claude/rt-4d/radio-spi-dump.bin"
data = open(DUMP, "rb").read()
def hx(b): return " ".join(f"{x:02X}" for x in b)
def parse_bcd(bcd):
    if all(b==0xFF for b in bcd): return 0
    r=0
    for bv in reversed(bcd):
        hi=(bv>>4)&0xF; lo=bv&0xF
        if hi==0xF: hi=0
        if lo==0xF: lo=0
        r=r*100+hi*10+lo
    return r

# Are 0x1C000 blocks packed 48B channels identical to main channels 0x4000?
print("Compare 0x1C000 first 96 bytes vs main channels 0x4000:")
print(" 0x1C000:", hx(data[0x1C000:0x1C000+96]))
print(" 0x04000:", hx(data[0x04000:0x04000+96]))
print(" match:", data[0x1C000:0x1C000+96]==data[0x04000:0x04000+96])

# Contacts - the two records
print("\nCONTACT records decode:")
for off in (0x05E000,0x05E020):
    d=data[off:off+32]
    print(f"@0x{off:06X}:", hx(d))
    print(f"   b0={d[0]:02X} b1(type)={d[1]:02X} dmr_id(BCD@2)={parse_bcd(d[2:6])} raw_le@2={struct.unpack('<I',d[2:6])[0]}")
    print(f"   name@0x10:", bytes(b for b in d[0x10:0x20] if b!=0xFF).decode('gbk','ignore'))
    print(f"   bytes 6-F:", hx(d[6:16]))

# The ct256 record: b1=0xAA (=170) type not <=2, name shows 'All Call'? re-decode name area
d=data[0x05E000:0x05E000+32]
print("\nct256 name @0x05..0x0D area (looks like 'All Call' at 0x05):", bytes(b for b in d[0x05:0x0D]).decode('latin1'))

# contact ct257 @0x5E020: name at 0x0F='TG366'? decode 0x0D..
d=data[0x05E020:0x05E020+32]
print("ct257 full decode: b0-F=",hx(d[:16]), " tail=", bytes(b for b in d[0x0B:0x14] if b!=0xFF).decode('latin1','ignore'))

# scan whole contacts region for the real contact layout - look at more contact entries near 0x5E000
print("\nHex dump 0x05E000..0x05E080:")
for r in range(0,0x80,16):
    print(f" +{r:04X}:", hx(data[0x05E000+r:0x05E000+r+16]))
