← 返回文章列表

《戦巫〈センナギ〉》存档修改与脚本逆向全复盘

创作说明:本文基于作者与 AI 的调试对话整理生成,完整保留问题排查思路与技术细节。

1. 背景

项目 说明
游戏 戦巫〈センナギ〉―穢れた契りと神ころも―
公司/引擎 Escu:de(エスクード)/ YU-RIS
版本 已打 UIF 注入式汉化补丁
好结局条件 神気率 100% → 触发“觉醒之仪” → 姫華线好结局
坏结局 神気未满 → 男主、女主、夏洛特同归于尽
用户现状 已通关一周目(坏结局),战斗系统繁琐不想二周目

核心挑战:把神気从 51% 改到 100%,让用户在现有存档上直接打出好结局。


2. 技术路径全景图

存档直改 ──→ 预览有效,游戏内无效 ──→ 校验拦截读不了档


内存扫描 ──→ u8/u16/u32/f32 全试 ──→ 只找到预览副本


解包脚本 ──→ EscudeTools 解 ESC-ARC2 + YU-RIS VM ──→ 定位觉醒判定逻辑


改脚本重打包 ──→ 绕开神気≥100 判定 ──→ ✅ 成功

3. 阶段一:存档文件直改 ❌

3.1 存档结构

文件 大小 说明
save_00X.dat ~1.9MB 手动存档,YU-RIS 二进制序列化,含预览区和加密数据区
game_data.sys 457KB 系统档,含 CG/标记数据,不含神気

路径:C:\Users\<user>\Documents\ESCUDE\Sennagi\save\

3.2 第一次发现:预览字段

通过对比 20 个存档的递增轨迹(0→1→3→4→6→11→15→23→42→51→59),定位到偏移 0x2218A 处是神気的 4 字节整数预览字段。但这个字段只影响存档列表的显示,读档后游戏内神気不变——它是独立预览副本。

3.3 为什么直改失败

  1. 游戏中实际的属性数据非明文存储——搜索 449/292/319/4060 等属性值,存档中找不到对应字节
  2. 直接修改 0x2218A → 游戏校验拦截,存档读不出来(YU-RIS 存档有完整性校验)
  3. 神気不是独立变量:游戏根据战斗记录动态计算,而非存一个固定整数

根因:YU-RIS 的存档体(Save Body)对实际游戏状态进行了加密/编码。预览区只是给存档列表看的,和游戏运行时数据是两套。


4. 阶段二:内存扫描 ❌

4.1 尝试的扫描方式

编码 方法 结果
u8 单字节值搜索 51/59/67 命中太多假阳性(图像纹理缓冲区)
u16 双字节值搜索 同上
u32 四字节搜索 + 差分对比 找到候选但写入后只影响预览
f32 浮点数搜索 不存在
连续序列 [69, 4780, 505, 403, 410] 紧凑存储 不存在
三重交叉验证 同地址“曾为51、曾为59、现为67” 无命中

4.2 为什么都不行

  • 真正的神気变量地址不固定(每次战斗对象重建,内存地址漂移)
  • 写入 100 到所有候选地址后,游戏内神気显示不变——这些候选全是 UI 缓存/预览副本
  • 神気可能是从练度等底层数据计算得出(当前/上限百分比),不是独立存储

关键教训:YU-RIS 引擎的 VM 全局变量(GVAR)在内存中是通过 VM 解释器间接访问的,扫描直接内存值找不到真正的运行时变量。


5. 阶段三:解锁关键信息 —— 解包脚本 🔬

5.1 工具链

使用开源工具 EscudeTools(GitHub),功能:

  • 解 ESC-ARC2 压缩包(游戏脚本的封包格式)
  • 解 YU-RIS VM 字节码脚本
  • 导出为 SQLite 数据库供分析

编译适配:源码目标 .NET 8,本机只有 .NET 6 和 10。改 TargetFrameworknet10.0 后重编译成功。

5.2 解包结果

script.bin (5.9MB, ESC-ARC2 加密压缩)
  └─ 247 个子脚本文件 (.bin, YU-RIS 字节码)
       ├─ a_prol_*.bin    ← 序章
       ├─ b_05st*.bin     ← 第五章
       ├─ b_06st*.bin     ← 第六章
       ├─ b_07hime_01_*   ← 好结局(姫華觉醒成功)
       ├─ b_07hime_02_*   ← 同归于尽坏结局(觉醒失败)
       ├─ b_07dark_*      ← 悪堕ち线
       ├─ z_flow_main.bin ← ⭐ 系统路由脚本(主流程控制)
       ├─ h_04chk_gp.bin  ← 神気检查
       └─ h_04chk_gpmax.bin ← 神気满检查

5.3 从脚本中确认的关键信息

通过搜索 YU-RIS VM 指令,确认:

