原版 feature 配额初始化与真实 TEMPLATE 输入

本批结果

新增 NativeFeatureInitialization:

  • TEMPLATE 请求模式与概率处理。
  • 5FE050 总量重置/抽取。
  • 5FE160 每块配额分配。
  • 5FDB00 未完成总量重分配。
  • 原容量增长和未知容量槽来源标记。

新增实际数据入口:

  • 导出全部 186 份 TEMPLATE;其中 145 份含 feature 请求。
  • 676 条原版 NAME/MINCOUNT/MAXCOUNT/CHANCE 请求。
  • 从 FEATURETAGS.HIE 导出 131 个标签名称 ID。
  • 41 份已知没有请求的 TEMPLATE 保留为空,区别于未知文件。

416 组原版重置/分配/重分配参考一致;全部 676 条实际请求进入核心初始化测试。累计 1313 条核心断言、179 项相关 Python 检查通过,Godot C# 构建零警告、零错误,coresimlint 通过。

真实标签关系矩阵、唯一性和具体世界宿主仍有剩余;全武器目标未完成。

从 TEMPLATE 创建请求

5FE2C0 读取 TAG 子块:

  • NAME 默认空;为空时不创建请求。
  • CHANCE 默认 0。
  • MINCOUNT/MAXCOUNT 默认 0,保留原 int32 位模式。
  • 缺少原标签表时,5FDEA0/5FDF80 不新增请求。

CHANCE 的分支:

  • CHANCE>0:mode +88=0,概率模式。
  • CHANCE>1:乘原 float 常量 0.01,再落为 float32。
  • 0<CHANCE<=1:原值保留。
  • 非正值以及原无序比较路径中的 NaN:mode=1,保存 Chance=0,使用配额模式。

该部分依据 5FE2C0、5FDEA0、5FDF80、5FDC60 及汇编核对和核心测试;不计入下面 416 组计数流程机器码参考。

请求构造的 quota/used 增长量均为 10。名称记录和 TAG ID 与计数分开。

总量重置:5FE050

按请求列表顺序:

  1. 清 quota 和 used 的数据、数量、容量。
  2. Total 与 Claimed 清零。
  3. MAXCOUNT 为 0 或 FFFFFFFF 时,Total 保持零,不取随机数。
  4. 其他情况先按 unsigned DWORD 比较 MIN/MAX,选出低值与高值。
  5. 将这两个位模式传入有符号同步整数随机包装。
  6. 将返回位模式保存为 Total。

因此不能把它简化成“按有符号 MIN/MAX 排序后总是掷骰”。等值区间,以及排序后有符号上端不大于下端的区间,遵循原包装器的不推进路径。

LastOwner、名称、模式、原 MIN/MAX 等定义字段不在这个函数中清空。

每块配额:5FE160

  • chunks=0 时改为 1。
  • Total=0 的请求不处理。
  • quota 数量为 0 时,为每块追加 quota=1 和 used=0。
  • quota 已存在时,不重建,也不清旧 used。
  • 然后计算 Total-QuotaCount 的 DWORD 差,再按 signed int32 判断是否大于零。
  • 正差值以从第 0 块开始的轮转方式增加 quota。

即使 Total 小于块数,也会先给每块一个 quota;总量上限仍由后续认领的 Claimed<Total 保证。不能为了让配额之和等于 Total 而把部分初值改成零。

重复调用并非幂等。例如 Total=5、两个初始空块:

text
首次分配:[3,2]
再次调用:[5,3]

used 的逻辑数量独立保存;不能以其容量长度替代有效数量。

未完成总量重分配:5FDB00

  • 计算 Total-Claimed 的 DWORD 差,再按 signed int32 判断。
  • 仅正差且 quota 数量非零时处理。
  • 从下标 0 开始,每次先把对应 used 清零,再将对应 quota 加一。
  • 下标到达传入的 remainingChunks 时归零。
  • remainingChunks=0 时每次都回到 0。
  • quota 与 used 各按自己的容量回落到第 0 槽,不按逻辑数量取模。

它增加的是原 quota,不是用“剩余配额”覆盖原值。

核心使用等价的访问次数公式处理纯整数循环,避免数十亿次循环阻塞。该循环没有 RNG 或业务回调;增量保留 DWORD 回绕。相同数组被两个存储字段引用的重分配路径,保留“先清零后加一,最终为 1”的效果。

