- 逆向:Ghidra/IDA 全量反编译 CoreSDKLib.dll/ThermalSDK.dll/libthermalSDK.so/ libcoresdk.so(ARM64)/libmagcore.so,导出 analysis/ida/export/ - 解码官方渲染管线:DDT 校准表加载->快门端点选择->Q12 插值->ref(4x type1 帧 均值)->NUC 查表->盲元补偿->窗口->LUT1024 重建->2x 升采样->调色板 - 逐像素验证:NUC+盲元 0/19200、插值 0 误差、2x 0/76800、窗口一致 - demo3 v5:完整复刻官方管线(含 DDT 解析、FFC 状态机、快门温度驱动), 修复 load_ddt 表错位导致的零像素问题 - 鬼影根因分析写入 analysis/reverse_20260813_full.md - 心跳/恢复机制:analysis/session_state.md + tools/resume_rev.ps1 - 新增 tsdk_pair3 增强采集工具;历史工具归档 csdk/tools/legacy/; 根目录抓帧残留删除,历史文档归档 analysis/history/ - csdk/README.md 完整使用文档;.gitignore/.gitattributes 补 LFS 规则
122 lines
4.1 KiB
C
122 lines
4.1 KiB
C
/* Save raw type=0 frames (bin) + frame metadata for offline analysis.
|
|
* Usage: mag160c_frame_dump <nframes> <outdir>
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
#include <libusb.h>
|
|
|
|
#define W 160
|
|
#define H 120
|
|
|
|
static libusb_context *g_ctx;
|
|
static libusb_device_handle *g_h;
|
|
|
|
static int sendcmd(unsigned magic, unsigned param, int len) {
|
|
unsigned char cmd[8] = {0};
|
|
cmd[0] = (unsigned char)(magic);
|
|
cmd[1] = (unsigned char)(magic >> 8);
|
|
cmd[2] = (unsigned char)(magic >> 16);
|
|
cmd[3] = (unsigned char)(magic >> 24);
|
|
if (len >= 8) {
|
|
cmd[4] = (unsigned char)(param);
|
|
cmd[5] = (unsigned char)(param >> 8);
|
|
cmd[6] = (unsigned char)(param >> 16);
|
|
cmd[7] = (unsigned char)(param >> 24);
|
|
}
|
|
int xfer = 0;
|
|
if (libusb_bulk_transfer(g_h, 0x03, cmd, len, &xfer, 2000)) return -1;
|
|
unsigned char resp[0x1000];
|
|
if (libusb_bulk_transfer(g_h, 0x82, resp, sizeof(resp), &xfer, 2000)) return -1;
|
|
return 0;
|
|
}
|
|
|
|
static int read_frame(unsigned char *frame, unsigned *type) {
|
|
unsigned char hdr[64];
|
|
static unsigned prev = 0xffffffff;
|
|
int xfer = 0;
|
|
if (libusb_bulk_transfer(g_h, 0x81, hdr, sizeof(hdr), &xfer, 200) && xfer < 28) return 0;
|
|
if (xfer < 28) return 0;
|
|
unsigned m = (unsigned)hdr[0] | ((unsigned)hdr[1] << 8) |
|
|
((unsigned)hdr[2] << 16) | ((unsigned)hdr[3] << 24);
|
|
if (m != 0x1bb1b11b) return 0;
|
|
unsigned c = (unsigned)hdr[4] | ((unsigned)hdr[5] << 8) |
|
|
((unsigned)hdr[6] << 16) | ((unsigned)hdr[7] << 24);
|
|
if (c == prev) return 0;
|
|
prev = c;
|
|
if (libusb_bulk_transfer(g_h, 0x81, frame, 40000, &xfer, 200) || xfer < 38400) return 0;
|
|
*type = (unsigned)hdr[12];
|
|
return 1;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
int nframes = argc > 1 ? atoi(argv[1]) : 60;
|
|
const char *dir = argc > 2 ? argv[2] : ".";
|
|
if (libusb_init(&g_ctx)) return 1;
|
|
libusb_device **list = NULL;
|
|
ssize_t cnt = libusb_get_device_list(g_ctx, &list);
|
|
for (ssize_t i = 0; i < cnt && !g_h; ++i) {
|
|
struct libusb_device_descriptor d;
|
|
libusb_get_device_descriptor(list[i], &d);
|
|
if (d.idVendor == 0x833c) libusb_open(list[i], &g_h);
|
|
}
|
|
libusb_free_device_list(list, 1);
|
|
if (!g_h) { printf("no device\n"); return 1; }
|
|
libusb_set_configuration(g_h, 2);
|
|
libusb_set_configuration(g_h, 1);
|
|
if (libusb_claim_interface(g_h, 0)) return 1;
|
|
sendcmd(0x6bb6b66b, 0, 4);
|
|
sendcmd(0x6bb6b66c, 0, 4);
|
|
sendcmd(0x6bb6b66f, 0, 4);
|
|
sendcmd(0x6bb6b672, 0, 8);
|
|
Sleep(100);
|
|
sendcmd(0x6bb6b672, 0, 8);
|
|
Sleep(300);
|
|
sendcmd(0x6bb6b673, 0, 4);
|
|
Sleep(700);
|
|
|
|
unsigned char frame[40000];
|
|
unsigned type = 1;
|
|
int drained = 0;
|
|
for (int i = 0; i < 120; ++i) {
|
|
if (!read_frame(frame, &type)) { Sleep(10); continue; }
|
|
drained++;
|
|
if (drained == 10) {
|
|
sendcmd(0x6bb6b672, 1, 8);
|
|
Sleep(200);
|
|
}
|
|
if (type == 0) break;
|
|
}
|
|
if (type != 0) { printf("no type=0 stream\n"); return 3; }
|
|
|
|
char path[512];
|
|
FILE *meta = NULL;
|
|
snprintf(path, sizeof(path), "%s/meta.txt", dir);
|
|
meta = fopen(path, "w");
|
|
for (int n = 0; n < nframes; ++n) {
|
|
if (!read_frame(frame, &type)) { Sleep(10); n--; continue; }
|
|
snprintf(path, sizeof(path), "%s/f%03d.bin", dir, n);
|
|
FILE *f = fopen(path, "wb");
|
|
if (f) { fwrite(frame + 28, 1, 38400, f); fclose(f); }
|
|
if (meta) {
|
|
long s = 0; unsigned mn = 65535, mx = 0;
|
|
for (int i = 0; i < W * H; ++i) {
|
|
unsigned v = (unsigned)frame[i * 2 + 28] | ((unsigned)frame[i * 2 + 29] << 8);
|
|
s += v; if (v < mn) mn = v; if (v > mx) mx = v;
|
|
}
|
|
fprintf(meta, "%d %u %ld %.0f %u %u\n", n, type, s,
|
|
(double)s / (W * H), mn, mx);
|
|
}
|
|
}
|
|
if (meta) fclose(meta);
|
|
printf("dumped %d frames to %s\n", nframes, dir);
|
|
Sleep(300);
|
|
libusb_clear_halt(g_h, 0x03);
|
|
libusb_clear_halt(g_h, 0x82);
|
|
sendcmd(0x6bb6b674, 0, 4);
|
|
libusb_close(g_h);
|
|
libusb_exit(g_ctx);
|
|
return 0;
|
|
}
|