神気 = 全局变量 #81(指令 INST_PUSH_GVAR 0x51)
觉醒判定在 z_flow_main.bin 中
主流程按 gvar41 分阶段:
  - gvar41 == 2 → 神気进度检查阶段
  - gvar41 == 3 → 觉醒判定阶段

关键判定指令序列:

INST_PUSH_GVAR 0x51    ; 读取 GVAR[81] = 神気
INST_PUSH_INT 100      ; 压入阈值 100
INST_CMP_GE            ; 比较:神気 >= 100?
INST_JMPZ LABEL_BAD    ; 不满足 → 跳转坏结局

6. 阶段四:成功 —— 改脚本重打包 ✅

6.1 修改目标

改的是 z_flow_main.bin 里的两处判定:

位置 偏移 原始逻辑 修改
@3001(觉醒闸门) gvar41==3 触发 神気 ≥ 100 才觉醒 无条件跳进觉醒分支
@2322(流程推进门) gvar41==2 触发 神気 < 100 才能推进 改成永远成立

6.2 改了什么

# @3001 觉醒判定:
原始:PUSH_GVAR(81) PUSH_INT(100) CMP_GE → JMPZ(跳坏结局)
修改:PUSH_GVAR(81) PUSH_INT(0)   CMP_GE → 永远成立
      + 条件跳转改为无条件跳转 → 保险绕过

# @2322 流程推进:
原始:PUSH_GVAR(81) PUSH_INT(100) CMP_LT → 神気<100
修改:PUSH_GVAR(81) PUSH_INT(0)   CMP_LT → 永远不成立,不卡流程

6.3 打包与部署

# 1. 修改子脚本字节(hex 编辑)
# 2. 用 EscudeTools 重打包为 script.bin
EscudeTools -r output_dir

# 3. 备份原脚本 + 替换
copy script.bin script.bin.orig
copy new_script.bin "D:\games\戦巫<...>\script.bin"

6.4 第一次失败 & 排查

第一次只改了 @3001(觉醒判定),但用户测试后仍然是坏结局。排查发现:主流程按 gvar41 分阶段,gvar41==2 时走的是 @2322 那个神気检查(不是觉醒判定),用户流程根本没进到觉醒阶段就分流了。

因此补改了第二处 @2322,两处一起改才生效。


7. 全部尝试一览

尝试 方法 结果 失败原因
直接改存档 0x2218A 二进制写入 100 预览变,游戏内不变 只是预览字段
改存档后读档 覆盖 100 后读档 读不了档 校验拦截
内存写 100 到候选地址 Python 进程注入 游戏内不变 只改到预览副本
连续属性序列搜索 内存搜 [69,4780,505,...] 不存在 属性不连续存储
f32 浮点搜索 搜 float 表示 不存在 不是浮点存储
game_data.sys 对比两次存档的系统档 无变化 神気不在这里
Gemini 给的工具 .py.ct 两个文件 用不了 .py 会乱改内存,.ct 缺少注入地址
最终方案 改脚本字节 → 重打包 成功

8. 方法论总结

8.1 存档修改通用流程

1. 收集多份存档(不同进度)→ 做差分对比
2. 区分预览区 vs 实际数据区
3. 如果数据加密/编码 → 跳到脚本层面
4. 解包游戏脚本 → 搜关键变量 → 改判定逻辑
5. 重打包 → 替换 → 测试

8.2 YU-RIS 引擎特点

  • 存档含预览区(明文值)和加密数据区,两者独立
  • 游戏状态由 VM 全局变量(GVAR)管理,不直接暴露在内存中
  • 脚本是 YU-RIS 字节码,需要专用工具解/打包
  • 部分属性值不是静态存储,而是根据底层数据运行时计算

8.3 为什么不建议直改存档

直接改存档字节有三大障碍:

  1. 加密/编码:数据区不是明文
  2. 校验:改了之后通不过完整性检查
  3. 动态计算:某些值不是存储的,是运行时算出来的

改脚本逻辑往往比改存档更可靠。 降低判定门槛(神気≥100 → 神気≥0)比改数值容易得多。

8.4 AI 协作的经验

  • ✅ 用 AI 做脚本分析(在 247 个文件中搜索变量引用、追踪调用链)非常高效
  • ✅ 用 AI 做工具适配(改编译目标从 .NET 8 到 .NET 10)
  • ⚠️ AI 给的“成品工具”需要验证(Gemini 的 .py 会乱改所有 30~99 的值,会把游戏搞崩)
  • ⚠️ 第一次改完没生效不要放弃——排查流程流转(gvar41 分阶段)是关键

9. 文件归档状态

文件 位置 说明
原版脚本备份 D:\games\戦巫<...>\script.bin.orig 想恢复时改名覆盖即可
修改后的脚本 D:\games\戦巫<...>\script.bin 当前生效,任何存档都走觉醒→好结局
用户存档 Documents\ESCUDE\Sennagi\save\save_020~024 未动,完好
临时文件 全删 EscudeTools 源码、编译产物、分析脚本、解包数据均已清理

10. 相关链接

评论区