电车
精华
|
战斗力 鹅
|
回帖 0
注册时间 2026-3-11
|
# Tsukihime 汉化版 Bottles 运行问题排查记录
## 环境信息
- 系统:CachyOS Linux (Arch 系)
- 游戏:月姬 (Tsukihime) 汉化版,NScripter 引擎
- 原运行方式:Bottles (Wine)
- 游戏路径:`~/Downloads/tsukihime`
- 最终运行方式:OnscripterYuri v0.7.6 (Linux 原生)
---
## 问题一:BGM 没有声音,音效正常
### 现象
在 Bottles 中运行游戏,音效 (SE) 正常播放,但背景音乐 (BGM) 完全无声。
### 原因分析
游戏通过 NScripter 的 `mp3loop` 命令播放 BGM,该命令依赖 Windows 的 MCI (Media Control Interface)。Wine 对 MCI 的实现不完整,尤其是对大 WAV 文件的循环播放支持有缺陷。而音效 (SE) 使用 `dwave`/`wave` 通道,走的是不同的音频路径,所以不受影响。
### 尝试 1:在 Bottles 中安装 gstreamer 组件
**结果:** Bottles 的依赖项中找不到 gstreamer 组件,无法安装。
### 尝试 2:将 BGM 从 WAV 转换为 MP3
操作:
1. 用 ffmpeg 将 `bgm/` 下 20 个 WAV 文件批量转为 192kbps MP3
2. 修改游戏脚本 `0.txt` 中 135 处 BGM 引用,从 `.wav` 改为 `.mp3`
**结果:** 转换后 BGM 仍然无声。说明问题不在文件格式,而是 Wine 的 MCI 播放通道本身有问题。
已将所有修改恢复为原始 WAV 引用。
### 尝试 3(最终方案):使用 OnscripterYuri 原生运行
OnscripterYuri 是 NScripter 的开源跨平台兼容引擎,基于 SDL2,可在 Linux 原生运行,完全绕过 Wine。
操作:
1. AUR 的 `onscripter` 包源码下载 403 失败
2. 从 GitHub 下载 OnscripterYuri v0.7.6 预编译 x64 Linux 二进制
- 来源:https://github.com/YuriSizuku/OnscripterYuri/releases/tag/v0.7.6
3. 放入游戏目录并赋予执行权限
**结果:BGM 正常播放。**
---
## 问题二:OnscripterYuri 启动报错找不到字体
### 现象
```
can't open font file: default.ttf
```
### 原因
游戏目录下字体文件名为 `default.TTF`(大写扩展名),但 Linux 文件系统区分大小写,ONScripter 查找的是 `default.ttf`(小写)。
### 解决
创建小写符号链接:
```bash
ln -s default.TTF default.ttf
```
---
## 问题三:游戏内文字显示为空方块
### 现象
游戏能启动,但所有中文文字显示为空白方块。
### 原因
`default.ttf` (即 `default.TTF`) 虽然是 TrueType 字体文件,但其元数据中 charset 和 lang 字段为空,字体名称为 "default Regular",实际上不能被 ONScripter 正确用于 GBK 中文渲染。
### 解决
用系统自带的 Noto Sans CJK SC 中文字体替换:
```bash
mv default.ttf default.ttf.bak
cp /usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc default.ttf
```
同时启动时需指定 GBK 编码:
```bash
./onsyuri --enc:gbk
```
---
## 问题四:加载存档时闪退
### 现象
在 OnscripterYuri 中加载 Bottles 下生成的 `save1.dat` 存档时,程序直接崩溃退出。
### 原因分析(详细)
通过逆向分析存档二进制结构,发现:
1. `save1.dat` 实际上是 **ONScripter v201 格式**的存档(不是原版 NScripter 格式),但**缺少 `ONS` 文件头**。这说明 Bottles 下运行的 `Tsukihime.exe` 内嵌了某个老版本的 ONScripter 兼容层。
2. OnscripterYuri 的 `loadSaveFile` 函数在检测不到 `ONS` 魔数头时,会将 `file_io_buf_ptr` 重置为 0,然后以**当前最新版本 v2.08** 格式解析整个文件。
3. v201 和 v208 的存档格式存在以下关键差异:
| 字段 | v201 | v208 |
|------|------|------|
| ONS 文件头 | 无 | `ONS` + 2 字节版本号 |
| tachi 区域末尾 | 无额外数据 | 追加 3 个 int32 (-1,-1,-1) |
| 每个 sprite | 4 个 int32 (x,y,vis,cell) | 5 个 int32 (多一个 trans) |
| sprite2 区域 | 不存在 | 256 个扩展精灵数据 |
| humanpos/underline | 不存在 | 5 个 int32 |
| page tags | 不存在 | num_page 个字符串 |
4. 由于 1000 个 sprite 每个少读一个 int (trans 字段),到 sprite 区域结束时累积偏移量已偏差 4000 字节,后续所有字段读取全部错位,导致程序崩溃。
### 解决
编写了 Python 转换工具 `convert_save.py`,将 v201 存档升级为 v208 格式:
- 添加 `ONS 2.08` 文件头
- 补全每个 sprite 的 trans 字段(默认 256 = 完全不透明)
- 补全 tachi 区域的 -1,-1,-1 标记
- 补全 sprite2 默认数据(256 个空精灵)
- 补全 humanpos/underline 默认值
- 补全 page tags 空数据
- version_indicator 从 1 升级为 2 (NSC >= 2.96)
转换结果:
- 输入:25172 字节 (v201, 无头)
- 输出:37710 字节 (v208, 带 ONS 头)
原始存档备份为 `save1.dat.bak`。
**后续如有新存档需要转换,运行:**
```bash
cd ~/Downloads/tsukihime
python3 convert_save.py
```
---
## 最终运行方式
```bash
cd ~/Downloads/tsukihime
./onsyuri --enc:gbk --fullscreen
```
### 文件清单
| 文件 | 说明 |
|------|------|
| `onsyuri` | OnscripterYuri v0.7.6 Linux x64 二进制 |
| `default.ttf` | Noto Sans CJK SC 中文字体(替换原 default.TTF) |
| `default.ttf.bak` | 原始字体备份 |
| `convert_save.py` | 存档格式转换工具 (v201 -> v208) |
| `save1.dat` | 转换后的 v208 存档 |
| `save1.dat.bak` | 原始 v201 存档备份 |
---
## 总结
| 问题 | 根因 | 解决方案 |
|------|------|----------|
| BGM 无声 | Wine MCI 实现不完整 | 改用 OnscripterYuri 原生运行 |
| 字体找不到 | Linux 大小写敏感 | 创建小写符号链接 |
| 文字空方块 | 字体缺少中文字符映射 | 替换为系统 Noto CJK 字体 + `--enc:gbk` |
| 加载存档闪退 | 存档为 v201 格式,被强制以 v208 解析导致字段错位 | 编写转换工具升级存档格式 |
linux有够折腾,如果是两年前,我只是觉得哎呀我不会配置,玩不了这个游戏算了,是我不想学。现在让ai来改,ai又是改字体文件,又是改bgm文件,又是推荐改用ones替代bottle啥的,还敢手写存档转换器,彻底暴露了linux真不是人用的。正常人大概在随意哪一步都提前放弃了 |
|