chore: reorganize analysis/ by SDK lineage (linux/win/android) with README index, move legacy notes to history/, refresh root README, ignore .zcode/

This commit is contained in:
ZXCLI
2026-09-10 03:09:13 +08:00
parent 4ba98f62cd
commit e69a97436b
137 changed files with 123 additions and 62 deletions
+55
View File
@@ -0,0 +1,55 @@
# analysis/ — MAG160C 逆向工程总目录
> 本目录汇总了 MAG160C 相关的**全部逆向工程材料**,覆盖三条产品线:
> ① Linux SDKlibmagcore.so)② Windows SDKCoreSDKLib.dll / ThermalSDK.dll
> ③ 官方安卓 AppMAG-Cx 普通版:Java 层 + libcxsdk.so / libcoresdk.so)。
> 阅读顺序建议:先读本 README → `magcx_official_flow.md`(权威协议结论)
> → 按需深入各分目录。
## 顶层文件(结论与工具)
| 文件 | 内容 |
|---|---|
| `magcx_official_flow.md` | **权威协议结论**2026-09-10,官方 Java 源码逐行核对版):命令表、BasePara/CaliInfo 布局、连接序列、标定文件下载、FFC 逻辑 |
| `protocol_spec.md` | 早期 PC 端逆向协议(libmagcore/CoreSDKLib2026-08-10 硬件验证),历史参考 |
| `gen_kotlin_tables.py` | 生成 `OfficialTables.kt`palette256/T2E/E2T)的脚本 |
| `render_offline.c` | PC 端参考渲染管线(gcc 编译),Kotlin 移植的逐字节差分基准 |
| `official_render_frame.rgb` / `official_t2e_table.txt` / `t2e_table.json` / `test_ref_stats.txt` | PC 差分验证数据 |
| `revtools.py` / `reverse_tools/` | 逆向辅助脚本 |
## sdk_re/ — 按 SDK 产品线归档
### `sdk_re/linux_libmagcore/` — Linux SDKlibmagcore.so.2.1.1x86-64
- `magcore_disasm.txt`(全量反汇编)+ `magcore_defined.txt` / `magcore_dynsyms.txt` / `magcore_relocs.txt`
- `disasm_*.txt`:关键函数级反汇编(LinkCameraEx / StartProcessImage / Raw2Temperature /
ConvertResponse2Temp / ReviseTemperature / ffc / frameParse / AccumulatorPushFrame 等)
- `all_functions_decomp_libmagcore.so_00100000.txt`Ghidra 全量伪代码
### `sdk_re/windows_sdk/` — Windows SDKCoreSDKLib.dll / ThermalSDK.dll
- `refs_CoreSDKLib.dll.txt` / `exports_decomp_CoreSDKLib.dll.txt` / `keyfuncs_decomp_CoreSDKLib.dll.txt`
/ `callers_decomp_CoreSDKLib.dll.txt` / `coresdk_keyfuncs_disasm.txt` / `coresdk_windows_disasm.txt`
- `exports_decomp_ThermalSDK.dll.txt` + `thermalsdk_dll/` + `thermalsdk_so/`ThermalSDK 包装层)
### `sdk_re/android_app/` — 官方安卓 App(普通版 MAG-Cx,本管线上真机跑通的代码)
- `jadx_magcx/`**全量 Java 源码**jadx 1.5.1)。核心:`cn/com/magnity/magnitycx/sdk/UsbCommunication.java`
USB 协议真身)、`P2DCmd.java`/`D2PCmd.java`(命令表)、`DeviceController.java`JNI 封装)
- `libcxsdk_decomp.txt`Ghidra 全量伪代码(libcxsdk.so1290 函数;Controller::StartProcess /
PushFrame / LoadCalibrationTable 已核对)
- `all_functions_decomp_libcoresdk_arm64.so_00100000.txt`libcoresdk(arm64) 全量伪代码
(专业版/网络路径,CNetComm 命令层)
- `coresdk_arm64_defined.txt`ARM64 库符号表
## history/ — 过程记录(按时间)
`task_plan_20260714``findings_20260810` / `progress_20260810` / `handoff_20260810..13` /
`交接_完整逆向工程说明_20260811`PC SDK 全流程报告)→ `reverse_20260813_full` /
`progress_reverse`。历史参考,协议细节以 `magcx_official_flow.md` 为准。
## preview/ — 渲染验证截图
demo2_v3..v7 系列(管线复刻过程对照)、preview_*.png(安卓 UI 验证)。
## 与代码库的关系
- `csdk/src/`:依据 Linux SDK 逆向写出的 C 参考实现(渲染/温度/IR 会话/FFC 调度),
Kotlin 管线(android/app)与其逐字节差分验证一致。
- `android/app/src/main/java/com/mag160c/thermal/usb/IrSession.kt`:官方
UsbCommunication.java 的 Kotlin 等价实现(含小端命令、800ms 超时、0x84 标定下载)。
- `docs/android_app/HANDOFF_DEVELOPMENT.md` §4.2 指向本目录。
@@ -0,0 +1,890 @@
# MAG160C 热像仪逆向工程完整交接说明
## 1. 文档目的
本文档用于把 `C:\Project\MAG160C` 整个工程移交给另一位工程师或另一位 AI。目标不是只说明当前代码怎么编译,而是把以下内容全部交代清楚:
- 工程每个主要目录的用途。
- MAG160C 硬件、USB、帧格式和驱动环境。
- 官方 Windows、Android、Linux SDK 的逆向成果。
- 官方 CoreSDKLib.dll 实际渲染主链路。
- `mag160c_demo3.c` 当前实现和所有实验性分支。
- 已经解决的问题、仍未解决的问题和曾经失败的路线。
- 如何安装工具、构建程序、连接设备、抓帧、运行和诊断。
- 如何继续逆向低温残影,并避免重复走已经验证失败的路线。
- 让下一位 AI 从零开始接手时可以直接使用的中文提示词。
文档日期:2026-08-11。工作目录:`C:\Project\MAG160C`。远端仓库:`https://git.zxcli.top/zxc/MAG160C.git`
## 2. 一分钟结论
### 2.1 硬件
- 设备是 MAG160C 160×120 红外热像仪。
- USB 设备常见身份是 VID `0x833C`、PID `0x0001`
- 它不是普通 UVC 热像仪,而是厂商自定义 USB bulk 协议。
- 命令使用 EP `0x03`,响应使用 EP `0x82`,实时帧使用 EP `0x81`
- 原始实时帧包含 160×120 个小端 `uint16` 像素。
### 2.2 官方渲染链路
官方 Windows `CoreSDKLib.dll` 的主链路已经被活体抓帧和反汇编共同确认:
```text
USB type=0 原始帧
-> f20 平滑器 0x41f10,当前 mode=1,基本是逐帧 memcpy
-> NUC 0x180017200
d2 = (f20[i] - ref[i]) >> 1
每像素两个 signed threshold 选择三个 segment
每像素 gain/off 查表
out = off + ((gain * d2) >> 12)
clamp 到 [0, 65535]
-> 0x180017330,固定表驱动的坏点/盲元邻域补偿
-> 可选 0x18001e920 temporal filter;当前实测 mode=1,通常跳过
-> 窗口 hi/lo
-> 1024 项灰度 LUT
-> 256 项 BGR 调色板
-> 320×240 输出
```
### 2.3 官方参考帧
- 官方参考缓冲来自 `dev+0x41ef0`,对象起点是 `dev+0x41ee0`
- 参考平滑器是 mode=4,启动阶段通过累计平均形成参考。
- 正常 type=0 帧不会逐帧重新采集整幅参考。
- FFC 后空间结构通常保持,只做全局基线变化或重新进入内部配置过程。
- 官方参考不是 demo3 当前的“每帧根据场景自适应参考”。
### 2.4 当前 demo3 状态
当前 demo3 已经接入一组从官方活体抓取并验证过的三段逐像素 NUC 表:
- `build-artifacts/mag160c_official_nuc_gain.bin`
- `build-artifacts/mag160c_official_nuc_thr.bin`
当前默认策略是:
- `CONSTANT_REF=1`
- `BADMAP_ENABLE=0`
- 官方表存在时使用三段逐像素 gain/off/threshold 查表。
- 使用当前场景中值在官方 NUC 输出域反求一个全局参考偏置,使中值约为 `NUC_CENTER=9804`
- `SBNUC_ENABLE=1`,但实际只允许“曾经进入热态、后来变成持续负残差”的像素在运动结束后自愈。
- 正残差不会写入参考,避免热目标被吸收。
- 显示层 `deghost_nuc()` 不调用。
当前仍未完全解决:
- 低温区域静止时间较长后仍可能出现残影。
- 某些固定参考失配会表现为黑洞。
- 官方每次 FFC/传感器温度区间变化后会重新生成 NUC 表;demo3 当前使用一组静态抓取表,没有完整复刻官方温度端点插值和运行时重建。
- 官方 `0x180017330` 的固定盲元补偿记录还没有完整接入 demo3 的新 NUC 表路径。
- 因此当前版本是比线性近似更接近官方的研究基线,不应宣称已经完全复刻官方。
## 3. 目录说明
### 3.1 根目录
| 路径 | 用途 |
|---|---|
| `README.md` | 仓库入口和最短说明。 |
| `交接_完整逆向工程说明_20260811.md` | 本完整交接文档。 |
| `findings.md` | 早期和中期的综合逆向发现,包含 Windows、Android、Linux SDK 证据。 |
| `progress.md` | 按日期记录的长期工程进度、协议恢复和工具安装记录。 |
| `task_plan.md` | 早期 Linux SDK 实现计划和历史任务状态。后续热像渲染工作应以本交接文档和 `analysis/handoff_*.md` 为准。 |
| `frame_stats.txt` | 历史原始帧统计。 |
| `pair_*.win``pair_*.win2``pair_*.nuctab` | 根目录中遗留的官方抓帧窗口、字段和短 NUC 表样本。完整抓帧在 `analysis/pairs_*`。 |
| `.gitattributes` | Git LFS 大文件规则。 |
| `.tools/` | 逆向分析工具、Python 包和下载缓存。 |
| `.agents/` | 当前为空,保留目录结构。 |
| `.superpowers/` | 早期计划工具的资料,当前不参与 demo3 运行。 |
| `app/` | 原厂 APK 和 PC 分析程序。 |
| `IR_Camera_SDK-1.0.1/` | 原厂 Windows、Android、Linux SDK、示例、驱动、DLL、SO 和文档。 |
| `vendor-docs/` | 从根目录整理出的模块硬件文档。 |
### 3.2 `csdk/`
这是当前维护的纯 C SDK 和 Windows 工具目录。
| 路径 | 用途 |
|---|---|
| `csdk/include/` | 对外头文件和 C API。 |
| `csdk/src/mag160c_frame.c` | `0x1bb1b11b` / `0x1bb1b11c` 帧解析和流组装。 |
| `csdk/src/mag160c_ir.c` | libusb 设备打开、命令、启动、停止、FFC、帧线程。 |
| `csdk/src/mag160c_temp.c` | 原始响应、PWL 校正、T2E 温度换算。 |
| `csdk/src/mag160c_tcm.c` | TCM 的 `0x7e` 帧和校验。 |
| `csdk/src/mag160c_display.c` | 坏点、显示、FFC 调度、线性温度工具。 |
| `csdk/src/mag160c_tables.h` | 从官方二进制提取的温度表。 |
| `csdk/tools/mag160c_demo3.c` | 当前主要 Windows 直连、渲染和残影实验程序。 |
| `csdk/tools/mag160c_demo2.c` | 历史显示管线和 MOG/NUC 实验版本。 |
| `csdk/tools/tsdk_pair2.c` | 官方 ThermalSDK 活体同帧抓帧工具。已修正 gain/thr 文件覆盖问题。 |
| `csdk/tests/` | C SDK 纯计算、协议、温度和显示测试。 |
| `csdk/third_party/libusb/win64/` | Windows x64 libusb 头文件、DLL 和 MinGW 导入库。 |
| `csdk/CMakeLists.txt` | CMake 构建文件。当前环境没有 CMake,主要使用直接 GCC 命令。 |
| `csdk/WINDOWS_TESTING.md` | USBPcap、Wireshark、MinGW 和硬件测试指南。 |
### 3.3 `analysis/`
这是逆向工程的核心证据目录。
| 路径 | 用途 |
|---|---|
| `analysis/disasm/` | Windows CoreSDK、Linux libmagcore、Android ARM64 的反汇编、符号和函数切片。 |
| `analysis/protocol_spec.md` | USB 协议、帧格式、命令、温度和 NUC 公式的正式规格。 |
| `analysis/progress_reverse.md` | 官方渲染主链和反汇编阶段性结论。 |
| `analysis/handoff_20260810.md` | demo2 早期路线、MOG、平场和问题演化。 |
| `analysis/handoff_20260811.md` | 较短的 2026-08-11 交接。 |
| `analysis/handoff_20260811_full.md` | 当前残影问题最重要的交接文档之一。 |
| `analysis/handoff_20260812.md` | 官方活体抓帧、NUC 和显示数据分析。 |
| `analysis/handoff_20260812_night.md` | 平滑器、参考和 NUC 查表的夜间逆向结论。 |
| `analysis/handoff_20260813.md` | 黑洞、SBNUC、Hardie/Kalman 路线的历史总结。 |
| `analysis/pairs_nuc2/` | 官方 NUC 同帧数据。 |
| `analysis/pairs_move/` | 官方移动目标数据。注意旧 `.gain/.thr` 曾被覆盖。 |
| `analysis/pairs_recheck_20260811/` | 使用修复后的 `tsdk_pair2_fixed.exe` 重新捕获的数据,包含未覆盖的真实 `.gain/.thr`。 |
| `analysis/pairs_long/` | 较长时间官方抓帧和内部缓冲。 |
| `analysis/pairs_ffc/``pairs_ffc2/` | FFC 前后对比。 |
| `analysis/pairs_win/``pairs2/``pairs_bar/` | 窗口、调色板和官方输出实验。 |
| `analysis/captures/` | USBPcap、libusb shim 和官方/csdk 抓包。 |
| `analysis/usbnoise/` | 原始噪声帧和元数据。 |
| `analysis/ourdump/` | 直连设备原始抓帧。 |
| `analysis/reverse-cache/` | AAR、JAR 等解包后的逆向缓存。 |
| `analysis/reverse_tools/` | ARM64/ELF 辅助工具。 |
| `analysis/revtools.py` | ELF 加载、符号、交叉引用辅助脚本。 |
| `analysis/t2e_table.json` | T2E 单调表。 |
| `analysis/official_t2e_table.txt` | 官方 T2E 提取文本。 |
| `analysis/legacy-cpp/` | 被纯 C SDK 替代的旧 C++ 实现和构建物。 |
| `analysis/demo2_*.png` | 历史实机验证截图。 |
### 3.4 `build-artifacts/`
该目录保存可直接运行的 Windows 程序、DLL、抓图、日志和实验产物。当前最重要的文件:
- `mag160c_demo3.exe`:当前 demo3。
- `mag160c_official_nuc_gain.bin`:官方三段 gain/off 表,230400 字节。
- `mag160c_official_nuc_thr.bin`:官方 threshold 抓取文件,115200 字节;demo3 实际使用前 76800 字节中的两个 threshold/像素,尾部多余数据保留作证据。
- `tsdk_pair2_fixed.exe`:修复 `.gain/.thr` 覆盖问题的官方抓帧工具。
- `demo3_diag.txt`demo3 每帧诊断日志。
- `demo3_ffc.txt`FFC 调度日志。
- `demo3_rebase.txt`FFC 后参考 rebase 日志。
- `demo3_auto_*.bmp`demo3 每 30 帧自动抓图。
- `official_*.bin``official_*.rgb``official_meta.txt`:官方活体输出样本。
- `csdk_*``mag160c_*``usb_*``tsdk_*`:历史测试和探针程序。
不要把 `build-artifacts` 当成唯一源代码目录。多数文件是从不同历史版本生成的,必须结合时间、文件名和日志判断是否属于当前版本。
## 4. 硬件和 USB 环境
### 4.1 设备身份
```text
VID = 0x833C
PID = 0x0001(常见值,具体以设备描述符为准)
分辨率 = 160×120
帧像素数 = 19200
常见帧率 = 15 fps
```
### 4.2 Windows 直连端点
| 端点 | 方向 | 用途 |
|---|---|---|
| `0x03` | 主机到设备 | 命令写入。 |
| `0x82` | 设备到主机 | 命令响应。 |
| `0x81` | 设备到主机 | 实时帧。 |
| `0x84` | 设备到主机 | 大块数据或 DDT 相关读取,当前 demo3 不依赖。 |
### 4.3 原始帧布局
EP `0x81` 数据以固定标记开始:
```text
+0x00 u32 0x1BB1B11B
+0x04 u32 帧计数
+0x08 u32 数据长度,160×120 时为 0x9600
+0x0C u32 帧类型,0 或 1
+0x10 u32 shutter/周期字段
+0x1C 38400 字节像素,19200 个小端 uint16
+0x1C+len u32 0x1BB1B11C
```
demo3 的第二次 bulk read 直接从 `data[0]` 读取 38400 字节像素;第一段 28 字节头已在 `hdr` 中读取。这是曾经修复过的关键偏移问题。
### 4.4 命令序列
当前设备实测的初始化序列:
```text
0x6BB6B66B4 字节
0x6BB6B66C4 字节
0x6BB6B66F4 字节
0x6BB6B672,参数 0,8 字节,通常连续发送两次
等待约 300 ms
0x6BB6B6734 字节,启动
```
停止:
```text
clear_halt(0x03)
clear_halt(0x82)
0x6BB6B6744 字节
```
FFC
```text
0x6BB6B672 + uint32 参数
```
不要把普通 4 字节命令误写成 8 字节;当前设备对普通命令的 8 字节形式可能 STALL。只有带参数的 FFC 使用 8 字节。
## 5. 官方 SDK 和反汇编成果
### 5.1 SDK 文件
原厂 SDK 主要在:
```text
IR_Camera_SDK-1.0.1/windows/windows/app/
IR_Camera_SDK-1.0.1/windows/windows/lib/x64/
IR_Camera_SDK-1.0.1/windows/windows/drivers/
IR_Camera_SDK-1.0.1/android/android/EloThermal/
IR_Camera_SDK-1.0.1/linux/1.2.2/1.2.2/EloThermal/
```
Windows 关键文件:
- `CoreSDKLib.dll`:底层 MAG API、USB 和渲染主链。
- `ThermalSDK.dll`:更高层的热像 API 包装。
- `libusb0.dll`:官方旧版 libusb-win32 路径使用。
- `CameraSDK.dll`:RGB/UVC 相机接口,不是红外原始帧主通道。
Android/Linux 版本提供了额外符号、JNI、C++ 类名和温度函数线索,对 ARM64 `libcoresdk.so` 的温度和校正逆向非常有帮助。
### 5.2 平滑器
通用平滑器函数大约位于 `0x1800011a0`
- mode=1:当前 f20 实例使用,逐帧复制输入,不是多帧 EMA。
- mode=2:两帧平均。
- mode=4:累计平均,当前 ref 启动阶段使用。
对象:
```text
dev+0x41ee0ref 平滑器对象
dev+0x41ef0ref 实际 uint16 缓冲指针
dev+0x41f10f20 平滑器对象
dev+0x41f20f20 实际 uint16 缓冲指针
dev+0x41fd8ref 相关 mode,实测为 4
dev+0x41fdcf20 相关 mode,实测为 1
dev+0x41fe0:后续可选处理模式,实测为 1
```
### 5.3 官方参考时序
启动帧计数和参数实测:
```text
0x2d78 = 4
0x2d88 = 5
0x2d8c = 4
0x2d90 = 1800
0x2d94 = 250
```
启动早期的 `c620 -> 0x41ee0` 推帧会形成 ref。正常处理帧不会每帧重新采集整幅 ref。FFC 会切换 type=1 校准帧,官方应用在这段时间冻结显示。
### 5.4 官方 NUC 查表
`0x180017200` 的关键反汇编已经确认:
```c
d2 = ((int)f20[i] - (int)ref[i]) >> 1;
seg = 0;
while (seg < nsegs - 1 && d2 > threshold[i][seg])
seg++;
gain = gainoff[seg][i].gain;
off = gainoff[seg][i].off;
out = off + ((gain * d2) >> 12);
out = clamp(out, 0, 65535);
```
实测:
```text
nsegs = 3
每像素 threshold 数 = 2
每段每像素是一个 uint16 gain + 一个 uint16 off
gain/off 表总大小 = 3 × 19200 × 4 = 230400 字节
threshold 实际需要 = 2 × 19200 × 2 = 76800 字节
shift = dev+0x11c = 12
```
本工程通过修复后的 `tsdk_pair2.c` 抓取 pair_000 表,并用 PowerShell 离线复算:
```text
官方 raw 与表公式重建的平均绝对误差约 0.118 counts
绝大多数像素完全一致
少量最大误差约 900 counts,来自后续盲元补偿尚未复刻
```
这是当前最可靠的官方 NUC 复刻证据。
### 5.5 NUC 表生成
相关函数:
```text
0x180016ae0:按 dev+0x54 传感器温度选择端点区间
0x180016dd0threshold 的 signed Q12 分段插值
0x180016f10gain/off 的 unsigned Q12 分段插值
0x18000c760:把表重建分成多个 chunk 逐步写入
```
端点来自 DDT/配置,不来自当前 live、ref 或场景。官方表在启动重建和 FFC 后重建阶段变化;同一个重建组内的连续普通帧通常相同。当前 demo3 使用一组静态官方表,因此 FFC 后和传感器温度区间变化时还不完全等价。
### 5.6 NUC 后处理
`0x180017330` 不是全帧 3×3 模糊,而是固定记录表驱动的盲元/坏点补偿:
- 只处理 `dev+0x41878` 指向的固定记录。
- 原地修改 `dev+0x270`
- 访问邻域像素并平均或按固定类型替换。
- 没有场景历史,也不负责整幅图去鬼影。
`0x18001e920` 可能是输出 temporal filter,但当前 `dev+0x41fe0=1` 时实测路径跳过,不能把它当成官方当前画面的主要鬼影来源。
### 5.7 窗口、灰度和调色板
- 官方窗口字段约为 `dev+0x4202c` / `dev+0x42030`
- 静态背景最小跨度约 624 counts,即半宽约 312。
- 有热目标时窗口会动态扩大。
- `dev+0x4284c` 有 1024 项灰度 LUT。
- `dev+0xb18` 有 256×4 BGR 调色板。
- 同帧重建实验已经证明窗口和 LUT 是当前帧确定性映射,不保存上一帧历史,显示层不是大片鬼影的主要来源。
### 5.8 官方温度
demo3 采用已从官方提取的 T2E 表:
```text
temp_mC = T2E[3 * nuc - C]
C 约为 5797,实际会话相关
```
主要代码在 `counts_to_temp_mc()`。T2E 数据在:
- `csdk/include/mag160c_official_t2e.h`
- `analysis/t2e_table.json`
- `analysis/official_t2e_table.txt`
## 6. 当前 demo3 代码思路
### 6.1 输入和坏点
`decode_live()`
1. 从第二次 bulk read 的 `data[0]` 解析 19200 个小端 `uint16`
2. 如果启用固定坏点表则执行拓扑填充;当前 `BADMAP_ENABLE=0`,避免动态场景坏图钉在屏幕坐标。
3. 执行 `correct_zero_pixels(g_live)`,修复原始零值。
### 6.2 参考采集
- 启动 FFC 后等待基线稳定。
- `REF_INIT_N=12` 帧采集。
- 每像素收集样本并做排序和中间 50% 平均。
- 结果放入 `g_ref_mura`
- `g_ref_mura` 同时承担固定 mura 图案和启动场景基线,这是当前低温残影的根本风险之一。
### 6.3 官方表加载
`load_official_nuc_tables()` 从程序工作目录加载:
```text
mag160c_official_nuc_gain.bin
mag160c_official_nuc_thr.bin
```
`official_nuc_value()` 按官方公式选择每像素 segment 并计算输出。
### 6.4 全局偏置
`calibrate_official_ref_bias()`
- 每帧抽取每 4 个像素中的一个。
- 对候选 scalar bias 计算官方 NUC 输出直方图中值。
- 二分搜索,使输出中值接近 `NUC_CENTER=9804`
- 使用 `g_ref_mura + g_official_ref_bias` 作为查表参考。
这个步骤只跟踪全局漂移,不应把局部场景写进逐像素参考。
### 6.5 当前 SBNUC 实验分支
当前 `SBNUC_ENABLE=1` 的实际更新约束:
- 正残差不更新参考。
- 运动期间创新门控保持约 6 帧,不更新参考。
- 负残差需要运动结束后连续 2 帧低于 `SB_RECOVER_T=16`
- 还要求该像素之前处于 `SB_HOT_RELEASE`,也就是曾经为热态、随后离开。
- 低温物体从头到尾的负残差不应进入自愈,避免移开后亮鬼影。
这仍是实验代码。旧的 `g_hot_hist``g_sb_prev_d``g_sb_innov_var` 等数组和注释中保留了多轮失败方案,后继者应在确认新方案后清理,而不是继续叠加状态。
### 6.6 设置参考按钮
当前按钮文字是 `Recenter bias`,对应 `WM_COMMAND``1004`
- 如果官方表可用,只重新计算全局 bias。
- 不再执行 `g_ref_mura[i] = g_live[i]`
- 这是刚修复的严重问题;旧行为会把当前物体温度写进参考,导致设置参考后所有物体趋于相同,挪开后才出现高温/低温差异。
- 没有官方表时才保留旧的 fallback 手动参考行为。
## 7. 已解决的问题
以下问题在历史实机验证中已经明显改善,不要在没有证据时推翻:
| 问题 | 原因 | 当前处理 |
|---|---|---|
| 颗粒感很重 | demo2 早期 NUC 斜率过大,曾使用接近 3 的斜率 | 当前线性 fallback 为 `NUC_GAIN=19`,官方表路径已接入。 |
| FFC 后颜色跳变 | FFC 后重新采集场景参考,把场景写进 ref | `REF_REINIT_AFTER_FFC=0`,type=1 不渲染,使用全局 rebase。 |
| 物体破碎、椒盐 | 固定窗口过窄 | 使用 P2..P98 自适应窗口和最小 624 跨度。 |
| mura 蒙层 | 常数参考或错误平场直接显示传感器固定纹理 | 启动采集 `g_ref_mura`,并使用逐像素官方 NUC 表。 |
| 中上固定遮蔽 | 动态 badmap 将场景结构钉在屏幕坐标 | `BADMAP_ENABLE=0`。 |
| 右下炫光 | 把盲元补偿误当全帧 3×3 blur | 删除错误整帧 blur 路径。 |
| 最高温点黑色 | 极值映射和零值处理不稳 | `idx >= hi` 饱和到 1023,保留零值修复。 |
| 黑洞完全不消失 | 参考冻结且没有任何失配处理 | 当前保留受限的 post-motion self-heal,但仍有速度/误判权衡。 |
| 设置参考后物体被抵消 | 按钮把当前 live 整帧覆盖到 ref | 改为 `Recenter bias`,不覆盖固定平场。 |
## 8. 已经尝试且效果不好的路线
### 8.1 单纯调 SBNUC 全局参数
尝试过:
- 去掉帧差条件。
- 放宽 `dd` 阈值。
- `alpha``1/64` 调到 `1/16`
- 统一使用更快负残差步长。
结果:黑洞在某些情况下改善,但小温差或低温物体会被参考吸收,移开后残影回来;过激时画面稳定性变差。
### 8.2 显示层去鬼影
尝试过:
- 最近热区 mask。
- motion history。
- recent hot mask。
- 显示层邻居替换。
- `deghost_nuc()`
结果:容易把真实目标抹掉,出现“有地方看不见”的副作用。当前调用被注释,后继者不要重新走这条路线。
### 8.3 复杂 MOG/自愈状态机
尝试过:
- 逐像素 warm/release 状态。
- 时域创新方差。
- 运动保持计数。
- persistent negative self-heal。
结果:可以在黑洞和鬼影之间移动问题。根本原因是一个 `g_ref_mura` 同时承载固定平场、场景基线和自适应背景,信息角色混在一起。
### 8.4 完全冻结参考
效果:热目标鬼影明显减少或消失。
副作用:当场景基线或局部低温发生变化时,旧位置会形成黑洞;黑洞自愈又可能吸收低温物体。这个折中证明需要拆分“固定传感器校正”和“场景背景模型”,而不是继续改一个 ref。
### 8.5 静态官方表
效果:比单一 `0.19 + comp` 更接近官方,热目标鬼影有明显改善。
局限:
- 表来自某次官方会话,FFC/传感器温度变化后官方会重新插值。
- `0x180017330` 固定盲元补偿没有完整接入。
- 表外的参考时序、内部 sensor temperature 和端点配置没有完全复刻。
- 当前静态表不是最终官方复刻。
## 9. 当前未解决问题和最重要的下一步
### 9.1 低温长停留残影
现象:
- 低温区域在画面中停留较长时间。
- 参考或负残差处理可能逐渐改变局部基线。
- 物体移动后出现残影,或者黑洞与亮鬼影互换。
最可能的根因:
1. demo3 的 `g_ref_mura` 仍然是“固定平场 + 启动场景”混合物。
2. post-motion self-heal 对“曾热后变冷”和“从头到尾低温”虽然已区分,但低对比度转换可能漏过状态阈值。
3. 官方表当前是静态表,FFC/温度区间变化没有实时重建。
4. 官方盲元补偿没有完全复刻,少量异常像素可能形成黑点或局部结构。
5. 官方的实际 ref 绝对偏置和 demo3 的 `g_ref_mura + scalar bias` 不是同一个参考定义。
### 9.2 优先任务 A:复刻官方动态 NUC 表
需要继续做:
1.`tsdk_pair2_fixed` 保存的 `b01/b02/b04/b05` 端点源表中确认 DDT 端点记录结构。
2. 找到 USB 原始帧或设备状态中对应 `dev+0x54` 的传感器温度。
3.`0x180016ae0``0x180016dd0``0x180016f10` 的 Q12 整数公式,在 demo3 中按温度插值生成 threshold/gain/off。
4. FFC 后重新生成表,但不重新把场景采入空间参考。
5. 用多温度、多次 FFC 的官方 `b03/b06``raw` 做逐像素回归。
### 9.3 优先任务 B:复刻官方盲元补偿
需要从官方活体捕获:
- `dev+0x41878` 固定记录表。
- `dev+0x41654` 对应的记录数量。
- 每条记录的目标像素、类型和邻域索引。
然后把 `0x180017330` 的原地邻域补偿接到官方 NUC 表输出后。不要使用由场景动态生成的 badmap。
### 9.4 优先任务 C:拆分参考角色
推荐最终数据结构:
```text
g_fixed_pattern[i] 只保存传感器固定空间校正
g_scene_reference[i] 可选、严格受状态控制的场景背景
g_global_ref_bias 全局传感器/FFC 漂移
g_official_nuc_table 官方温度配置表
```
当前 `g_ref_mura` 不应继续同时承担上述所有角色。
### 9.5 优先任务 D:受控实验数据
必须抓以下序列,每个序列至少 60 帧,最好包括 live/ref/raw/gain/thr/gray
1. 空背景稳定 10 秒。
2. 热目标进入、停留、离开、空背景恢复。
3. 冷目标进入、停留、离开、空背景恢复。
4. 小温差热目标重复移动。
5. FFC 前后同一目标序列。
对每个像素同时画:
```text
live
ref
live-ref
d2
official raw
demo3 raw
gray
```
不要只看 BMP。BMP 只能说明最终表现,不能定位残影是在 USB、ref、NUC、盲元补偿还是窗口阶段产生。
## 10. 环境安装和部署
### 10.1 当前开发环境
当前主要环境是 Windows PowerShell
```text
工作目录:C:\Project\MAG160C
MinGW GCCC:\mingw64\bin\gcc.exe
GCC 版本:曾使用 14.2.0
Python:用于 PDF、二进制和逆向辅助
JavaZulu 21,用 javap 查看 Android 类
Git:用于提交和远端同步
Git LFS:用于大型二进制
```
### 10.2 必装工具
建议安装或确认以下工具:
1. MinGW-w64,要求 `gcc``g++``ar``objdump``readelf``strings``dlltool``gendef` 可用。
2. Git。
3. Git LFS。
4. Python 3.10 或更新版本。
5. Java 21 或可用的 `javap`,仅在需要分析 Android JAR/AAR 时使用。
6. PowerShell 5.1 或 PowerShell 7。
7. 可选:CMake。当前环境中 `cmake` 不在 PATH,因此实际验证主要使用 GCC 直接命令。
8. 可选:Wireshark 4.6.7 和 USBPcap 1.5.4,用于 USB 抓包。
9. 可选:Zadig,用于切换 WinUSB/libusb-win32 驱动。
### 10.3 Python 逆向包
历史上使用过:
- `capstone`
- `pyelftools`
- `pdfplumber`
工程中已有 `.tools/python-revlibs/`,不要假设系统 Python 一定有这些包。需要时可以先检查:
```powershell
python --version
python -c "import capstone, elftools; print('逆向 Python 包可用')"
```
### 10.4 SDK 和 DLL
原厂文件已经随工程提供,通常不需要再次下载:
```text
IR_Camera_SDK-1.0.1\windows\windows\app\CoreSDKLib.dll
IR_Camera_SDK-1.0.1\windows\windows\app\ThermalSDK.dll
IR_Camera_SDK-1.0.1\windows\windows\app\libusb0.dll
IR_Camera_SDK-1.0.1\windows\windows\lib\x64\CoreSDKLib.dll
IR_Camera_SDK-1.0.1\windows\windows\lib\x64\ThermalSDK.dll
csdk\third_party\libusb\win64\libusb-1.0.dll
csdk\third_party\libusb\win64\libusb-1.0.x64.a
```
官方 `ThermalSDK.dll` 路径和 demo3 的 libusb-1.0 路径不要混用。官方程序通常依赖 `libusb0.dll`/libusb-win32demo3 使用 `libusb-1.0.dll` 和 MinGW 导入库。
### 10.5 驱动注意事项
曾经验证过的 Windows 组合:
- 原厂旧驱动签名在新 Windows 上可能失败。
- Zadig 安装 WinUSB 或 libusb-win32 后,设备才能被对应程序打开。
- 官方 DLL、TI 的 64 位 `libusb-1.0.dll`、WinUSB/libusb-win32 的组合行为不同。
- 不要在官方程序、`tsdk_pair2` 和 demo3 同时占用设备。
- 如果出现 `no channel`、STALL、设备不枚举,先停止所有程序并重新插拔 USB。
## 11. 构建和启动
### 11.1 demo3 当前编译命令
在 PowerShell 中执行:
```powershell
```
注意:命令只允许出现一次 `mag160c_error.c`。重复传入会出现 `multiple definition` 链接错误。
### 11.2 启动 demo3
```powershell
Stop-Process -Name mag160c_demo3 -Force -ErrorAction SilentlyContinue
Start-Process "C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe" -WorkingDirectory "C:\Project\MAG160C\build-artifacts"
```
官方 NUC 表文件必须和 exe 在同一个工作目录中:
```text
build-artifacts\mag160c_official_nuc_gain.bin
build-artifacts\mag160c_official_nuc_thr.bin
```
如果缺失,程序会退回旧的线性 NUC 路径,画面和残影表现不能与当前版本比较。
### 11.3 停止 demo3
```powershell
Stop-Process -Name mag160c_demo3 -Force -ErrorAction SilentlyContinue
```
必须先停止 demo3 才能运行官方 ThermalSDK 抓帧工具。
### 11.4 编译修复后的官方抓帧工具
`tsdk_pair2.c` 原来先保存真实指针表,后面又覆盖同名 `.gain/.thr`。当前修复版把后面的内联字段改存为 `.gain_inline/.thr_inline`
```powershell
```
### 11.5 官方抓帧
先确认输出目录父目录存在,再执行:
```powershell
New-Item -ItemType Directory -Path "C:\Project\MAG160C\analysis\pairs_recheck_20260811" -Force
Stop-Process -Name mag160c_demo3 -Force -ErrorAction SilentlyContinue
& "C:\Project\MAG160C\build-artifacts\tsdk_pair2_fixed.exe" "C:\Project\MAG160C\analysis\pairs_recheck_20260811" 12 6000
```
参数含义:
```text
参数 1:输出目录
参数 2:抓取 pair 数
参数 3:官方 SDK 初始化等待毫秒数
```
`tsdk_pair2.c` 当前会在约三分之一和三分之二位置触发 FFC,适合验证 FFC 表变化,不适合完全无干预的纯运动实验。要做低温残影实验,建议另写不自动触发 FFC 的 harness。
### 11.6 日志和图像
demo3 工作目录下:
```text
```
日志文件由程序重新启动时以写模式打开,重启会覆盖旧日志。要保留一轮实验,先复制到 `analysis/` 并改名。
## 12. C SDK 构建和验证
如果已经安装 CMake
```powershell
cmake -B build -S csdk
cmake --build build
ctest --test-dir build
```
当前机器没有 CMake 时,按照 `csdk/WINDOWS_TESTING.md` 使用 MinGW 直接编译。无硬件时可以验证:
```powershell
build-artifacts\csdk_cli_libusb.exe frame-test
build-artifacts\csdk_cli_libusb.exe temp-test
build-artifacts\csdk_cli_libusb.exe tcm-rotate 5
build-artifacts\csdk_cli_libusb.exe tcm-light green blink
build-artifacts\csdk_cli_libusb.exe ir-info
```
预期 TCM 编码结果示例:
```text
7e 00 07 85 02 77 00 01 00 05 7f
```
## 13. Git 和仓库维护
本工程原先只有空的 `.git` 目录,不是有效 Git 仓库。本次移交应初始化真实 Git 仓库并推送到:
```text
https://git.zxcli.top/zxc/MAG160C.git
```
仓库约 0.824 GB,包含大量 DLL、EXE、APK、PDF、PNG、BMP、抓帧和反汇编二进制。已准备 Git LFS 规则。提交前必须检查:
```powershell
```
不要把账号密码、访问令牌、私钥写入文档或代码。原厂 SDK 和 APK 可能受第三方许可限制,仓库接手者应确认仓库访问权限和内部使用范围。
## 14. 当前接手者的建议工作顺序
### 第一步:确认环境和版本
1. 阅读本文、`analysis/handoff_20260813.md``analysis/handoff_20260811_full.md`
2. 检查 `git status` 和远端分支,确认没有并行改动。
3. 检查设备 PID、驱动、DLL、表文件。
4. 编译并启动当前 demo3,保存一轮不移动时的日志。
### 第二步:验证当前路径是否真的加载官方表
1. 暂时把 `mag160c_official_nuc_gain.bin` 改名,启动一次并记录 fallback 画面。
2. 恢复表文件,再启动并记录官方表画面。
3. 比较 `demo3_diag.txt``g_sb_shift`、NUC 统计和 BMP。
4. 不要用缺失表文件的 fallback 版本评价当前算法。
### 第三步:做官方和 demo3 同帧采集
1. 停 demo3。
2. 用修复后的官方工具抓取至少 60 帧,不要自动触发 FFC。
3. 保存 f20、ref、raw、gain、thr、gray、window、blind compensation 记录。
4. 用脚本逐像素对比官方 raw 和 demo3 raw。
### 第四步:优先修官方动态表和盲元补偿
不要先改调色板、窗口、显示层。官方证据已经说明这两个阶段没有上一帧历史,低温残影优先查 ref、gain/off、threshold、FFC 表重建和盲元补偿。
## 15. 给下一位 AI 的接手提示词
下面的提示词可以直接复制给下一位 AI。它要求 AI 先理解工程,再动手,不要从头重做,也不要反复尝试已经失败的显示层补丁。
```text
你现在接手 C:\Project\MAG160C 的 MAG160C 热像仪逆向工程。
设备:MAG160C160x120USB VID 0x833C,常见 PID 0x0001。
主程序:C:\Project\MAG160C\csdk\tools\mag160c_demo3.c
输出程序:C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe
官方 DLLIR_Camera_SDK-1.0.1\windows\windows\app\CoreSDKLib.dll 和 ThermalSDK.dll
远端仓库:https://git.zxcli.top/zxc/MAG160C.git
严格执行以下步骤:
1. 先读:
- 交接_完整逆向工程说明_20260811.md
- analysis/handoff_20260813.md
- analysis/handoff_20260811_full.md
- analysis/protocol_spec.md
- csdk/tools/mag160c_demo3.c
- csdk/tools/tsdk_pair2.c
2. 再检查:
- git status --short --branch
- build-artifacts/mag160c_official_nuc_gain.bin
- build-artifacts/mag160c_official_nuc_thr.bin
- analysis/pairs_recheck_20260811/
- analysis/disasm/
3. 先理解已经确认的官方事实:
- EP 0x03 是命令 OUTEP 0x82 是响应 INEP 0x81 是帧流。
- 帧 marker 是 0x1BB1B11B,像素从帧内 +0x1c 开始,160x120 uint16 LE。
- f20 平滑器 dev+0x41f10 当前 mode=1,正常帧基本直接复制,不是隐藏 EMA。
- ref 在 dev+0x41ef0,启动/FFC 平滑器 mode=4 形成,正常显示帧不逐帧重采集。
- NUC 0x180017200 使用 d2=(f20-ref)>>1、每像素两个 signed threshold、三段 gain/off、Q12 乘法和 clamp。
- 0x180017330 是固定盲元邻域补偿,不是全帧 3x3 blur。
- 0x18001e920 当前 mode=1 通常跳过,不要假设官方有开启的 temporal filter。
- 官方 gain/off/threshold 表由传感器温度、DDT 配置和 FFC 重建生成,不读取 scene/live/ref。
4. 当前 demo3 的真实状态:
- 已接入一组官方活体抓取的静态 gain/off/threshold 表。
- 用输出域中值反求全局 ref bias。
- SBNUC 只允许曾经热、后来负残差的像素自愈;低温从头到尾的负残差不应更新参考。
- 显示层 deghost_nuc() 不调用,BADMAP_ENABLE=0,窗口、LUT、palette 不要随意改。
- 低温区域长时间停留仍有残影,说明问题尚未解决。
5. 当前首要研究目标:
- 查清低温静止目标的残影是在 raw/live、ref、d2、官方 gain/off、盲元补偿还是窗口前产生。
- 不能只看 BMP;必须逐像素保存和比较 live/f20/ref/d2/raw/gray。
- 建立官方和 demo3 的 60 帧以上同场景数据集,覆盖热目标和冷目标。
- 复刻官方 gain/off/threshold 温度端点插值和 FFC 后表重建。
- 复刻固定盲元补偿记录表,不能用场景动态 badmap 代替。
6. 已经失败、不要盲目重复的路线:
- 显示层 motion history、recent hot mask、邻域替换。
- 单纯把 SBNUC 全局 alpha 调快。
- 把所有负残差都快速写回参考。
- 把所有正负残差都用一个 MOG 参考吸收。
- 随意修改窗口、调色板、FFC 周期和 BADMAP_ENABLE。
7. 修改原则:
- 先保留当前已验证的官方查表、窗口、LUT、palette 和 USB 链路。
- 只在有反汇编或抓帧证据的地方修改。
- 不回退用户已经确认有效的修复。
- 所有手工编辑使用 apply_patch。
- 修改后使用用户给出的 GCC 命令编译,并启动 demo3 让用户实测。
- 不要声称“已修复”,除非有用户实机反馈或可复现的同帧数据证据。
8. 编译命令:
gcc -O2 -w -DMAG160C_STATIC -I"C:\Project\MAG160C\csdk\third_party\libusb\win64" -I"C:\Project\MAG160C\csdk\include" -I"C:\Project\MAG160C\csdk\src" -o "C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe" "C:\Project\MAG160C\csdk\tools\mag160c_demo3.c" "C:\Project\MAG160C\csdk\src\mag160c_display.c" "C:\Project\MAG160C\csdk\src\mag160c_error.c" "C:\Project\MAG160C\csdk\third_party\libusb\win64\libusb-1.0.x64.a" -lgdi32 -luser32
9. 启动命令:
Stop-Process -Name mag160c_demo3 -Force -ErrorAction SilentlyContinue
Start-Process "C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe" -WorkingDirectory "C:\Project\MAG160C\build-artifacts"
10. 你的第一条回复不要直接提方案。先返回:
- 你读过的文件。
- 当前官方链路理解。
- 当前 demo3 链路理解。
- 低温残影的证据缺口。
- 下一轮最小可验证实验。
然后再开始修改或抓帧。
```
## 16. 交接结束条件
下一位接手者在以下条件都满足前,不应把项目标记为完成:
1. 官方和 demo3 的 60 帧以上同帧 raw/ref/NUC 对比完成。
2. 热目标和冷目标的进入、停留、离开都没有明显残影。
3. FFC 前后表重建、窗口和显示冻结行为与官方一致。
4. 固定盲元补偿记录已复刻,异常零点和少量极端 outlier 消失。
5. 不依赖显示层遮罩,不牺牲真实目标,不产生黑洞。
6. 用户在实机上确认低温和小温差场景都达到可接受效果。
+4 -4
View File
@@ -1,10 +1,10 @@
# MAG160C 官方 MAG-Cx 完整逆向结论(2026-09-10jadx + Ghidra 全量解包)
> 产物来源:
> - Java 层:`analysis/jadx_magcx/`jadx 1.5.1 反编译官方普通版 MAG-Cx.apk 全量源码)
> - Native 层:`analysis/ida/export/ghidra_dump/libcxsdk_decomp.txt`
> - Java 层:`analysis/sdk_re/android_app/jadx_magcx/`jadx 1.5.1 反编译官方普通版 MAG-Cx.apk 全量源码)
> - Native 层:`analysis/sdk_re/android_app/libcxsdk_decomp.txt`
> Ghidra 11.3.2 headless 全量反编译 lib/armeabi/libcxsdk.so1290 函数)
> - libcoresdk(arm64) 反编译已在 `analysis/ida/export/ghidra_dump/`(专业版/网络路径)
> - libcoresdk(arm64) 反编译已在 `analysis/sdk_re/android_app/`(专业版/网络路径)
> - 本文结论全部来自以上反编译源码,与真机日志交叉验证(vivo V2509A, Android 16)。
## 1. USB 协议权威版(以官方 Java UsbCommunication.java 为准)
@@ -96,7 +96,7 @@ fpaTemp 在尾 +8devType0/5/6/3),camTemp=fpaTemp-500。
## 3. 工具与环境(2026-09-10 本机)
- jadx 1.5.1C:\Tools\jadx-1.5.1(反编译产物 C:\Tools\jadx-out,已拷贝入库
analysis/jadx_magcx/
analysis/sdk_re/android_app/jadx_magcx/
- Ghidra 11.3.2C:\Tools\ghidra_11.3.2_PUBLIC;工程 C:\Tools\ghidra_proj\MagCX
全量反编译脚本 C:\Tools\ghidra_scripts_user\DumpAllDecomp.java
- 重跑命令(PowerShell/cmd):

Some files were not shown because too many files have changed in this diff Show More