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 удалений
+51
Просмотреть файл
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Uppercase Russian bitmap font for the RT-4D, 6px wide (col 6 blank => 1px
gap with the fixed 7px advance), body rows 3..10 (descenders to 11).
Format encoded elsewhere: column-major 7 cols x 14 rows, 2 bytes/col LE, bit0=top.
Each glyph here is a list of up to 9 six-char rows placed starting at row `TOP`."""
TOP = 3
# 6-wide bitmaps (cols 0..5). '#'=pixel. Bottom-aligned on baseline row 10.
UPPER = {
"А": ["_####_","#____#","#____#","#____#","######","#____#","#____#","#____#"],
"Б": ["######","#_____","#_____","#####_","#____#","#____#","#____#","#####_"],
"В": ["#####_","#____#","#____#","#####_","#____#","#____#","#____#","#####_"],
"Г": ["######","#_____","#_____","#_____","#_____","#_____","#_____","#_____"],
"Д": ["_####_","_#__#_","_#__#_","_#__#_","_#__#_","######","#____#","#____#"],
"Е": ["######","#_____","#_____","#####_","#_____","#_____","#_____","######"],
"Ё": ["#_##_#","______","######","#_____","#####_","#_____","#_____","######"],
"Ж": ["#_#_#_","#_#_#_","_###__","__#___","_###__","#_#_#_","#_#_#_","#_#_#_"],
"З": ["_###__","#___#_","____#_","__##__","____#_","#___#_","_###__","______"],
"И": ["#____#","#___##","#__#_#","#_#__#","##___#","#____#","#____#","#____#"],
"Й": ["_####_","#____#","#___##","#__#_#","#_#__#","##___#","#____#","#____#"],
"К": ["#___#_","#__#__","#_#___","##____","#_#___","#__#__","#___#_","#____#"],
"Л": ["_####_","_#__#_","_#__#_","_#__#_","_#__#_","#___#_","#___#_","#___#_"],
"М": ["#____#","##__##","#_##_#","#_##_#","#____#","#____#","#____#","#____#"],
"Н": ["#____#","#____#","#____#","######","#____#","#____#","#____#","#____#"],
"О": ["_####_","#____#","#____#","#____#","#____#","#____#","#____#","_####_"],
"П": ["######","#____#","#____#","#____#","#____#","#____#","#____#","#____#"],
"Р": ["#####_","#____#","#____#","#####_","#_____","#_____","#_____","#_____"],
"С": ["_####_","#____#","#_____","#_____","#_____","#_____","#____#","_####_"],
"Т": ["######","__#___","__#___","__#___","__#___","__#___","__#___","__#___"],
"У": ["#____#","#____#","#____#","_####_","___#__","___#__","__#___","_##___"],
"Ф": ["__#___","_####_","#_#__#","#_#__#","#_#__#","_####_","__#___","__#___"],
"Х": ["#____#","#____#","_#__#_","__##__","__##__","_#__#_","#____#","#____#"],
"Ц": ["#___#_","#___#_","#___#_","#___#_","#___#_","#___#_","######","____##"],
"Ч": ["#____#","#____#","#____#","_#####","_____#","_____#","_____#","_____#"],
"Ш": ["#_#__#","#_#__#","#_#__#","#_#__#","#_#__#","#_#__#","#_#__#","######"],
"Щ": ["#_#__#","#_#__#","#_#__#","#_#__#","#_#__#","#_#__#","######","_____#"],
"Ъ": ["##____","_#____","_#____","_####_","_#___#","_#___#","_#___#","_####_"],
"Ы": ["#____#","#____#","#____#","##___#","#_#__#","#_#__#","#_#__#","##___#"],
"Ь": ["#_____","#_____","#_____","#####_","#____#","#____#","#____#","#####_"],
"Э": ["_###__","#___#_","____#_","__###_","____#_","____#_","#___#_","_###__"],
"Ю": ["#__##_","#_#__#","#_#__#","###__#","#_#__#","#_#__#","#_#__#","#__##_"],
"Я": ["_#####","#____#","#____#","_#####","__#__#","_#___#","#____#","#____#"],
}
def rows_for(ch):
body = UPPER[ch]
grid = ["______"] * 14
for i, r in enumerate(body):
grid[TOP + i] = r.replace("_", ".")
return grid