import struct, sys sys.path.insert(0, r"C:/Users/vikto/Documents/Claude/rt-4d/rt4d-cps") from rt4d_codeplug.tones import decode_subaudio_bytes DUMP = r"C:/Users/vikto/Documents/Claude/rt-4d/radio-spi-dump.bin" data = open(DUMP, "rb").read() print("size", len(data)) CH_BASE = 0x004000 ZN_BASE = 0x01C000 CT_BASE = 0x05C000 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 print("="*70) print("CHANNELS") for i in range(6): off = CH_BASE + i*48 d = data[off:off+48] if all(b==0xFF for b in d): print(f"ch{i}: EMPTY"); continue rx = struct.unpack('>1)&1} dmrmode={(b0>>2)&1} useChID={(b0>>3)&1} rxtx={(b0>>4)&3}") print(f" b1=0x{b1:02X} scramble={b1&0xF} colorcode={(b1>>4)&0xF}") print(f" b2=0x{b2:02X} tot={b2&0x3F} power={'HIGH' if b2&0x40 else 'LOW'}") print(f" b3=0x{b3:02X} tailtone={b3&7} anaBusyLock={(b3>>3)&3} dmrBusyLock={(b3>>5)&3} scan={'REMOVE' if b3&0x80 else 'ADD'}") print(f" b4=0x{b4:02X} ctdcs_sel={(b4>>1)&7} mod={(b4>>4)&3} bw={'Narrow' if (b4>>6)&1 else 'Wide'}") print(f" rx_tone={decode_subaudio_bytes(d[0x0D:0x0F])} tx_tone={decode_subaudio_bytes(d[0x0F:0x11])}") cslot=struct.unpack('idx {0 if cslot==0xFFFF else cslot+1}) grouplist(0x13)={d[0x13]} encrypt(0x14)={struct.unpack(' 2: # empty per parser continue name = bytes(b for b in d[0x10:0x20] if b!=0xFF).decode('gbk','ignore').strip() dmr = parse_bcd(d[0x02:0x06]) print(f"\nct{i} @0x{off:06X}") print(" raw:", hx(d)) print(f" type(b1)={d[1]} name={name!r} dmr_id(BCD 0x2)={dmr}") print(f" b0=0x{d[0]:02X} bytes6-F: {hx(d[6:16])}") cnt+=1 if cnt>=6: break print("="*70) print("ZONES") zc=0 for i in range(256): off = ZN_BASE + i*512 d = data[off:off+512] if d[0]==0xFF: continue name = bytes(b for b in d[0x04:0x14] if b!=0xFF).decode('gbk','ignore').strip() count = d[0] | (d[1]<<8) print(f"\nzone{i} @0x{off:06X} name={name!r} count(b0-1)={count} curA(b2)={d[2]} curB(b3)={d[3]}") print(" head 0x00-0x13:", hx(d[0:0x14])) chans=[] for k in range(min(count,200)): o=0x14+k*2 ci=d[o]|(d[o+1]<<8) chans.append(ci) print(" channel idx list:", chans[:30]) scan=d[0x1A4:0x1A4+25] print(" scan bitmap @0x1A4:", hx(scan)) zc+=1 if zc>=4: break