layout: restructure into src/ tests/ android/ scripts/ tools/

- extension/src/{port,platform,codepage} -> src/; native_render -> src/host
  (+ dxt, shaders/); libgr2 -> src/gr2; extension/third_party -> third_party
- extension/tests -> tests/port, libgr2/tests -> tests/gr2
- android-native -> android (build.sh, push-client.sh moved in)
- script -> scripts; tools/40250 -> tools/server; oracle -> tools/granny-oracle;
  perf tools -> tools/perf
- all build trees under build/ (native, release, android, port-gate)
- xrender:: CMake aliases -> mt::; port-map ledger impl paths rewritten

No code changes. ctest 15/15, port_gate macos+android PASS, port_map check 0 errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-29 19:08:19 +09:00
co-authored by Claude Opus 5.5
parent 70710477cf
commit a46093104c
2817 changed files with 13728 additions and 13744 deletions
+6 -6
View File
@@ -45,7 +45,7 @@
| 产物 | 位置 |
|---|---|
| `libgr2` 静态库(demo 子集) | `libgr2/` |
| `libgr2` 静态库(demo 子集) | `src/gr2/` |
| `gr2dump` CLI(结构化 dump + `--sections` + 可选 glTF) | `tools/gr2dump/` |
| `gr2fuzz`(全量 ~9166 解析 + 谓词 + 直方图) | `tools/gr2fuzz/` |
| 格式变体直方图报告 | `test/fuzz-report.json` |
@@ -79,7 +79,7 @@ T4,T5,T6(+可选 T7b) ──▶ T8(gr2dump)
### T1 · `gr2_file` —— header + section table + fixup **[M]** ✅
> **状态:header + section 表解析已实现**(`libgr2/src/gr2_file.cpp`),`gr2dump --sections` 跑通全部 9166 个文件、0 崩溃。
> **状态:header + section 表解析已实现**(`src/gr2/src/gr2_file.cpp`),`gr2dump --sections` 跑通全部 9166 个文件、0 崩溃。
> 剩下的是 **section 解压(Oodle1,见 T2)**和 **fixup 重定位**(需展开后的数据)。
**实测结论**(写进代码注释,替换旧假设):
@@ -105,7 +105,7 @@ T4,T5,T6(+可选 T7b) ──▶ T8(gr2dump)
### T2 · `gr2_decompress` **[M]** —— 已实现并验证
> **状态:done。** `libgr2/src/oodle1.c` —— 从泄露 SDK 的 `granny_oodle1_compression.cpp` + `radlz.c` + `radarith.c` + `arithbit.c` 端口了**解码路径**(自适应算术编码 + LZ)。约 450 行 C。
> **状态:done。** `src/gr2/src/oodle1.c` —— 从泄露 SDK 的 `granny_oodle1_compression.cpp` + `radlz.c` + `radarith.c` + `arithbit.c` 端口了**解码路径**(自适应算术编码 + LZ)。约 450 行 C。
- `format==0` → memcpy;`format==2`(Oodle1)→ `gr2_oodle1_decompress()`;`format==1`(Oodle0)/ `format==4`(BitKnit,全样本 0 个)→ 留桩报错。
- 3-block 结构:`stop0/1/2` = section 的 `First16Bit` / `First8Bit` / `ExpandedDataSize`(32 位 / 16 位 / 8 位 marshalling 区各一块,共享算术流)。
@@ -213,10 +213,10 @@ T4,T5,T6(+可选 T7b) ──▶ T8(gr2dump)
## 门禁(go / no-go)
- **主**:`libgr2` dump vs 真 Granny —— ✅ **达成**。`oracle probe` 的 `GrannyGetFileInfo` 与 `gr2dump` 逐字段一致;`tools/oracle_diff` 对拍 Granny **2.9.12** 的 `GrannyGetWorldPose4x4Array` + `GrannyDeformVertices`:23 用例(13 模型 bind + 8 动画帧,含 v7 / 双 root / 刚体)骨骼矩阵 ≤ 4.6e-5、蒙皮顶点 ≤ 6.5e-5(`test/m2-numeric.json`)。oracle 在 macOS + Wine + MinGW 跑(`oracle/RUNBOOK.md`)。
- **主**:`libgr2` dump vs 真 Granny —— ✅ **达成**。`oracle probe` 的 `GrannyGetFileInfo` 与 `gr2dump` 逐字段一致;`tools/oracle_diff` 对拍 Granny **2.9.12** 的 `GrannyGetWorldPose4x4Array` + `GrannyDeformVertices`:23 用例(13 模型 bind + 8 动画帧,含 v7 / 双 root / 刚体)骨骼矩阵 ≤ 4.6e-5、蒙皮顶点 ≤ 6.5e-5(`test/m2-numeric.json`)。oracle 在 macOS + Wine + MinGW 跑(`tools/granny-oracle/RUNBOOK.md`)。
- **自洽**:T5 bind pose 自洽 —— ✅ `warrior_cheongrin` `6.1e-5` PASS。全量 2013/2017 < 1e-3;4 个 `>=1e-1` **经 oracle 证实 libgr2 正确**(assassin 对 Granny 3.1e-5),是自洽不变量本身对这几个双-root 资产不成立,非 libgr2 bug。
- **fuzz**:T9b 全量 9166 —— ✅ **零崩溃 + 零谓词失败**。
- **变体可实现**:✅ 无 BitKnit / 无 Oodle0;曲线全 `OldCurveType`,degree ≤ 2,T7b 全覆盖。不做的变体见 [`libgr2/README.md`](../../../libgr2/README.md)「明确不做」(均 0 出现,坏输入干净报错不崩)。
- **变体可实现**:✅ 无 BitKnit / 无 Oodle0;曲线全 `OldCurveType`,degree ≤ 2,T7b 全覆盖。不做的变体见 [`src/gr2/README.md`](../../../src/gr2/README.md)「明确不做」(均 0 出现,坏输入干净报错不崩)。
- **产出**:✅ `test/{fuzz-report,m2-numeric,noise_floor}.json` + `test/assets.list` + `test/oracle_dumps/`。
- **noise_floor**:✅ `test/noise_floor.json`。同-DLL 确定性 = 0(byte-identical);跨实现地板 = mat 4.6e-5 / vtx 6.5e-5;跨版本一档待另一个 granny2.dll。
@@ -279,7 +279,7 @@ T4,T5,T6(+可选 T7b) ──▶ T8(gr2dump)
**bind pose 自洽 4 个异常**(`>=1e-1`):`assassin.gr2`(PC + season1,同)、`warrior_rabbit1_backup.gr2`、`hair_11_1.gr2`。
这 4 个都是**多 root skeleton**(如 assassin:`assasin_low` + `Bip01` 两个 root),且 model 的 `InitialPlacement` 非单位。
> **后续更正(oracle 对拍后)**:这不是 libgr2 的 bug。`assassin` bind pose 的 **骨骼世界矩阵 + 蒙皮顶点与真 Granny 2.9.12 逐字段一致(3.1e-5 / 4.6e-5)**(见 [00-oracle](./00-oracle.md) / `oracle/RUNBOOK.md`)。
> **后续更正(oracle 对拍后)**:这不是 libgr2 的 bug。`assassin` bind pose 的 **骨骼世界矩阵 + 蒙皮顶点与真 Granny 2.9.12 逐字段一致(3.1e-5 / 4.6e-5)**(见 [00-oracle](./00-oracle.md) / `tools/granny-oracle/RUNBOOK.md`)。
> `world[i]·InverseWorld4x4[i] ≈ I` 这个**自洽不变量本身**对这几个资产不成立 —— 它们的 `InverseWorld4x4` 是相对「不含 InitialPlacement 的参考」烘的,而 `world = local链 · InitialPlacement`。是资产属性,不是读取错误。
> 自洽检查因此是个**比 oracle 对拍弱的信号**:能抓转置 / 手系 bug,但对「InverseWorld 参考系不一致」会误报。`warrior_cheongrin` 等单 root 模型不受影响(IP 为单位,两者等价)。