Files
viktorиClaude Opus 4.8 ae36c3b729 RT-4D: реверс прошивки, русификация, кастомный UI, флешеры
- Полный RE стока V3.25 (Cortex-M4F) + FM100B: карта памяти, протокол, codeplug, UI-архитектура
- Русификация: свой CP1251-шрифт + патч рендера, перевод меню и надписей, ребренд Ru-4D V3.25
- Блюпринт переделки UI + C-тулчейн (clang thumbv7em), доказан инъекцией
- Готовые флешеры: WebSerial .html и Windows .exe со вшитой прошивкой
- Дамп SPI рации, стоковая прошивка, инструменты сборки

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 15:47:22 +09:00

49 строки
2.2 KiB
Python

import struct
DUMP = r"C:/Users/vikto/Documents/Claude/rt-4d/radio-spi-dump.bin"
with open(DUMP, "rb") as f:
cal = f.read(0x1000)
# The header +0x02: 37 a0 38 6b and +0x06: 40 ab ... Let's test freq*100000 interpretation.
# But RT-4D VHF band 136-174, UHF 400-480. As MHz*100000: 136MHz=13600000=0x00CF8500.
# header bytes 37 a0 38 6b 40 ab don't look like that. Try as MHz*? Let's see 0x6b38a037? no.
# Maybe the header tail 16 bytes [58,60,63,65,68,71,74,75,76,77,78,79,80,81,82,128] are the
# 15-point + terminator for RX/AGC or S-meter. The last is 0x80.
# KEY INSIGHT: tag bytes: rec0=0x0a, rec1=0x11. In the header at 0x0c-0x0f we saw "0a 00 05 00".
# Header +0x08: 05 00 05 00 0a 00 05 00 => (5,5,10,5). rec0 tag=0x0a=10, rec1 tag=0x11=17.
# Let's look: maybe tag = number of active frequency points? rec0=10, but table0 rec0 has 8 distinct then flat.
# Re-examine: table0 rec0: 2f 2d 2d 32 33 35 37 3e | 3e repeated? no: 3e then 37 37...
# Actually first 8 vary, last 8 are flat=0x37. rec0 tag=0x0a=10.
# rec1 tag=0x11=17, table0 rec1 all 16 vary (55..62..61).
# Hypothesis: tables have 16 columns = 16 frequency calibration points spanning the band.
# Let's just present the 6 tables clearly and label by likely meaning based on value ranges.
base=0x20; REC=0x70
labels_guess = ["TX_power_low? / bias","?","?","TX_power_high?","?","?"]
for idx in [0,1]:
off=base+idx*REC; r=cal[off:off+REC]
print(f"REC{idx} tag=0x{r[0]:02x}({r[0]}) flag=0x{r[1]:02x}")
for t in range(6):
tab=list(r[0x10+t*16:0x10+t*16+16])
rng=f"min={min(tab)} max={max(tab)}"
print(f" t{t} +0x{0x10+t*16:02x}: {tab} {rng}")
print()
# Check equality relationships between tables within rec1
r=cal[base+REC:base+2*REC]
t=[list(r[0x10+k*16:0x10+k*16+16]) for k in range(6)]
print("rec1 t3==t5?", t[3]==t[5])
r0=cal[base:base+REC]
t0=[list(r0[0x10+k*16:0x10+k*16+16]) for k in range(6)]
print("rec0 t3==t5?", t0[3]==t0[5])
print("rec0 t0 first8 vary, last8:", t0[0][8:])
# Reference const 12 e2 34 40 2a 4f b3 : could be a float? 40 34 e2 12 as BE float:
import struct as s
be = s.unpack(">f", bytes([0x40,0x34,0xe2,0x12]))[0]
le = s.unpack("<f", bytes([0x12,0xe2,0x34,0x40]))[0]
print("const first4 as float BE:", be, "LE:", le)
# 2a 4f b3 remaining