/* tsdk_pair3: same-frame capture of official pipeline outputs + full NUC/ * window/ref state, for replicating CoreSDKLib.dll in the C SDK. * Extends tsdk_pair2 with: * - per-frame shutter (metadata+0x2c), frame counters * - config dump: 0x24, 0x48, 0x4c, 0x54/0x58/0x5c/0x60, 0x47944..0x47954, * 0x11c, DDT header fields (0x41340..0x41880), endpoint arrays * - DDT file copy (path from dev+0x4134c) * - stats (0x42010..0x42024) + window (0x4202c/0x42030) + LUT1024 + hist */ #define _WIN32_WINNT 0x0601 #include #include #include #include #include #include typedef void (CALLBACK *INewIRFrame)(const unsigned char *, int, int, int); typedef bool (CALLBACK *fn_Start_t)(void); typedef void (CALLBACK *fn_Stop_t)(void); typedef void (CALLBACK *fn_SetNewIRFrameDelegate_t)(INewIRFrame); typedef void (CALLBACK *fn_SetTempBoundary_t)(double, double, double); typedef void (CALLBACK *fn_SetUnitMode_t)(int); typedef void (CALLBACK *fn_ReadTemperatureAtPoint_t)(int, int, unsigned char *); typedef int (CALLBACK *MAG_GetOutputBMPdata_t)(int, unsigned char **, void **); typedef int (CALLBACK *MAG_GetOutputBMPdataRGB24_t)(int, unsigned char *, int, int); typedef int (CALLBACK *MAG_GetTemperatureData_Raw_t)(int, unsigned int *, int, int); typedef int (CALLBACK *MAG_GetOutputColorBardata_t)(int, void **, void **); typedef int (CALLBACK *MAG_TriggerFFC_t)(int, int); static volatile int g_frames; static unsigned char g_cb[320 * 240 * 3]; static int g_cbw, g_cbh; static const char *g_dir = "."; static void CALLBACK onIR(const unsigned char *buf, int w, int h, int ch) { if (buf && w > 0 && h > 0 && ch == 3) { memcpy(g_cb, buf, (size_t)w * h * ch); g_cbw = w; g_cbh = h; } g_frames++; } static void save(const char *name, const void *buf, size_t n) { char path[512]; snprintf(path, sizeof(path), "%s\\%s", g_dir, name); FILE *f = fopen(path, "wb"); if (f) { fwrite(buf, 1, n, f); fclose(f); } } static int is_ro_ptr(const void *p, size_t n) { if (!p) return 0; MEMORY_BASIC_INFORMATION mi; if (VirtualQuery(p, &mi, sizeof(mi)) == 0) return 0; if (mi.State != MEM_COMMIT) return 0; if (mi.Protect == PAGE_NOACCESS) return 0; if ((size_t)((const char *)p - (const char *)mi.BaseAddress) + n > mi.RegionSize) return 0; return 1; } int main(int argc, char **argv) { int npairs = 24; int start_delay = 6000; double tb[3] = {30.0, 44.0, 37.0}; if (argc > 1) g_dir = argv[1]; if (argc > 2) npairs = atoi(argv[2]); if (argc > 3) start_delay = atoi(argv[3]); if (argc > 4) tb[0] = atof(argv[4]); if (argc > 5) tb[1] = atof(argv[5]); if (argc > 6) tb[2] = atof(argv[6]); SetDllDirectoryA("C:\\Project\\MAG160C\\IR_Camera_SDK-1.0.1\\windows\\windows\\app"); HMODULE t = LoadLibraryA("ThermalSDK.dll"); HMODULE c = LoadLibraryA("CoreSDKLib.dll"); printf("T=%p C=%p\n", (void*)t, (void*)c); if (!t || !c) return 1; fn_Start_t T_Start = (fn_Start_t)GetProcAddress(t, "Start"); fn_Stop_t T_Stop = (fn_Stop_t)GetProcAddress(t, "Stop"); fn_SetNewIRFrameDelegate_t T_Set = (fn_SetNewIRFrameDelegate_t)GetProcAddress(t, "SetNewIRFrameDelegate"); fn_SetTempBoundary_t T_Bound = (fn_SetTempBoundary_t)GetProcAddress(t, "SetTempBoundary"); fn_SetUnitMode_t T_Unit = (fn_SetUnitMode_t)GetProcAddress(t, "SetUnitMode"); fn_ReadTemperatureAtPoint_t T_Temp = (fn_ReadTemperatureAtPoint_t)GetProcAddress(t, "ReadTemperatureAtPoint"); MAG_GetOutputBMPdata_t G_Gray = (MAG_GetOutputBMPdata_t)GetProcAddress(c, "MAG_GetOutputBMPdata"); MAG_GetOutputBMPdataRGB24_t G_RGB = (MAG_GetOutputBMPdataRGB24_t)GetProcAddress(c, "MAG_GetOutputBMPdataRGB24"); MAG_GetTemperatureData_Raw_t G_TempRaw = (MAG_GetTemperatureData_Raw_t)GetProcAddress(c, "MAG_GetTemperatureData_Raw"); MAG_GetOutputColorBardata_t G_Bar = (MAG_GetOutputColorBardata_t)GetProcAddress(c, "MAG_GetOutputColorBardata"); if (!T_Start || !T_Set || !G_Gray || !G_RGB) { printf("missing export\n"); return 2; } if (T_Unit) T_Unit(0); if (T_Bound) T_Bound(tb[0], tb[1], tb[2]); T_Set(onIR); printf("Start()...\n"); fflush(stdout); BOOL ok = T_Start(); printf("Start=%d\n", ok); fflush(stdout); printf("warming %d ms...\n", start_delay); fflush(stdout); Sleep(start_delay); unsigned char *gray = NULL; void *hdr = NULL; int chan = -1; for (int i = 0; i < 8; ++i) { int rc = G_Gray(i, &gray, &hdr); printf("chan %d: rc=%d gray=%p hdr=%p\n", i, rc, (void*)gray, (void*)hdr); if (rc && gray && hdr) { chan = i; break; } } if (chan < 0) { printf("no channel\n"); T_Stop(); return 3; } unsigned char *dev = (unsigned char *)hdr - 0xaf0; int w = *(int *)(dev + 0xaf4); int h = *(int *)(dev + 0xaf8); int n = w * h; int nw = w / 2, nh = h / 2; int nn = nw * nh; printf("dev=%p w=%d h=%d\n", (void*)dev, w, h); /* ---- config dump ---- */ FILE *cfg = fopen("config.txt", "w"); if (cfg) { fprintf(cfg, "dev24=%d dev48=%d dev4c=%d dev54=%d dev58=%d dev5c=%d dev60=%d\n", *(int *)(dev + 0x24), *(int *)(dev + 0x48), *(int *)(dev + 0x4c), *(int *)(dev + 0x54), *(int *)(dev + 0x58), *(int *)(dev + 0x5c), *(int *)(dev + 0x60)); fprintf(cfg, "11c=%d 41340=%d 41344=%d 41348=%d 4134c=%ls\n", *(int *)(dev + 0x11c), *(int *)(dev + 0x41340), *(int *)(dev + 0x41344), *(int *)(dev + 0x41348), (wchar_t *)(dev + 0x4134c)); fprintf(cfg, "41558=%d 41554=%d 4155c=%d 41560=%d 47944=%d 47948=%d 4794c=%d 47950=%d 47954=%d 47938=%d\n", *(int *)(dev + 0x41558), *(int *)(dev + 0x41554), *(int *)(dev + 0x4155c), *(int *)(dev + 0x41560), *(int *)(dev + 0x47944), *(int *)(dev + 0x47948), *(int *)(dev + 0x4794c), *(int *)(dev + 0x47950), *(int *)(dev + 0x47954), *(int *)(dev + 0x47938)); int cnt = *(int *)(dev + 0x41558); if (cnt < 1 || cnt > 64) cnt = 1; fprintf(cfg, "T:"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x41564 + i * 4)); fprintf(cfg, "\nB:"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x415b4 + i * 4)); fprintf(cfg, "\nC:"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x41604 + i * 4)); fprintf(cfg, "\nD(blind cnt):"); for (int i = 0; i < cnt - 1; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x41654 + i * 4)); fprintf(cfg, "\nloaded:"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x416b8 + i * 4)); fprintf(cfg, "\noffsets(41708):"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x41708 + i * 4)); fprintf(cfg, "\nthr_off(41758):"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x41758 + i * 4)); fprintf(cfg, "\nblind_off(417a8):"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x417a8 + i * 4)); fprintf(cfg, "\nblind_off2(417f4):"); for (int i = 0; i < cnt; ++i) fprintf(cfg, " %d", *(int *)(dev + 0x417f4 + i * 4)); fprintf(cfg, "\nbases: 416a0=%p 416a8=%p 416b0=%p\n", *(void **)(dev + 0x416a0), *(void **)(dev + 0x416a8), *(void **)(dev + 0x416b0)); fprintf(cfg, "41840=%d 41848=%p 41850=%p 41858=%p 41860=%p 41868=%p 41870=%p 41878=%p\n", *(int *)(dev + 0x41840), *(void **)(dev + 0x41848), *(void **)(dev + 0x41850), *(void **)(dev + 0x41858), *(void **)(dev + 0x41860), *(void **)(dev + 0x41868), *(void **)(dev + 0x41870), *(void **)(dev + 0x41878)); fprintf(cfg, "41f0c=%d 41f3c=%d 41fdc=%d 41fe0=%d 41fe4=%d 41fe8=%d\n", *(int *)(dev + 0x41f0c), *(int *)(dev + 0x41f3c), *(int *)(dev + 0x41fdc), *(int *)(dev + 0x41fe0), *(int *)(dev + 0x41fe4), *(int *)(dev + 0x41fe8)); fprintf(cfg, "2d47=%d 2d86=%d 2d78=%d 2d88=%d 2d8c=%d 2d90=%d 2d94=%d 2d98=%d 2d9c=%d\n", *(char *)(dev + 0x2d47), *(short *)(dev + 0x2d86), *(int *)(dev + 0x2d78), *(int *)(dev + 0x2d88), *(int *)(dev + 0x2d8c), *(int *)(dev + 0x2d90), *(int *)(dev + 0x2d94), *(int *)(dev + 0x2d98), *(int *)(dev + 0x2d9c)); fprintf(cfg, "47940=%d 44c50=%d 44c60=%d 44c64=%d 44c68=%d 42010=%d 42014=%d\n", *(int *)(dev + 0x47940), *(int *)(dev + 0x44c50), *(int *)(dev + 0x44c60), *(int *)(dev + 0x44c64), *(int *)(dev + 0x44c68), *(int *)(dev + 0x42010), *(int *)(dev + 0x42014)); fprintf(cfg, "ctrl: 28=%d 30=%d 44=%d 88=%d 8c=%d 90=%d 230=%d 234=%d\n", *(int *)(dev + 0x28), *(int *)(dev + 0x30), *(int *)(dev + 0x44), *(int *)(dev + 0x88), *(int *)(dev + 0x8c), *(int *)(dev + 0x90), *(int *)(dev + 0x230), *(int *)(dev + 0x234)); fprintf(cfg, "temporal: 41f40+30=%d +34=%d +38=%d +3c=%d 41f68=%p 41f70=%d 41f74=%d 41f7c=%d\n", *(int *)(dev + 0x41f40 + 0x30), *(int *)(dev + 0x41f40 + 0x34), *(int *)(dev + 0x41f40 + 0x38), *(int *)(dev + 0x41f40 + 0x3c), *(void **)(dev + 0x41f68), *(int *)(dev + 0x41f70), *(int *)(dev + 0x41f74), *(int *)(dev + 0x41f7c)); fprintf(cfg, "smo2: 41f90+30=%d +38=%d +3c=%d 41fa8=%p 41fb0=%d 41fb4=%d 41fbc=%d\n", *(int *)(dev + 0x41f90 + 0x30), *(int *)(dev + 0x41f90 + 0x38), *(int *)(dev + 0x41f90 + 0x3c), *(void **)(dev + 0x41fa8), *(int *)(dev + 0x41fb0), *(int *)(dev + 0x41fb4), *(int *)(dev + 0x41fbc)); fprintf(cfg, "flags: 4203c=%d 42038=%d 42040=%d 42044=%d 42004=%d 41ffc=%d 41fdc=%d\n", *(int *)(dev + 0x4203c), *(int *)(dev + 0x42038), *(int *)(dev + 0x42040), *(int *)(dev + 0x42044), *(int *)(dev + 0x42004), *(int *)(dev + 0x41ffc), *(int *)(dev + 0x41fdc)); fprintf(cfg, "bufs: 270=%p 278=%p 280=%p 288=%p 290=%p 2a0=%p 2b0=%p 2c8=%p\n", *(void **)(dev + 0x270), *(void **)(dev + 0x278), *(void **)(dev + 0x280), *(void **)(dev + 0x288), *(void **)(dev + 0x290), *(void **)(dev + 0x2a0), *(void **)(dev + 0x2b0), *(void **)(dev + 0x2c8)); fprintf(cfg, "win: 42018=%d 4201c=%d 44c48=%d 44c64=%d 44c68=%d\n", *(int *)(dev + 0x42018), *(int *)(dev + 0x4201c), *(int *)(dev + 0x44c48), *(int *)(dev + 0x44c64), *(int *)(dev + 0x44c68)); fclose(cfg); } /* copy the DDT file */ wchar_t *ddtp = (wchar_t *)(dev + 0x4134c); if (ddtp && *ddtp) { printf("DDT path: %ls\n", ddtp); fflush(stdout); char apath[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, ddtp, -1, apath, MAX_PATH, NULL, NULL); FILE *sf = fopen(apath, "rb"); if (sf) { fseek(sf, 0, SEEK_END); long sz = ftell(sf); fseek(sf, 0, SEEK_SET); void *buf = malloc(sz); if (buf) { fread(buf, 1, sz, sf); save("official.ddt", buf, sz); printf("DDT copied: %ld bytes\n", sz); free(buf); } fclose(sf); } else printf("DDT file not readable: %s\n", apath); } else printf("no DDT path\n"); fflush(stdout); unsigned char *rgb = malloc((size_t)n * 3); unsigned short *raw = malloc((size_t)nn * 2); unsigned char *pal = malloc(256 * 4); unsigned int *t32 = malloc((size_t)n * 4); unsigned char *g2 = malloc((size_t)n); MAG_TriggerFFC_t G_FFC = (MAG_TriggerFFC_t)GetProcAddress(c, "MAG_TriggerFFC"); int prev = g_frames; for (int k = 0; k < npairs; ++k) { if (G_FFC && k == npairs / 3) { G_FFC(chan, 1); Sleep(1500); prev = g_frames; } if (G_FFC && k == 2 * npairs / 3) { G_FFC(chan, 0); Sleep(1500); prev = g_frames; } int t0 = GetTickCount(); while (g_frames == prev && GetTickCount() - t0 < 3000) Sleep(5); prev = g_frames; Sleep(2); memcpy(g2, gray, (size_t)n); int rcr = G_RGB(chan, rgb, n * 3, 1); unsigned short *rawp = *(unsigned short **)(dev + 0x270); memcpy(raw, rawp, (size_t)nn * 2); memcpy(pal, dev + 0xb18, 256 * 4); int rct = G_TempRaw ? G_TempRaw(chan, t32, nn * 4, 1) : 0; char base[64]; snprintf(base, sizeof(base), "pair_%03d", k); char nm[128]; snprintf(nm, sizeof(nm), "%s.gray", base); save(nm, g2, (size_t)n); snprintf(nm, sizeof(nm), "%s.rgb", base); save(nm, rgb, (size_t)n * 3); snprintf(nm, sizeof(nm), "%s.raw", base); save(nm, raw, (size_t)nn * 2); snprintf(nm, sizeof(nm), "%s.pal", base); save(nm, pal, 256 * 4); snprintf(nm, sizeof(nm), "%s.cbrgb", base); save(nm, g_cb, (size_t)g_cbw * g_cbh * 3); if (rct) { snprintf(nm, sizeof(nm), "%s.t32", base); save(nm, t32, (size_t)nn * 4); } /* frame metadata + shutter: the frame buffer base at dev+0x50 */ unsigned char *fb = *(unsigned char **)(dev + 0x50); if (!is_ro_ptr(fb, 0x4c + 38400 + 8)) fb = NULL; unsigned int fcnt = *(unsigned int *)(dev + 8); unsigned int shutter = fb ? *(unsigned int *)(fb + 0x2c) : 0; unsigned int shutter2 = fb ? *(unsigned int *)(fb + 0x28) : 0; unsigned int ftype = fb ? *(unsigned int *)(fb + 0x40) : 0; unsigned int dev54 = *(unsigned int *)(dev + 0x54); unsigned int dev5c = *(unsigned int *)(dev + 0x5c); unsigned int dev60 = *(unsigned int *)(dev + 0x60); unsigned int win_hi = *(unsigned int *)(dev + 0x4202c); unsigned int win_lo = *(unsigned int *)(dev + 0x42030); unsigned int s_max = *(unsigned int *)(dev + 0x42010); unsigned int s_min = *(unsigned int *)(dev + 0x42014); unsigned int s_mean = *(unsigned int *)(dev + 0x42018); unsigned int s_std = *(unsigned int *)(dev + 0x4201c); unsigned int sel = *(unsigned int *)(dev + 0x41840); snprintf(nm, sizeof(nm), "%s.meta", base); { unsigned int v[16] = {fcnt, shutter, shutter2, ftype, dev54, dev5c, dev60, win_hi, win_lo, s_max, s_min, s_mean, s_std, sel, *(unsigned int *)(dev + 0x41558), *(unsigned int *)(dev + 0x41554)}; FILE *f = fopen(nm, "wb"); if (f) { fwrite(v, 4, 16, f); fclose(f); } } /* window + stats + lut + hist */ snprintf(nm, sizeof(nm), "%s.win", base); { FILE *f = fopen(nm, "wb"); if (f) { unsigned int v[8] = {win_hi, win_lo, s_max, s_min, s_mean, s_std, *(unsigned int *)(dev + 0x42020), *(unsigned int *)(dev + 0x42024)}; fwrite(v, 4, 8, f); fclose(f); } } snprintf(nm, sizeof(nm), "%s.lut", base); save(nm, dev + 0x4284c, 1024); snprintf(nm, sizeof(nm), "%s.hist", base); save(nm, dev + 0x4204c, 256 * 4); snprintf(nm, sizeof(nm), "%s.h1024", base); save(nm, dev + 0x42c4c, 1024 * 4); snprintf(nm, sizeof(nm), "%s.cdf", base); save(nm, dev + 0x43c4c, 1024 * 4); /* ref + f20 */ unsigned short *refp = *(unsigned short **)(dev + 0x41ef0); if (is_ro_ptr(refp, (size_t)nn * 2)) { snprintf(nm, sizeof(nm), "%s.ref", base); save(nm, refp, (size_t)nn * 2); } void *f20 = *(void **)(dev + 0x41f20); if (is_ro_ptr(f20, (size_t)nn * 2)) { snprintf(nm, sizeof(nm), "%s.f20", base); save(nm, f20, (size_t)nn * 2); } /* full working tables + endpoints (sel/sel+1) */ { int nsegs = *(int *)(dev + 0x41554); int c5c = *(int *)(dev + 0x4155c); size_t thr_sz = (size_t)(nsegs - 1) * nn * 2 + (size_t)c5c; size_t g_sz = (size_t)nsegs * nn * 4; void *p; p = *(void **)(dev + 0x41848); if (is_ro_ptr(p, thr_sz)) { snprintf(nm, sizeof(nm), "%s.thr0", base); save(nm, p, thr_sz); } p = *(void **)(dev + 0x41850); if (is_ro_ptr(p, thr_sz)) { snprintf(nm, sizeof(nm), "%s.thr1", base); save(nm, p, thr_sz); } p = *(void **)(dev + 0x41858); if (is_ro_ptr(p, (size_t)(nsegs - 1) * nn * 2)) { snprintf(nm, sizeof(nm), "%s.thrw", base); save(nm, p, (size_t)(nsegs - 1) * nn * 2); } p = *(void **)(dev + 0x41860); if (is_ro_ptr(p, g_sz)) { snprintf(nm, sizeof(nm), "%s.g0", base); save(nm, p, g_sz); } p = *(void **)(dev + 0x41868); if (is_ro_ptr(p, g_sz)) { snprintf(nm, sizeof(nm), "%s.g1", base); save(nm, p, g_sz); } p = *(void **)(dev + 0x41870); if (is_ro_ptr(p, g_sz)) { snprintf(nm, sizeof(nm), "%s.gw", base); save(nm, p, g_sz); } p = *(void **)(dev + 0x41878); if (is_ro_ptr(p, 0x1000)) { int sel2 = *(int *)(dev + 0x41840); int bc = sel2 >= 0 && sel2 < 64 ? *(int *)(dev + 0x41654 + (size_t)sel2 * 4) : 0; if (bc > 0 && bc < 100000 && is_ro_ptr(p, (size_t)bc * 40)) { snprintf(nm, sizeof(nm), "%s.blind", base); save(nm, p, (size_t)bc * 40); printf(" blind records: %d\n", bc); } } } /* frame header bytes + tail (raw USB frame, from the parser buffer) */ { unsigned char *rb = *(unsigned char **)(dev + 0x2d20); if (is_ro_ptr(rb, 0x1c + 0x9600 + 0x100)) { snprintf(nm, sizeof(nm), "%s.fhdr", base); save(nm, rb, 0x40); snprintf(nm, sizeof(nm), "%s.ftail", base); save(nm, rb + 0x1c + 0x9600, 0x100); } } printf("[%d] fcnt=%u shutter=%u/%u type=%u dev54=%u dev5c=%u dev60=%u sel=%u win=[%u,%u] stats=(%u..%u m%u s%u)\n", k, fcnt, shutter, shutter2, ftype, dev54, dev5c, dev60, sel, win_hi, win_lo, s_max, s_min, s_mean, s_std); fflush(stdout); Sleep(100); } T_Stop(); printf("done\n"); return 0; }