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
co-authored by Claude Opus 4.8
Коммит ae36c3b729
72 изменённых файлов: 24124 добавлений и 0 удалений
+29
Просмотреть файл
@@ -0,0 +1,29 @@
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)
CT=0x05C000
# raw region 0x5C000 .. 0x5F000
print("Search whole contacts region 0x5C000-0x6C000 for ascii runs & non-FF:")
region=data[CT:CT+0x10000]
# find first non-FF
first=None
for i,b in enumerate(region):
if b!=0xFF: first=i;break
print("first non-FF at region+0x%X = abs 0x%06X"%(first,CT+first))
# dump 0x5E000 area with 32B alignment relative to CT base
print("\n32B records from 0x5C000 index where data begins:")
# data begins at 0x5E000 => that's record (0x5E000-0x5C000)/32 = 0x2000/32=256
for idx in [255,256,257,258]:
off=CT+idx*32
d=data[off:off+32]
print(f"rec{idx} @0x{off:06X}:", hx(d))
# Try interpreting as: the two contacts are 'All Call' and 'TG6' and 'TG666'
# Layout guess A (like CPS .4rdmf): b0=?, b1=type, dmr@2 (4 LE or BCD), name@0x10 (16)
# But data misaligned. Let's realign: maybe record size is different or base offset differs.
# Locate ascii "All Call","TG6","TG666"
for tok in [b'All Call', b'TG6', b'TG666']:
p=data.find(tok, CT, CT+0x10000)
print(f"{tok} at 0x{p:06X} (region+0x{p-CT:X})")