容量未知、异常资源大小等情形不会被报告为成功分配。

容量不是有效数量

原 vec_grow 7D68B0:

  • 首次容量为增长量。
  • 后续容量每次增加同一增长量,不翻倍。
  • 扩容复制旧容量范围,而不只复制有效数量。
  • 新分配空间不保证清零。

核心保留原容量,并新增 QuotaKnown/UsedKnown:

  • 已明确提供的旧存储默认视为已知。
  • 初始化写入的 quota=1/used=0 标为已知。
  • 新增但未写入的容量槽标为未知。
  • 后续读到未知槽时报缺输入,不把托管数组的物理零值当作原游戏内存证据。
  • used 被明确清零后,可将相应槽标为已知。

参考分配器故意以 A5 填充新内存,用于证明移植未将未初始化容量内容误判为零。A5 不是原游戏的规定填充值;它只用于验证来源标记。

内存分配失败、未定义容量内容和异常跨向量分配别名不在正常初始化的完整等价性声明内。管理端对超过当前支持存储上限的请求明确报缺输入,不偷偷缩小 chunks 或 Total。

实际 TEMPLATE 数据入口

tools/build_native_feature_definitions.py 冻结:

  • 原文件路径、SHA256。
  • 每个 TAG 的原行号和名称。
  • MINCOUNT/MAXCOUNT 的原 32 位位模式。
  • CHANCE 的原 float32 位值。
  • HIE 名称表及源 hash。

读取时验证 NAME 是 STRING、计数为 INTEGER、概率为 FLOAT;不把错误类型静默转成另一个值。保留名称空格,不做任意 trim。

F2NativeFeatureDefinitions:

  • 为已知空 TEMPLATE 返回空请求集合。
  • 对不在冻结目录的来源明确报错。
  • 按原请求顺序调用核心构造入口。
  • 名称查找依 643EB0 对 ASCII 大小写归一化,不去除空格。
  • 名称未知返回 -1;非 ASCII 的大小写语义保持显式未支持。

实际原数据中的 A3_ROTCRYPTGEM2 在当前 FEATURETAGS.HIE 名称表中不存在。保留 -1,不猜替代 TAG,不删掉该请求。原名称查询失败后仍可构造请求,后续关系查询决定其资格。

名称 ID 表不等于完整标签关系矩阵。 导出文件明确 tag_matrix_verified=false;本批没有将名称存在性代替层级匹配。

冻结文件:build/f2/native_feature_definitions.json。

验证范围

416 组参考实际执行:

  • 5FE050。
  • 5FE160。
  • 5FDB00。
  • 原 vec_grow。
  • 同步整数 RNG。

仅分配器边界提供可识别的测试内存。覆盖零/哨兵 MAX、倒序及高位 MIN/MAX、已有存储、独立容量、重复分配、零剩余块数、无符号差值和别名重分配。

另外:

  • 对全部 186 份 TEMPLATE 逐文件校验来源;145 份的 676 条请求进入创建/总量/三块配额流程。
  • 验证从真实字段构造到 NativeFeatureLedger 的认领上限。
  • 验证未知容量读取被拒绝。
  • 验证大整数循环的等价结果。
  • 原有预选、普通 CHOICE、装载器及全量 BINLAYOUT 回归继续通过。

产物:

  • tools/build_native_feature_init_oracle.py/tools/native_feature_init_oracle.c。
  • build/native_feature_init_oracle/results.json。
  • build/native_feature_init_core.log:1313 断言。
  • build/native_feature_init_python.log:179 检查。
  • build/native_feature_init_godot.log:零警告、零错误。

原 EXE SHA256: 186472c3057b38f4cdff4696959a943c396ae6166995f7418997b5ea853e8a5e

剩余与工作边界

下一步继续真实 FEATURETAGS.HIE 关系矩阵、解析期 LEVEL UNIQUE/实例条件上下文,以及具体场景宿主的节点/碰撞注册。世界分区、完整攻击型触发技能和全武器验收仍未完成。

本批请求/配额仍是分阶段装载状态,未作为持久世界状态或快照落地,v29 未改。按 godot-master 的数据/表现分层,正式地图画面未替换。

main 原地工作、未提交、未 attach 原游戏。默认存档 SHA256 保持: 9840fe858b6e311c73f8c2d4ed49912d59d71365f6278392811730e012d32a7f