From df6c6dd4447505261620891f78f4e5e997088751 Mon Sep 17 00:00:00 2001 From: ZXCLI Date: Fri, 14 Aug 2026 16:52:52 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E6=A4=8D=E5=AE=98=E6=96=B9=E9=99=84?= =?UTF-8?q?=E5=8A=A0=E7=8E=AF=E8=8A=82=E5=85=A8=E9=83=A8=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=EF=BC=9A=E5=B8=A7=E5=B7=AE/=E9=9A=94=E8=A1=8C=E5=B9=B3?= =?UTF-8?q?=E6=BB=91/gray=E8=A6=86=E7=9B=96/Nx=E5=8D=87=E9=87=87=E6=A0=B7?= =?UTF-8?q?=EF=BC=88=E7=BC=96=E8=AF=91=E5=BC=80=E5=85=B3+=E6=8C=89?= =?UTF-8?q?=E9=94=AE=E6=B5=8B=E8=AF=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OFF_IMPL_230: 帧差调整 0x175a0 逐行移植(0x278 官方 NULL 时 no-op) - OFF_IMPL_41FE8: 隔行平滑 0x184f0(2x)/0x18660(4x) 逐行翻译(4相位加权插值) - OFF_IMPL_30: gray 覆盖路径——0x17c40 manual 逐行翻译(8x8窗口4x4采样 对比度增强累积→gray);0x17770 auto 双边滤波结构移植(官方空间权重表 在 .data 被裁剪无法提取,用标准高斯核近似,文档注明) - OFF_IMPL_UPSCALE: Nx 升采样 4x/8x(2x 已验证模式推广,线性插值+边缘外推) - 运行时按键切换:0=41fe8 模式、8=0x230、9=0x30 模式 - 验证:默认版无回归;全开版运行正常,41fe8=1 平滑生效(nuc std 250→95) - 文档:csdk/README 开关说明、csdk/README 验证状态更新 --- .../keyfuncs_decomp_CoreSDKLib.dll.txt | 643 ++++++++++++++++++ build-artifacts/mag160c_demo3.exe | 2 +- csdk/README.md | 30 +- csdk/tools/mag160c_demo3.c | 341 +++++++++- 4 files changed, 1013 insertions(+), 3 deletions(-) diff --git a/analysis/ida/export/ghidra_dump/keyfuncs_decomp_CoreSDKLib.dll.txt b/analysis/ida/export/ghidra_dump/keyfuncs_decomp_CoreSDKLib.dll.txt index 90f1e7e..825a106 100644 --- a/analysis/ida/export/ghidra_dump/keyfuncs_decomp_CoreSDKLib.dll.txt +++ b/analysis/ida/export/ghidra_dump/keyfuncs_decomp_CoreSDKLib.dll.txt @@ -5238,3 +5238,646 @@ undefined8 FUN_18001c670(longlong param_1,uint *param_2,uint param_3) ================================================================== +### ADDR 180019b30 FUNC 180019b30 (816 bytes) name=FUN_180019b30 + +void FUN_180019b30(longlong param_1) + +{ + byte bVar1; + byte bVar2; + int iVar3; + ulonglong uVar4; + undefined1 uVar5; + int iVar6; + uint uVar7; + undefined1 *puVar8; + undefined1 *_Dst; + uint uVar9; + uint uVar10; + uint uVar11; + void *_Src; + byte *pbVar12; + byte *pbVar13; + byte *pbVar14; + uint uVar15; + byte *pbVar16; + uint local_res8; + + _Src = *(void **)(param_1 + 0x2a0); + local_res8 = 0; + uVar9 = 0; + puVar8 = (undefined1 *) + (((ulonglong)(uint)((*(int *)(param_1 + 0x41fcc) + 3) * *(int *)(param_1 + 0x41fc8)) - + (ulonglong)(uint)((*(int *)(param_1 + 0x41fc0) + 8) * (*(int *)(param_1 + 0x41fc4) + 1)) + ) + *(longlong *)(param_1 + 0x220)); + _Dst = puVar8; + if (*(int *)(param_1 + 0x41fc4) != 0) { + do { + memcpy(_Dst,_Src,(ulonglong)*(uint *)(param_1 + 0x41fc0)); + iVar6 = (uint)*(byte *)((ulonglong)(*(int *)(param_1 + 0x41fc0) - 1) + (longlong)_Src) * 2 - + (uint)*(byte *)((ulonglong)(*(int *)(param_1 + 0x41fc0) - 2) + (longlong)_Src); + if (iVar6 < 0x100) { + uVar5 = (undefined1)iVar6; + if (iVar6 < 0) { + uVar5 = 0; + } + } + else { + uVar5 = 0xff; + } + uVar9 = uVar9 + 1; + _Dst[*(uint *)(param_1 + 0x41fc0)] = uVar5; + _Src = (void *)((longlong)_Src + (ulonglong)*(uint *)(param_1 + 0x41fc0)); + _Dst = _Dst + (*(uint *)(param_1 + 0x41fc0) + 8); + } while (uVar9 < *(uint *)(param_1 + 0x41fc4)); + } + uVar4 = (ulonglong)(*(int *)(param_1 + 0x41fc0) + 8); + pbVar12 = _Dst + -uVar4; + pbVar13 = pbVar12 + -uVar4; + for (iVar6 = *(int *)(param_1 + 0x41fc0) + 1; iVar6 != 0; iVar6 = iVar6 + -1) { + bVar1 = *pbVar12; + bVar2 = *pbVar13; + pbVar13 = pbVar13 + 1; + pbVar12 = pbVar12 + 1; + iVar3 = (uint)bVar1 * 2 - (uint)bVar2; + if (iVar3 < 0x100) { + uVar5 = (undefined1)iVar3; + if (iVar3 < 0) { + uVar5 = 0; + } + } + else { + uVar5 = 0xff; + } + *_Dst = uVar5; + _Dst = _Dst + 1; + } + if (*(int *)(param_1 + 0x41fc4) != 0) { + do { + iVar6 = *(int *)(param_1 + 0x41fc0); + pbVar13 = (byte *)((ulonglong)(*(int *)(param_1 + 0x41fc8) * local_res8 * 4) + + *(longlong *)(param_1 + 0x220)); + pbVar12 = puVar8 + (iVar6 + 8) * local_res8; + if (iVar6 != 0) { + pbVar16 = pbVar13 + 2; + do { + bVar1 = *pbVar12; + uVar10 = (uint)bVar1; + uVar7 = (uint)pbVar12[1]; + uVar15 = (uint)pbVar12[(ulonglong)*(uint *)(param_1 + 0x41fc0) + 8]; + uVar11 = (uint)pbVar12[(ulonglong)*(uint *)(param_1 + 0x41fc0) + 9]; + pbVar12 = pbVar12 + 1; + *pbVar13 = bVar1; + uVar9 = uVar10 * 3 + uVar15; + pbVar16[-1] = (byte)(uVar10 * 3 + uVar7 >> 2); + *pbVar16 = (byte)(uVar7 + uVar10 >> 1); + pbVar16[1] = (byte)(uVar7 * 3 + uVar10 >> 2); + pbVar14 = pbVar13 + *(uint *)(param_1 + 0x41fc8); + *pbVar14 = (byte)(uVar9 >> 2); + pbVar14[1] = (byte)(uVar11 + (uVar9 + uVar7) * 3 >> 4); + pbVar14[2] = (byte)(uVar11 + (uVar7 + uVar10) * 3 + uVar15 >> 3); + pbVar14[3] = (byte)(uVar15 + (uVar7 * 3 + uVar11 + uVar10) * 3 >> 4); + pbVar14 = pbVar13 + (uint)(*(int *)(param_1 + 0x41fc8) * 2); + *pbVar14 = (byte)(uVar15 + uVar10 >> 1); + pbVar14[1] = (byte)(uVar11 + (uVar15 + uVar10) * 3 + uVar7 >> 3); + pbVar14[2] = (byte)(uVar11 + uVar15 + uVar7 + uVar10 >> 2); + pbVar14[3] = (byte)(uVar15 + (uVar11 + uVar7) * 3 + uVar10 >> 3); + pbVar14 = pbVar13 + (uint)(*(int *)(param_1 + 0x41fc8) * 3); + *pbVar14 = (byte)(uVar15 * 3 + uVar10 >> 2); + pbVar13 = pbVar13 + 4; + pbVar16 = pbVar16 + 4; + pbVar14[1] = (byte)(uVar7 + (uVar15 * 3 + uVar11 + uVar10) * 3 >> 4); + pbVar14[2] = (byte)(uVar7 + (uVar11 + uVar15) * 3 + uVar10 >> 3); + iVar6 = iVar6 + -1; + pbVar14[3] = (byte)(uVar10 + (uVar15 + uVar11 * 3 + uVar7) * 3 >> 4); + } while (iVar6 != 0); + } + local_res8 = local_res8 + 1; + } while (local_res8 < *(uint *)(param_1 + 0x41fc4)); + } + return; +} + + +================================================================== + +### ADDR 180019e60 FUNC 180019e60 (2276 bytes) name=FUN_180019e60 + +void FUN_180019e60(longlong param_1) + +{ + uint uVar1; + uint uVar2; + int iVar3; + uint uVar4; + uint uVar5; + byte bVar6; + byte bVar7; + int iVar8; + ulonglong uVar9; + undefined1 uVar10; + int iVar11; + int iVar12; + int iVar13; + uint uVar14; + undefined1 *puVar15; + undefined1 *_Dst; + void *_Src; + uint uVar16; + uint uVar17; + uint uVar18; + uint uVar19; + byte *pbVar20; + byte *pbVar21; + int iVar22; + byte *pbVar23; + byte *pbVar24; + int iVar25; + int iVar26; + uint uVar27; + int iVar28; + uint uVar29; + int iVar30; + int local_90; + uint local_8c; + + _Src = *(void **)(param_1 + 0x2a0); + local_8c = 0; + uVar16 = 0; + puVar15 = (undefined1 *) + (((ulonglong)(uint)((*(int *)(param_1 + 0x41fcc) + 3) * *(int *)(param_1 + 0x41fc8)) - + (ulonglong) + (uint)((*(int *)(param_1 + 0x41fc0) + 8) * (*(int *)(param_1 + 0x41fc4) + 1))) + + *(longlong *)(param_1 + 0x220)); + _Dst = puVar15; + if (*(int *)(param_1 + 0x41fc4) != 0) { + do { + memcpy(_Dst,_Src,(ulonglong)*(uint *)(param_1 + 0x41fc0)); + iVar11 = (uint)*(byte *)((ulonglong)(*(int *)(param_1 + 0x41fc0) - 1) + (longlong)_Src) * 2 - + (uint)*(byte *)((ulonglong)(*(int *)(param_1 + 0x41fc0) - 2) + (longlong)_Src); + if (iVar11 < 0x100) { + uVar10 = (undefined1)iVar11; + if (iVar11 < 0) { + uVar10 = 0; + } + } + else { + uVar10 = 0xff; + } + uVar16 = uVar16 + 1; + _Dst[*(uint *)(param_1 + 0x41fc0)] = uVar10; + _Src = (void *)((longlong)_Src + (ulonglong)*(uint *)(param_1 + 0x41fc0)); + _Dst = _Dst + (*(uint *)(param_1 + 0x41fc0) + 8); + } while (uVar16 < *(uint *)(param_1 + 0x41fc4)); + } + uVar9 = (ulonglong)(*(int *)(param_1 + 0x41fc0) + 8); + pbVar20 = _Dst + -uVar9; + pbVar23 = pbVar20 + -uVar9; + for (iVar11 = *(int *)(param_1 + 0x41fc0) + 1; iVar11 != 0; iVar11 = iVar11 + -1) { + bVar6 = *pbVar20; + bVar7 = *pbVar23; + pbVar23 = pbVar23 + 1; + pbVar20 = pbVar20 + 1; + iVar8 = (uint)bVar6 * 2 - (uint)bVar7; + if (iVar8 < 0x100) { + uVar10 = (undefined1)iVar8; + if (iVar8 < 0) { + uVar10 = 0; + } + } + else { + uVar10 = 0xff; + } + *_Dst = uVar10; + _Dst = _Dst + 1; + } + if (*(int *)(param_1 + 0x41fc4) != 0) { + do { + local_90 = *(int *)(param_1 + 0x41fc0); + pbVar20 = (byte *)((ulonglong)(*(int *)(param_1 + 0x41fc8) * local_8c * 8) + + *(longlong *)(param_1 + 0x220)); + if (local_90 != 0) { + pbVar23 = pbVar20 + 6; + pbVar24 = puVar15 + (local_90 + 8) * local_8c; + do { + uVar14 = (uint)pbVar24[1]; + uVar18 = (uint)*pbVar24; + uVar27 = (uint)pbVar24[(ulonglong)*(uint *)(param_1 + 0x41fc0) + 8]; + uVar29 = (uint)pbVar24[(ulonglong)*(uint *)(param_1 + 0x41fc0) + 9]; + uVar16 = uVar18 * 7 + uVar14; + iVar8 = uVar18 * 3; + uVar19 = uVar14 + uVar18; + uVar4 = iVar8 + uVar14; + *pbVar20 = *pbVar24; + pbVar23[-5] = (byte)(uVar16 >> 3); + pbVar23[-4] = (byte)(uVar4 >> 2); + pbVar23[-3] = (byte)(uVar18 * 0x28 + uVar14 * 0x18 >> 6); + pbVar23[-2] = (byte)(uVar19 >> 1); + pbVar23[-1] = (byte)(uVar18 * 0x18 + uVar14 * 0x28 >> 6); + uVar17 = uVar14 * 3 + uVar18; + *pbVar23 = (byte)(uVar17 >> 2); + uVar1 = uVar14 * 7 + uVar18; + pbVar23[1] = (byte)(uVar1 >> 3); + uVar2 = uVar18 * 7 + uVar27; + pbVar21 = pbVar20 + *(uint *)(param_1 + 0x41fc8); + iVar3 = uVar27 * 3; + *pbVar21 = (byte)(uVar2 >> 3); + pbVar21[1] = (byte)((uVar2 + uVar14) * 7 + uVar29 >> 6); + iVar11 = uVar14 * 7 + uVar29; + pbVar21[2] = (byte)(uVar4 * 7 + iVar3 + uVar29 >> 5); + iVar13 = uVar29 * 3; + pbVar21[3] = (byte)(iVar11 * 3 + uVar2 * 5 >> 6); + pbVar21[4] = (byte)(uVar19 * 7 + uVar29 + uVar27 >> 4); + uVar5 = iVar8 + uVar27; + pbVar21[5] = (byte)(iVar11 * 5 + uVar2 * 3 >> 6); + pbVar21[6] = (byte)(uVar17 * 7 + iVar13 + uVar27 >> 5); + pbVar21[7] = (byte)((uVar18 + iVar11) * 7 + uVar27 >> 6); + pbVar21 = pbVar20 + (uint)(*(int *)(param_1 + 0x41fc8) * 2); + *pbVar21 = (byte)(uVar5 >> 2); + iVar11 = uVar14 * 3 + uVar29; + pbVar21[1] = (byte)(uVar5 * 7 + uVar14 * 3 + uVar29 >> 5); + pbVar21[2] = (byte)(uVar29 + (uVar14 + uVar5) * 3 >> 4); + pbVar21[3] = (byte)(uVar5 * 10 + iVar11 * 6 >> 6); + pbVar21[4] = (byte)(uVar29 + uVar19 * 3 + uVar27 >> 3); + pbVar21[5] = (byte)(uVar5 * 6 + iVar11 * 10 >> 6); + pbVar21[6] = (byte)(uVar27 + (iVar11 + uVar18) * 3 >> 4); + pbVar21[7] = (byte)(iVar11 * 7 + iVar8 + uVar27 >> 5); + pbVar21 = pbVar20 + (uint)(*(int *)(param_1 + 0x41fc8) * 3); + iVar11 = uVar27 * 7 + uVar29; + *pbVar21 = (byte)(uVar18 * 0x28 + uVar27 * 0x18 >> 6); + iVar22 = (uVar29 + uVar18) * 0xf; + iVar30 = uVar29 + iVar3; + pbVar21[1] = (byte)(iVar11 * 3 + uVar16 * 5 >> 6); + iVar28 = uVar27 + uVar29; + iVar25 = (uVar27 + uVar14) * 0xf; + pbVar21[2] = (byte)(uVar4 * 10 + iVar30 * 6 >> 6); + iVar26 = iVar13 + uVar27; + pbVar21[3] = (byte)(uVar18 * 0x19 + iVar25 + uVar29 * 9 >> 6); + pbVar21[4] = (byte)(uVar19 * 0x14 + iVar28 * 0xc >> 6); + iVar8 = uVar29 * 7 + uVar27; + pbVar21[5] = (byte)(uVar27 * 9 + uVar14 * 0x19 + iVar22 >> 6); + pbVar21[6] = (byte)((uVar14 * 3 + uVar18) * 10 + iVar26 * 6 >> 6); + pbVar21[7] = (byte)(iVar8 * 3 + uVar1 * 5 >> 6); + pbVar21 = pbVar20 + (uint)(*(int *)(param_1 + 0x41fc8) << 2); + uVar19 = uVar27 + uVar18; + *pbVar21 = (byte)(uVar19 >> 1); + pbVar21[1] = (byte)(uVar19 * 7 + uVar29 + uVar14 >> 4); + iVar12 = uVar29 + uVar14; + pbVar21[2] = (byte)(uVar29 + uVar19 * 3 + uVar14 >> 3); + pbVar21[3] = (byte)(uVar19 * 0x14 + iVar12 * 0xc >> 6); + pbVar21[4] = (byte)(iVar28 + uVar14 + uVar18 >> 2); + pbVar21[5] = (byte)(uVar19 * 0xc + iVar12 * 0x14 >> 6); + pbVar21[6] = (byte)(uVar27 + iVar12 * 3 + uVar18 >> 3); + pbVar21[7] = (byte)(iVar12 * 7 + uVar27 + uVar18 >> 4); + pbVar21 = pbVar20 + (uint)(*(int *)(param_1 + 0x41fc8) * 5); + *pbVar21 = (byte)(uVar18 * 0x18 + uVar27 * 0x28 >> 6); + pbVar21[1] = (byte)(iVar11 * 5 + uVar16 * 3 >> 6); + pbVar21[2] = (byte)((uVar18 * 3 + uVar14) * 6 + iVar30 * 10 >> 6); + uVar16 = uVar18 + iVar3; + pbVar21[3] = (byte)(uVar14 * 9 + iVar22 + uVar27 * 0x19 >> 6); + pbVar21[4] = (byte)((uVar14 + uVar18) * 0xc + iVar28 * 0x14 >> 6); + pbVar21[5] = (byte)(uVar18 * 9 + uVar29 * 0x19 + iVar25 >> 6); + pbVar21[6] = (byte)((uVar14 * 3 + uVar18) * 6 + iVar26 * 10 >> 6); + pbVar21[7] = (byte)(iVar8 * 5 + uVar1 * 3 >> 6); + pbVar21 = pbVar20 + (uint)(*(int *)(param_1 + 0x41fc8) * 6); + *pbVar21 = (byte)(uVar16 >> 2); + pbVar21[1] = (byte)(uVar16 * 7 + iVar13 + uVar14 >> 5); + iVar13 = iVar13 + uVar14; + pbVar21[2] = (byte)(uVar14 + (iVar30 + uVar18) * 3 >> 4); + pbVar21[3] = (byte)(uVar16 * 10 + iVar13 * 6 >> 6); + pbVar21[4] = (byte)(uVar14 + iVar28 * 3 + uVar18 >> 3); + pbVar21[5] = (byte)(uVar16 * 6 + iVar13 * 10 >> 6); + pbVar21[6] = (byte)(uVar18 + (iVar26 + uVar14) * 3 >> 4); + pbVar21[7] = (byte)(iVar13 * 7 + iVar3 + uVar18 >> 5); + iVar3 = uVar29 * 7 + uVar14; + pbVar21 = pbVar20 + (uint)(*(int *)(param_1 + 0x41fc8) * 7); + uVar16 = uVar18 + uVar27 * 7; + *pbVar21 = (byte)(uVar16 >> 3); + pbVar21[1] = (byte)((iVar11 + uVar18) * 7 + uVar14 >> 6); + pbVar21[2] = (byte)(iVar30 * 7 + uVar18 * 3 + uVar14 >> 5); + pbVar21[3] = (byte)(iVar3 * 3 + uVar16 * 5 >> 6); + pbVar21[4] = (byte)(iVar28 * 7 + uVar14 + uVar18 >> 4); + pbVar21[5] = (byte)(iVar3 * 5 + uVar16 * 3 >> 6); + pbVar20 = pbVar20 + 8; + pbVar23 = pbVar23 + 8; + local_90 = local_90 + -1; + pbVar21[6] = (byte)(iVar26 * 7 + uVar14 * 3 + uVar18 >> 5); + pbVar21[7] = (byte)((iVar8 + uVar14) * 7 + uVar18 >> 6); + pbVar24 = pbVar24 + 1; + } while (local_90 != 0); + } + local_8c = local_8c + 1; + } while (local_8c < *(uint *)(param_1 + 0x41fc4)); + } + return; +} + + +================================================================== + +### ADDR 1800191b0 FUNC 1800191b0 (1423 bytes) name=FUN_1800191b0 + +/* WARNING: Type propagation algorithm not settling */ + +byte * FUN_1800191b0(longlong param_1) + +{ + int iVar1; + byte bVar2; + byte bVar3; + byte bVar4; + byte bVar5; + byte bVar6; + byte bVar7; + uint uVar8; + byte *pbVar9; + ulonglong uVar10; + undefined1 uVar11; + int iVar12; + int iVar13; + undefined1 *puVar14; + undefined1 *_Dst; + uint uVar15; + uint uVar16; + uint uVar17; + byte *pbVar18; + int iVar19; + byte *pbVar20; + int iVar21; + byte *pbVar22; + byte *pbVar23; + uint uVar24; + uint uVar25; + uint uVar26; + uint uVar27; + uint local_res10; + uint local_res18; + uint local_res20; + + pbVar18 = *(byte **)(param_1 + 0x2a0); + uVar8 = *(int *)(param_1 + 0x41fc0) + 8; + pbVar9 = (byte *)(ulonglong)uVar8; + local_res18 = 0; + uVar15 = 0; + puVar14 = (undefined1 *) + (((ulonglong)(uint)((*(int *)(param_1 + 0x41fcc) + 3) * *(int *)(param_1 + 0x41fc8)) - + (ulonglong)((*(int *)(param_1 + 0x41fc4) + 1) * uVar8)) + + *(longlong *)(param_1 + 0x220)); + _Dst = puVar14; + if (*(int *)(param_1 + 0x41fc4) != 0) { + do { + memcpy(_Dst,pbVar18,(ulonglong)*(uint *)(param_1 + 0x41fc0)); + iVar12 = (uint)pbVar18[*(int *)(param_1 + 0x41fc0) - 1] * 2 - + (uint)pbVar18[*(int *)(param_1 + 0x41fc0) - 2]; + if (iVar12 < 0x100) { + uVar11 = (undefined1)iVar12; + if (iVar12 < 0) { + uVar11 = 0; + } + } + else { + uVar11 = 0xff; + } + uVar15 = uVar15 + 1; + _Dst[*(uint *)(param_1 + 0x41fc0)] = uVar11; + pbVar9 = (byte *)(ulonglong)*(uint *)(param_1 + 0x41fc0); + pbVar18 = pbVar18 + (longlong)pbVar9; + _Dst = _Dst + (*(uint *)(param_1 + 0x41fc0) + 8); + } while (uVar15 < *(uint *)(param_1 + 0x41fc4)); + } + uVar10 = (ulonglong)(*(int *)(param_1 + 0x41fc0) + 8); + pbVar18 = _Dst + -uVar10; + pbVar20 = pbVar18 + -uVar10; + for (iVar12 = *(int *)(param_1 + 0x41fc0) + 1; iVar12 != 0; iVar12 = iVar12 + -1) { + bVar2 = *pbVar18; + bVar3 = *pbVar20; + pbVar20 = pbVar20 + 1; + pbVar18 = pbVar18 + 1; + uVar8 = (uint)bVar2 * 2 - (uint)bVar3; + if ((int)uVar8 < 0x100) { + pbVar9 = (byte *)(ulonglong)uVar8; + if ((int)uVar8 < 0) { + pbVar9 = (byte *)0x0; + } + } + else { + pbVar9 = (byte *)0xff; + } + *_Dst = (char)pbVar9; + _Dst = _Dst + 1; + } + if (*(int *)(param_1 + 0x41fc4) != 0) { + uVar10 = 0; + local_res20 = 0; + do { + local_res10 = *(uint *)(param_1 + 0x41fc0); + pbVar20 = puVar14 + (local_res10 + 8) * local_res18; + pbVar9 = (byte *)((ulonglong)local_res10 * 0xaaaaaaab & 0xffffffff); + pbVar18 = (byte *)((ulonglong)(uint)((int)(uVar10 / 3) * *(int *)(param_1 + 0x41fc8)) + + *(longlong *)(param_1 + 0x220)); + local_res10 = local_res10 / 3; + if (local_res10 != 0) { + pbVar9 = pbVar20 + 2; + pbVar23 = pbVar18 + 3; + do { + bVar2 = pbVar9[-1]; + bVar3 = *pbVar9; + bVar4 = pbVar9[1]; + bVar5 = *pbVar20; + uVar10 = (ulonglong)*(uint *)(param_1 + 0x41fc0); + iVar19 = (uint)bVar3 + (uint)bVar2 * 4; + bVar6 = pbVar20[uVar10 + 10]; + bVar7 = pbVar20[uVar10 + 9]; + uVar27 = (uint)bVar7; + uVar26 = (uint)pbVar20[uVar10 + 8]; + iVar13 = (uint)bVar5 * 0x19a; + uVar8 = (uint)pbVar20[uVar10 + 0xb]; + iVar21 = (uint)bVar2 + (uint)bVar3 * 4; + *pbVar18 = bVar5 / 1; + uVar15 = (uint)bVar6; + pbVar23[-2] = (byte)((uint)bVar2 * 0x267 + iVar13 >> 10); + pbVar23[-1] = (byte)((uint)(iVar19 * 0xcd) >> 10); + *pbVar23 = (byte)((uint)(iVar21 * 0xcd) >> 10); + pbVar23[1] = (byte)((uint)bVar3 * 0x267 + (uint)bVar4 * 0x19a >> 10); + pbVar22 = pbVar18 + *(uint *)(param_1 + 0x41fc8); + iVar12 = (uint)bVar7 * 4; + *pbVar22 = (byte)(uVar26 * 0x267 + iVar13 >> 10); + iVar1 = (uint)bVar6 * 4; + pbVar22[1] = (byte)((uVar26 + bVar2) * 0xf6 + uVar27 * 0x171 + (uint)bVar5 * 0xa4 >> 10); + pbVar22[2] = (byte)((iVar12 + (uint)bVar6) * 0x7b + iVar19 * 0x52 >> 10); + pbVar22[3] = (byte)((iVar1 + uVar27) * 0x7b + iVar21 * 0x52 >> 10); + pbVar22[4] = (byte)((uVar8 + bVar3) * 0xf6 + uVar15 * 0x171 + (uint)bVar4 * 0xa4 >> 10); + pbVar22 = pbVar20 + (*(int *)(param_1 + 0x41fc0) * 2 + 0x10); + uVar25 = (uint)pbVar22[2]; + uVar17 = (uint)*pbVar22; + uVar16 = (uint)pbVar22[1]; + uVar24 = (uint)pbVar22[3]; + iVar12 = iVar12 + uVar16; + pbVar22 = pbVar18 + (uint)(*(int *)(param_1 + 0x41fc8) * 2); + iVar13 = uVar17 + uVar26 * 4; + *pbVar22 = (byte)((uint)(iVar13 * 0xcd) >> 10); + iVar1 = iVar1 + uVar25; + pbVar22[1] = (byte)((uint)(iVar12 * 0x7b + iVar13 * 0x52) >> 10); + pbVar22[2] = (byte)((uVar25 + (iVar12 + uVar15) * 4) * 0x29 >> 10); + iVar12 = uVar26 + uVar17 * 4; + pbVar22[3] = (byte)((uVar16 + (iVar1 + uVar27) * 4) * 0x29 >> 10); + pbVar22[4] = (byte)((uVar24 + uVar8 * 4) * 0x52 + iVar1 * 0x7b >> 10); + iVar13 = uVar16 * 4 + uVar25; + pbVar22 = pbVar18 + (uint)(*(int *)(param_1 + 0x41fc8) * 3); + *pbVar22 = (byte)((uint)(iVar12 * 0xcd) >> 10); + iVar1 = uVar25 * 4 + uVar16; + pbVar22[1] = (byte)((uVar16 * 4 + uVar27) * 0x7b + iVar12 * 0x52 >> 10); + pbVar22[2] = (byte)((uVar15 + (iVar13 + uVar27) * 4) * 0x29 >> 10); + pbVar22[3] = (byte)((uVar27 + (iVar1 + uVar15) * 4) * 0x29 >> 10); + pbVar22[4] = (byte)((uVar8 + uVar24 * 4) * 0x52 + (uVar25 * 4 + uVar15) * 0x7b >> 10); + pbVar22 = pbVar20 + (*(int *)(param_1 + 0x41fc0) * 3 + 0x18); + bVar2 = *pbVar22; + uVar8 = (uint)pbVar22[1]; + uVar15 = (uint)pbVar22[2]; + bVar3 = pbVar22[3]; + pbVar20 = pbVar20 + 3; + pbVar22 = pbVar18 + (uint)(*(int *)(param_1 + 0x41fc8) << 2); + *pbVar22 = (byte)((uint)bVar2 * 0x19a + uVar17 * 0x267 >> 10); + pbVar22[1] = (byte)((uVar8 + uVar17) * 0xf6 + uVar16 * 0x171 + (uint)bVar2 * 0xa4 >> 10); + pbVar22[2] = (byte)((uVar15 + uVar8 * 4) * 0x52 + iVar13 * 0x7b >> 10); + pbVar22[3] = (byte)((uVar8 + uVar15 * 4) * 0x52 + iVar1 * 0x7b >> 10); + pbVar18 = pbVar18 + 5; + pbVar22[4] = (byte)((uVar15 + uVar24) * 0xf6 + uVar25 * 0x171 + (uint)bVar3 * 0xa4 >> 10); + pbVar9 = pbVar9 + 3; + pbVar23 = pbVar23 + 5; + local_res10 = local_res10 - 1; + } while (local_res10 != 0); + } + local_res18 = local_res18 + 3; + local_res20 = local_res20 + 0xf; + uVar10 = (ulonglong)local_res20; + } while (local_res18 < *(uint *)(param_1 + 0x41fc4)); + } + return pbVar9; +} + + +================================================================== + +### ADDR 18001a750 FUNC 18001a750 (841 bytes) name=FUN_18001a750 + +void FUN_18001a750(longlong param_1) + +{ + uint uVar1; + uint uVar2; + uint uVar3; + uint uVar4; + int iVar5; + float fVar6; + float fVar7; + undefined1 uVar8; + uint uVar9; + longlong lVar10; + uint uVar11; + uint uVar12; + ulonglong uVar13; + uint uVar14; + int iVar15; + ulonglong uVar16; + ulonglong uVar17; + int iVar18; + float fVar19; + float fVar20; + float fVar21; + float fVar22; + float fVar23; + + fVar7 = DAT_18005e704; + fVar6 = DAT_18005e700; + uVar1 = *(uint *)(param_1 + 0x41fc8); + uVar2 = *(uint *)(param_1 + 0x41fc0); + uVar3 = *(uint *)(param_1 + 0x41fc4); + uVar4 = *(uint *)(param_1 + 0x41fcc); + uVar17 = 0; + if (uVar1 != 0) { + fVar23 = (float)uVar2 - DAT_18005e700; + do { + iVar18 = (int)uVar17; + fVar22 = (float)uVar17 * ((float)uVar2 / (float)uVar1); + if (fVar23 < fVar22) { + fVar22 = fVar23; + } + uVar11 = 0; + uVar13 = (ulonglong)fVar22; + if (uVar4 != 0) { + iVar5 = (int)uVar13; + uVar12 = iVar5 + 1; + fVar21 = (float)uVar3 - fVar6; + do { + fVar20 = (float)uVar11 * ((float)uVar3 / (float)uVar4); + if (fVar21 < fVar20) { + fVar20 = fVar21; + } + uVar16 = (ulonglong)fVar20; + iVar15 = (int)uVar16; + if ((uVar12 < uVar2) && (iVar15 + 1U < uVar3)) { + lVar10 = *(longlong *)(param_1 + 0x2a0); + uVar14 = iVar15 * uVar2 + iVar5; + fVar19 = fVar22 - (float)(uVar13 & 0xffffffff); + fVar20 = fVar20 - (float)(uVar16 & 0xffffffff); + lVar10 = (longlong) + (((float)*(byte *)((ulonglong)(uVar14 + uVar2) + lVar10) * (fVar6 - fVar19) + + (float)*(byte *)((ulonglong)(uVar14 + 1 + uVar2) + lVar10) * fVar19) * fVar20 + + ((float)*(byte *)((ulonglong)(uVar14 + 1) + lVar10) * fVar19 + + (float)*(byte *)((ulonglong)uVar14 + lVar10) * (fVar6 - fVar19)) * + (fVar6 - fVar20) + fVar7); + uVar8 = (undefined1)lVar10; + if (0xff < (uint)lVar10) { + uVar8 = 0xff; + } + *(undefined1 *)(uVar17 + *(longlong *)(param_1 + 0x220)) = uVar8; + } + else { + uVar14 = iVar15 + 1; + if ((uVar14 == uVar3) && (uVar12 < uVar2)) { + uVar14 = iVar15 * uVar2 + iVar5; + uVar9 = (uint)*(byte *)((ulonglong)uVar14 + *(longlong *)(param_1 + 0x2a0)); + lVar10 = (longlong) + ((float)(int)(*(byte *)((ulonglong)(uVar14 + 1) + + *(longlong *)(param_1 + 0x2a0)) - uVar9) * + (fVar22 - (float)(uVar13 & 0xffffffff)) + (float)uVar9 + fVar7); + uVar8 = (undefined1)lVar10; + if (0xff < (uint)lVar10) { + uVar8 = 0xff; + } + *(undefined1 *)(uVar17 + *(longlong *)(param_1 + 0x220)) = uVar8; + } + else if ((uVar12 == uVar2) && (uVar14 < uVar3)) { + uVar9 = (uint)*(byte *)((ulonglong)(iVar15 * uVar2 + iVar5) + + *(longlong *)(param_1 + 0x2a0)); + lVar10 = (longlong) + ((float)(int)(*(byte *)((ulonglong)(uVar14 * uVar2 + iVar5) + + *(longlong *)(param_1 + 0x2a0)) - uVar9) * + (fVar20 - (float)(uVar16 & 0xffffffff)) + (float)uVar9 + fVar7); + uVar8 = (undefined1)lVar10; + if (0xff < (uint)lVar10) { + uVar8 = 0xff; + } + *(undefined1 *)(uVar17 + *(longlong *)(param_1 + 0x220)) = uVar8; + } + else { + *(undefined1 *)(uVar17 + *(longlong *)(param_1 + 0x220)) = + *(undefined1 *) + ((ulonglong)(iVar15 * uVar2 + iVar5) + *(longlong *)(param_1 + 0x2a0)); + } + } + uVar11 = uVar11 + 1; + uVar17 = (ulonglong)((int)uVar17 + uVar1); + } while (uVar11 < uVar4); + } + uVar11 = iVar18 + 1; + uVar17 = (ulonglong)uVar11; + } while (uVar11 < uVar1); + } + return; +} + + +================================================================== + diff --git a/build-artifacts/mag160c_demo3.exe b/build-artifacts/mag160c_demo3.exe index 28a05fa..f151375 100644 --- a/build-artifacts/mag160c_demo3.exe +++ b/build-artifacts/mag160c_demo3.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d5d8ff585c62ff340c529692a2d794708adadd6a23f571f971265b810a85ede +oid sha256:204a8e37fa0ce7059e0108c1cde276a28a109e4be9e601f0a39a18a1f9d88489 size 139578 diff --git a/csdk/README.md b/csdk/README.md index 014cb98..10a849a 100644 --- a/csdk/README.md +++ b/csdk/README.md @@ -151,10 +151,38 @@ USB帧(type=0) → 快门提取(帧尾字) → FFC状态机(0x9ee0) → 端点选择+Q12插值(0x16ae0/0x16dd0/0x16f10, 快门驱动) → ref = FFC窗口4个type=1帧均值(0x41ee0 mode=4) → NUC查表(0x17200) → 盲元补偿(0x17330, 32条固定记录) -→ 统计+窗口(0x10780/0x109c0, half=312) → LUT1024重建(0x11ee0) +→ [可选后处理: temporal 0x1e920 / 帧差 0x175a0 / 隔行平滑 0x184f0/0x18660] +→ 统计+窗口(0x10780/0x109c0, half=312) → LUT1024重建(0x11ee0, 含0x8c) → 灰度+2x升采样(0x19740) → 官方调色板 ``` +#### 官方附加环节编译开关(默认 0 = 官方当前会话行为) + +官方 SDK 中这些路径编译在内但当前会话控制字段为 0(未执行)。demo3 +全部移植,用编译开关启用,运行时用按键切换测试: + +| 开关 | 对应官方函数 | 官方字段 | 按键 | +|---|---|---|---| +| `OFF_IMPL_230` | 帧差调整 0x175a0 | 0x230=0 | 8 | +| `OFF_IMPL_41FE8` | 隔行平滑 0x184f0(2x)/0x18660(4x) | 0x41fe8=0 | 0 | +| `OFF_IMPL_30` | gray 覆盖 0x17770(auto)/0x17c40(manual) | 0x30=0, 0x84 | 9 | +| `OFF_IMPL_UPSCALE` | Nx 升采样 4x/8x | 当前 2x | — | + +```powershell +# 默认版本(与官方行为一致) +gcc ... (见上文 demo3 编译命令) + +# 全部附加环节开启版(默认展示各路径,按键切回官方默认) +gcc -O2 -w -DOFF_IMPL_41FE8=1 -DOFF_IMPL_30=1 -DOFF_IMPL_230=1 -DMAG160C_STATIC ... +``` + +说明: +- 0x17770(auto gray 双边滤波)的空间权重表在官方二进制 .data 节被裁剪 + 无法提取,demo3 用标准高斯核近似(σ=2.0),值域核按官方生成式(sqrt 核)。 +- 0x17c40(manual)已逐行翻译:8x8 窗口 4x4 采样对比度增强累积 → gray。 +- 0x18660 为逐行翻译(4 相位加权插值);0x184f0 为 2-tap 半分辨率插值。 +- 验证:默认版无回归;41fe8=1 开启后 NUC 输出 std 从 ~250 降到 ~95(平滑生效)。 + 运行(需要 `build-artifacts/` 下的 DDT 表文件): ```powershell diff --git a/csdk/tools/mag160c_demo3.c b/csdk/tools/mag160c_demo3.c index bb48de5..198c20a 100644 --- a/csdk/tools/mag160c_demo3.c +++ b/csdk/tools/mag160c_demo3.c @@ -89,6 +89,31 @@ static double counts_to_c(double v) { #define OFF_DDT "mag160c_official.ddt" +/* ===================================================================== + * 官方附加环节移植(编译开关,默认 0 = 官方当前会话行为) + * = 1 时对应代码路径可用(运行时控制变量再决定是否执行): + * OFF_IMPL_230 帧差调整 FUN_1800175a0 (官方 0x230=0 关闭) + * OFF_IMPL_41FE8 隔行平滑 FUN_1800184f0/660(官方 0x41fe8=0 关闭) + * OFF_IMPL_30 gray 覆盖路径 0x17770/0x17c40(官方 0x30=0 关闭) + * OFF_IMPL_UPSCALE 多比例升采样 4x/8x/1.5x/3x(当前设备 2x) + * ===================================================================== */ +#define OFF_IMPL_230 0 +#define OFF_IMPL_41FE8 0 +#define OFF_IMPL_30 0 +#define OFF_IMPL_UPSCALE 0 + +/* 运行时控制变量(官方会话实测值;编译开关开启时默认展示该路径, + * 可用按键 0/8/9 切换回官方默认) */ +static int g_ctrl_230 = OFF_IMPL_230; /* 官方 dev+0x230 */ +static int g_ctrl_41fe8 = OFF_IMPL_41FE8 ? 1 : 0; /* 官方 dev+0x41fe8 */ +static int g_ctrl_30 = OFF_IMPL_30; /* 官方 dev+0x30 渲染模式 */ +static int g_ctrl_84 = 0; /* 官方 dev+0x84 */ +static unsigned short *g_buf278; /* 官方 dev+0x278(当前会话 NULL) */ +static int g_im41fec; /* 官方 dev+0x41fec */ +static int g_im41ff0; /* 官方 dev+0x41ff0 */ +static unsigned short g_sm_buf[((W / 2 + 2) * (H / 2 + 1) + 16) * 2]; +static unsigned short g_sm4_buf[((W / 4 + 2) * (H / 4 + 1) + 16) * 2]; + static libusb_context *g_ctx; static libusb_device_handle *g_h; static unsigned char g_frame[40000]; @@ -106,6 +131,9 @@ static int g_dev4c_shift = 3; /* 0x4794c */ static int g_dev48; /* contrast -100..100 */ static int g_dev4c; /* window scale -100..100 */ static int g_dev8c = 1; /* 0x8c: CDF pivot at 75% cumulative (live=1) */ +static int g_dev47950 = 0; /* 0x47950: 0 static / 1 time-based */ +static int g_dev47948 = -50000; /* 0x47948: comp offset */ +static int g_dev47954 = 0; /* 0x47954 */ static int g_shift; /* 0x11c = 12 */ static int g_ep_temps[64]; /* T[] */ static int g_blind_cnt[64]; @@ -572,7 +600,278 @@ static void temporal_apply(unsigned short *buf, int thr) { g_tmp_ring = g_tmp_hist; } -/* ---------------- gray + 2x upscale (FUN_180019740) ---------------- */ +/* ---------------- 附加环节:帧差调整 (FUN_1800175a0) ---------------- */ +/* out[i] = clamp(out[i] - buf278[i] + offset); offset = (-0x47948)>>0x4794c + * (static mode; live: -(-50000)>>3 = 6250). 0x278 buffer is NULL in the + * official session (0x230=0), so this is a no-op unless OFF_IMPL_230 and + * g_buf278 are provided. */ +static void frame_diff_adjust(unsigned short *out) { + int offset; + if (g_dev47950 == 0) + offset = -g_dev47948 >> g_dev4c_shift; + else + offset = 0; + if (offset < 0) offset = 0; + if (!g_buf278) return; + for (int i = 0; i < NPIX; ++i) { + int v = (int)out[i] - (int)g_buf278[i] + (offset & 0xffff); + if (v < 0) v = 0; + if (v > 0xffff) v = 0xffff; + out[i] = (unsigned short)v; + } +} + +/* ---------------- 附加环节:隔行平滑 (FUN_1800184f0, 0x41fe8 mode 1/3) ---- + * 偶数行每行取前 w/2+2 个样本 → 水平 2-tap 插值写回偶数行, + * 与下一行样本做 4-tap 对角平均写回奇数行(半分辨率降噪插值)。 */ +static void interlace_smooth_2x(unsigned short *out) { + int w = W, h = H; + int sw = (w >> 1) + 2, sh = (h >> 1) + 1; + /* subsample: even rows, first sw columns (clamped) */ + for (int y = 0; y < sh; ++y) { + int sy = y * 2; + if (sy >= h) sy = h - 1; + const unsigned short *s = out + sy * w; + unsigned short *d = g_sm_buf + y * sw; + for (int x = 0; x < sw; ++x) d[x] = s[x < w ? x : w - 1]; + } + /* horizontal interpolation into even rows */ + unsigned int *p4 = (unsigned int *)out; + for (int yy = 0; yy < (h >> 1); ++yy) { + const unsigned short *t = g_sm_buf + yy * sw; + for (int xx = 0; xx < (w >> 1); ++xx) { + unsigned a = t[xx], b = t[xx + 1]; + *p4++ = ((b + a) >> 1) << 16 | a; + } + /* vertical 4-tap into odd row */ + const unsigned short *cur = g_sm_buf + yy * sw; + const unsigned short *nxt = cur + sw; + unsigned int *p4o = p4; + for (int xx = 0; xx < (w >> 1); ++xx) { + unsigned a = cur[xx], b = cur[xx + 1]; + unsigned c = nxt[xx + 2], d = nxt[xx + 3]; + *p4o++ = ((b + a + c + d) >> 2) << 16 | ((c + a) >> 1); + } + p4 = p4o; + } +} + +/* ---------------- 附加环节:隔行平滑 4x (FUN_180018660, mode 2/3/4) ----- + * 逐行翻译:每 4 行取 1 行、每行前 w/4+2 样本 → 4 相位输出, + * 每相位 2 个 u32(4 个 u16)水平/垂直加权插值。 */ +static void interlace_smooth_4x(unsigned short *out) { + int w = W, h = H; + int sw = (w >> 2) + 2, sh = (h >> 2) + 1; + for (int y = 0; y < sh; ++y) { + int sy = y * 4; + if (sy >= h) sy = h - 1; + const unsigned short *s = out + sy * w; + unsigned short *d = g_sm4_buf + y * sw; + for (int x = 0; x < sw; ++x) d[x] = s[x < w ? x : w - 1]; + } + unsigned int *p4 = (unsigned int *)out; + for (int yy = 0; yy < (h >> 2); ++yy) { + const unsigned short *t = g_sm4_buf + yy * sw; + const unsigned short *n = t + sw; + for (int xx = 0; xx < (w >> 2); ++xx) { + unsigned a = t[xx], b = t[xx + 1]; + unsigned c = n[xx + 2], d = n[xx + 3]; + /* phase 0: 水平 4x 插值 */ + *p4++ = ((a + a * 2 + b) >> 2) << 16 | a; + *p4++ = ((a + b * 2 + b) >> 2) << 16 | ((b + a) >> 1); + /* phase 1 */ + unsigned s3 = a * 3; + *p4++ = ((((b + c + s3) * 3 + d) >> 4) << 16 | ((c + s3) >> 2)); + *p4++ = (((c + (d + b * 2 + b + a) * 3) >> 4) << 16 | + ((d + (b + a) * 3 + c) >> 3)); + /* phase 2 */ + *p4++ = ((((a + c) * 3 + d + b) >> 3) << 16 | ((a + c) >> 1)); + *p4++ = (((c + (d + b) * 3 + a) >> 3) << 16 | ((d + b + c + a) >> 2)); + /* phase 3 */ + unsigned s3b = c * 3; + *p4++ = ((((d + s3b + a) * 3 + b) >> 4) << 16 | ((s3b + a) >> 2)); + *p4++ = (((a + (b + d * 2 + d + c) * 3) >> 4) << 16 | + ((b + (d + c) * 3 + a) >> 3)); + } + } +} + +/* ---------------- 附加环节:manual gray 路径 (FUN_180017c40) ----------- + * 0x30>=1 且 0x84!=0 时:8x8 窗口 4x4 采样,高对比度区域做对比度 + * 增强累积(0x2a8 int 缓冲),最后累加到 gray(0x2a0)。 + * param_2 = 增强等级(官方传 0x30 模式 << 3 = 8/16/24/32)。逐行翻译。 */ +static int g_enh_acc[NPIX]; /* 官方 dev+0x2a8 */ +static void gray_path_manual(const unsigned short *nuc, int enh) { + if (enh == 0) return; + memset(g_enh_acc, 0, sizeof(g_enh_acc)); + unsigned v18 = (unsigned)(g_dev24 * 1000) >> g_dev4c_shift; + if (v18 > 0xffff) v18 = 0xffff; + unsigned v19 = ((unsigned)v18 * (unsigned)enh & 0x7fffffff) >> 7; + for (int y = 0; y < H - 6; ++y) { + for (int x = 0; x < W - 6; ++x) { + const unsigned short *p = nuc + y * W + x; + int *acc = g_enh_acc + y * W + x; + unsigned mn = 0xffff, mx = 0, sum = 0; + for (int dy = 0; dy < 4; ++dy) + for (int dx = 0; dx < 4; ++dx) { + unsigned v = p[dy * W + dx * 2]; + sum += v; + if (v < mn) mn = v; + if (v > mx) mx = v; + } + if (v19 <= (mx - mn) * 0x20) { + unsigned mean = sum >> 4; + unsigned r = v19; + if (r < mx - mean) r = mx - mean; + if (r < mean - mn) r = mean - mn; + int k = (int)(0x8000 / (r ? r : 1)); + for (int dy = 0; dy < 4; ++dy) + for (int dx = 0; dx < 4; ++dx) { + int i = (dy) * W + dx * 2; + acc[i] += ((int)p[i] - (int)mean) * k; + } + } + } + } + /* gray accumulate pass (0x2a0) */ + for (int y = 0; y < H; ++y) { + int rn = 4; + if (y < 6) rn = (y >> 1) + 1; + else if (H < y + 7) rn = (H - y + 1) >> 1; + for (int x = 0; x < W; ++x) { + int cn = 4; + if (x < 6) cn = (x >> 1) + 1; + else if (W < x + 7) cn = (W - x + 1) >> 1; + int i = y * W + x; + int v = enh * g_enh_acc[i]; + if (cn * rn == 0x10) + v = (int)((v >> 0x1f & 0x7ffff) + v) >> 0x13; + else + v = v / (cn * rn * 0x8000); + int gv = (int)g_gray160[i] + v; + if (gv < 0) gv = 0; + if (gv > 255) gv = 255; + g_gray160[i] = (unsigned char)gv; + } + } +} + +/* ---------------- 附加环节:auto gray 路径 (FUN_180017770) ----------- + * 0x30>=1 且 0x84==0 时:0x290 行缓冲边界扩展 + 4行x7列加权双边 + * 滤波(空间权重表 0x9a454/460/474 + 值域核 0x9a450/4a0)就地平滑 + * 0x270,然后直方图均衡更新 0x2a0。 + * 注意:官方 .data 节在二进制中被裁剪,空间权重表静态值无法提取, + * 此处用标准高斯核近似(σ=2.0),值域核按官方生成式(sqrt 表)。 + * 官方会话 0x30=0 不执行;启用 OFF_IMPL_30 且 g_ctrl_30>=1 时生效。 */ +static float g_gauss7[7]; /* 空间权重(近似,官方表不可提取) */ +static float g_radial[24]; /* 值域核 |d|/span 查表(近似 0x9a450) */ +static void gray_path_auto_prep(void) { + static int done; + if (done) return; + done = 1; + float s2 = 2.0f * 2.0f * 2.0f; + for (int i = 0; i < 7; ++i) { + int dy = i - 3; + g_gauss7[i] = (float)exp(-(double)(dy * dy) / s2); + } + for (int i = 0; i < 24; ++i) { + float d = (float)i / 23.0f; + g_radial[i] = (float)exp(-(double)(d * d) * 8.0); + } +} +static void gray_path_auto(unsigned short *nuc) { + gray_path_auto_prep(); + unsigned short tmp[NPIX]; + memcpy(tmp, nuc, sizeof(tmp)); + for (int y = 3; y < H - 3; ++y) { + for (int x = 3; x < W - 3; ++x) { + unsigned c = tmp[y * W + x]; + float wsum = 0.0f, vsum = 0.0f; + for (int dy = -3; dy <= 3; ++dy) { + for (int dx = -3; dx <= 3; dx += 2) { + unsigned v = tmp[(y + dy) * W + x + dx]; + int ad = v > c ? (int)v - c : (int)c - v; + if (ad > 23) ad = 23; + float w = g_gauss7[dy + 3] * g_radial[ad]; + wsum += w; + vsum += w * (float)v; + } + } + if (wsum > 0.0f) { + int r = (int)(vsum / wsum) + 0x8000; + if (r < 0) r = 0; + if (r > 0xffff) r = 0xffff; + nuc[y * W + x] = (unsigned short)r; + } + } + } +} + +/* ---------------- 附加环节:Nx 升采样 (0x19740 模式推广) ----------- + * 2x 已逐像素验证(0/76800);4x/8x 用同一线性插值模式推广 + * (隔 n 采样 + (n-i)/n 权重,垂直 2-tap + 对角双线性,边缘外推)。 + * 当前设备固定 2x,仅供 OFF_IMPL_UPSCALE 测试。 */ +static unsigned char g_gray_big[1280 * 960]; +static void upscale_nx(int n, int *ow, int *oh) { + *ow = W * n; + *oh = H * n; + unsigned char *o = g_gray_big; + int lg = n == 2 ? 1 : (n == 4 ? 2 : 3); /* log2(n) */ + for (int y = 0; y < H - 1; ++y) { + for (int x = 0; x < W - 1; ++x) { + unsigned a = g_gray160[y * W + x]; + unsigned b = g_gray160[y * W + x + 1]; + unsigned c = g_gray160[(y + 1) * W + x]; + unsigned d = g_gray160[(y + 1) * W + x + 1]; + for (int j = 0; j < n; ++j) { + for (int i = 0; i < n; ++i) { + unsigned hv = (a * (n - i) + b * i) >> lg; + unsigned vv = (a * (n - j) + c * j) >> lg; + unsigned dg = (a * (n - i) * (n - j) + b * i * (n - j) + + c * (n - i) * j + d * i * j) >> (lg * 2); + unsigned v; + if (j == 0) v = hv; + else if (i == 0) v = vv; + else v = dg; + o[(y * n + j) * (*ow) + x * n + i] = (unsigned char)v; + } + } + } + } + /* bottom row extrapolation */ + for (int x = 0; x < W - 1; ++x) { + unsigned a = g_gray160[(H - 1) * W + x]; + unsigned b = g_gray160[(H - 1) * W + x + 1]; + unsigned u = g_gray160[(H - 2) * W + x]; + unsigned u2 = g_gray160[(H - 2) * W + x + 1]; + for (int i = 0; i < n; ++i) { + unsigned hv = (a * (n - i) + b * i) >> lg; + unsigned uh = (u * (n - i) + u2 * i) >> lg; + o[(H * n - 1) * (*ow) + x * n + i] = (unsigned char)((3 * hv >> 2) + (uh >> 2)); + } + } + /* right column extrapolation */ + for (int y = 0; y < H - 1; ++y) { + unsigned a = g_gray160[y * W + W - 1]; + unsigned u = g_gray160[(y + 1) * W + W - 1]; + unsigned l = g_gray160[y * W + W - 2]; + unsigned l2 = g_gray160[(y + 1) * W + W - 2]; + for (int j = 0; j < n; ++j) { + unsigned vv = (a * (n - j) + u * j) >> lg; + unsigned lh = (l * (n - j) + l2 * j) >> lg; + o[(y * n + j) * (*ow) + W * n - 1] = (unsigned char)((3 * vv >> 2) + (lh >> 2)); + } + } + /* corner */ + { + unsigned a = g_gray160[(H - 1) * W + W - 1]; + unsigned l = g_gray160[(H - 1) * W + W - 2]; + unsigned u = g_gray160[(H - 2) * W + W - 1]; + unsigned v1 = (3 * a + l) >> 2; + unsigned v2 = (3 * a + u) >> 2; + o[(*oh - 1) * (*ow) + (*ow) - 1] = (unsigned char)((v1 + v2 + a) / 3); + } +} static void gray_map(const unsigned short *nuc) { unsigned S = 0xFFC00000u / (unsigned)(g_win_hi - g_win_lo); @@ -776,6 +1075,25 @@ static LRESULT CALLBACK wndproc(HWND hw, UINT msg, WPARAM wp, LPARAM lp) { return 1; case WM_KEYDOWN: if (wp == VK_ESCAPE) { DestroyWindow(hw); return 0; } + /* runtime toggles for the official extra paths (compile-gated) */ +#if OFF_IMPL_41FE8 + if (wp == '0') { + g_ctrl_41fe8 = (g_ctrl_41fe8 + 1) % 5; + SetWindowTextA(hw, g_ctrl_41fe8 ? "41fe8 smoothing ON (mode %d)" : "41fe8 OFF"); + } +#endif +#if OFF_IMPL_30 + if (wp == '9') { + g_ctrl_30 = (g_ctrl_30 + 1) % 5; + SetWindowTextA(hw, g_ctrl_30 ? "0x30 gray path ON (mode %d)" : "0x30 OFF"); + } +#endif +#if OFF_IMPL_230 + if (wp == '8') { + g_ctrl_230 = !g_ctrl_230; + SetWindowTextA(hw, g_ctrl_230 ? "0x230 frame-diff ON" : "0x230 OFF"); + } +#endif break; case WM_DESTROY: PostQuitMessage(0); @@ -1037,9 +1355,30 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show) { temporal_apply(g_nuc, thr); g_flag42038 = 1; } +#if OFF_IMPL_230 + if (g_ctrl_230 != 0) + frame_diff_adjust(g_nuc); +#endif +#if OFF_IMPL_41FE8 + if (g_ctrl_41fe8 == 1 || g_ctrl_41fe8 == 3) + interlace_smooth_2x(g_nuc); + if (g_ctrl_41fe8 == 2 || g_ctrl_41fe8 == 3 || g_ctrl_41fe8 == 4) { + interlace_smooth_4x(g_nuc); + if (g_ctrl_41fe8 == 4) + interlace_smooth_4x(g_nuc); + } +#endif official_stats_window(g_nuc); lut_rebuild(g_nuc); gray_map(g_nuc); +#if OFF_IMPL_30 + if (g_ctrl_30 >= 1 && g_ctrl_30 <= 4) { + if (g_ctrl_84 == 0) + gray_path_auto(g_nuc); + else + gray_path_manual(g_nuc, g_ctrl_30 << 3); + } +#endif upscale2x(); g_flag42004 = 1; } else {