Linux 也要玩中二节奏!

发布于 2025-09-26 20:21 更新于 2026-09-26 21:10 1821 字 10 min read

Linux 上也许能玩中二节奏?Proton + WineD3D + Lutsir 成功运行!

Linux 也要玩中二节奏!

环境: CachyOS (Arch-based) / KDE Plasma 6 (Wayland) / Wine GE-Proton11-7 (umu-launcher) / Lutris

硬件: 联想小新 2022 (Intel i5-12500H + Iris Xe 核显 & NVIDIA RTX 3060 Laptop)

外设: 基于 LINGNITHM 3.2 的自制手台 (CDC 串口触摸 + HID 键盘 AIR)

游戏: CHUNITHM Mate (SDHD 2.50) + fufubot segatools


0. TL;DR

项目结论
Wine 版本GE-Proton11-7 (umu 启动) , 必须用 wined3d (DXVK 启动即崩)
渲染PROTON_USE_WINED3D=1 + winmm=n,b + d3d*/dxgi 全部 b (builtin)
独显__NV_PRIME_RENDER_OFFLOAD=1 + __GLX_VENDOR_LIBRARY_NAME=nvidia
帧数wined3d 下默认跑到最高帧数, 用 mangohud fps_limit=120 锁定 120
触摸面板直连串口 (Wine 内 COM1 → /dev/ttyACM0) , segatools [slider] enable=0
AIR面板 AIR 走 HID 键盘 (小键盘 1–6 → vkey 0x61–0x66) , segatools [io3] ir=0 + [ir] ir1..6=0x61..0x66
wine 中文问题segatools.ini 里不能写中文注释!Wine 的 INI 解析器会把中文注释的下一行配置整行吞掉
启动Lutris 正常启动 (start.bat) ;预启动脚本做 COM1 映射

1. 软硬件栈

1.1 硬件

  • 面板: 基于 LINGNITHM 3.2 的自制手台:
    • Interface 0 = CDC 串口 (/dev/ttyACM0, by-id usb-SparkFun_..._if00) → 触摸输入, 游戏直接读串口
    • Interface 2 = HID 键盘 → AIR 传感器, 按键 = 小键盘 1–6 (KP_1~KP_6)
  • GPU: Intel Iris Xe (核显) + NVIDIA RTX 3060 Laptop (独显, 需 PRIME offload 才能用上)
  • 屏幕: 笔记本自带 1920x1080@165Hz (支持 60/165 切换)

1.2 软件

组件版本备注
WineGE-Proton11-7 (wine 11.0 内核)通过 umu-run 启动
umu-launcher1.4.3steamrt4 容器
segatoolsfufubot 1.0.4 定制版chusanhook.dll / chusanamhook.dll / chuniio-mux.dll 等

2. 部署流程 (从零到能玩)

2.1 游戏本体

参考 Evilleaker 的教程:

  1. 在 Windows 上安装并保证可以正常运行
  2. 对游戏文件打补丁绕过 1080P 和 120hz 检测
  3. 把游戏目录拷贝到 Linux 上

2.2 触摸面板 COM1 映射 (关键)

游戏直接读串口拿触摸数据, 所以要在 Wine prefix 里把 COM1 指向面板的串口设备。

预启动脚本 scripts/wine-com1-map.sh (Lutris 的 prelaunch_command):

#!/usr/bin/env bash
set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GAME_DIR="$(dirname "$SCRIPT_DIR")"
LOG="$GAME_DIR/com1-map.log"
WINEPREFIX="${WINEPREFIX:-$GAME_DIR/wine/pfx}"
PORTS="${CHUNI_COM_PORTS:-1}"
log() { printf '%s [com1-map] %s\n' "$(date '+%F %T')" "$*" >>"$LOG"; }
DEV="${CHUNI_COM_DEV:-}"
if [ -z "$DEV" ]; then
    for candidate in \
        $(ls -1 /dev/serial/by-id/* 2>/dev/null | head -n1) \
        $(ls -1 /dev/ttyUSB* 2>/dev/null | head -n1) \
        $(ls -1 /dev/ttyACM* 2>/dev/null | head -n1) \
        $(ls -1 /dev/ttyS[0-9]* 2>/dev/null | head -n1) ; do
        if [ -n "$candidate" ] && [ -e "$candidate" ]; then DEV="$candidate"; break; fi
    done
fi
if [ -z "$DEV" ]; then log "WARN 未找到串口设备,游戏继续启动"; exit 0; fi
DOSDEV="$WINEPREFIX/dosdevices"
[ -d "$DOSDEV" ] || DOSDEV="$GAME_DIR/wine/dosdevices"
[ -d "$DOSDEV" ] || { log "ERROR 找不到 dosdevices"; exit 0; }
if [ ! -r "$DEV" ] || [ ! -w "$DEV" ]; then
    log "WARN $DEV 不可读写(请加入 uucp 组并重新登录)"
fi
for p in $PORTS; do
    link="$DOSDEV/com$p"
    if [ -e "$link" ] && [ ! -L "$link" ]; then log "SKIP com$p 非符号链接"; continue; fi
    rm -f "$link"; ln -s "$DEV" "$link"
    if [ -L "$link" ]; then log "OK   com$p -> $DEV"; else log "ERROR 创建 $link 失败"; fi
done
exit 0

注: 面板不在时脚本会 回退到 /dev/ttyS0 (主板自带串口), 游戏会打开一个滚木串口导致 3100 检测不到控制器错误

2.3 Lutris 配置

~/.local/share/lutris/games/chunithm.yml:

game:
  exe: /path/to/Chunithm/bin/start.bat
  prefix: /path/to/Chunithm/wine/pfx
  working_dir: /path/to/Chunithm/bin
system:
  env:
    PROTON_USE_WINED3D: "1" # DXVK 笔者尝试了很久依然会崩
    __NV_PRIME_RENDER_OFFLOAD: "1" # 独显
    __GLX_VENDOR_LIBRARY_NAME: "nvidia" # 独显
    MANGOHUD_CONFIG: fps_limit=120 # 锁 120fps
  mangohud: true
  prelaunch_command: /path/to/Chunithm/scripts/wine-com1-map.sh
  prelaunch_wait: true
  pulse_latency: true
wine:
  overrides:
    d3d8: b
    d3d9: b
    d3d10core: b
    d3d11: b
    d3d12: b
    d3d12core: b
    dxgi: b
    winmm: n,b
  version: GE-Proton11-7-x86_64

3. 按键链路原理

flowchart LR
    subgraph AIR["AIR 传感器 通路"]
        A1["面板 AIR 传感器"] -->|HID| A2["Linux input"]
        A2 --> A3["X11"]
        A3 --> A4["Wine (X11DRV)"]
        A4 --> A5["GetAsyncKeyState(0x61..0x66)"]
    end

    subgraph GAME["游戏进程 (chusanApp)"]
        G1["游戏"] --> G2["chusanhook.dll"]
        G2 --> G3["chuniio-mux.dll"]
        G3 --> G4["chuniio.dll"]
    end

    G4 -. "每帧轮询" .-> A5

    subgraph TOUCH["触摸 通路"]
        T1["触摸"] -->|CDC 串口| T2["/dev/ttyACM0"]
        T2 -->|符号链接| T3["Wine COM1"]
        T3 --> T4["游戏直接读串口"]
    end
  • AIR 轮询: chuniio.dll 每帧调用 GetAsyncKeyState(vk_ir[i]), 不是消息。所以:
    • 按键必须进入 Wine 的键盘状态 (窗口有焦点时才会更新)
  • NumLock 必须开: 否则小键盘 1–6 的 vkey 不是 0x61–0x66 而是方向键 (VK_END 等)
  • [io3] ir 语义 (segatools 源码 chuniio/config.c):
    • ir=0: 使用 [ir] 段的 6 个独立键
    • ir=0x20: 空格模拟 AIR

4. 踩坑全记录

4.1 最大的坑: Wine 的 INI 解析器吞掉中文注释的下一行

症状:

  • AIR 传感器按了没反应
  • 但按空格反而能触发 AIR

根因: AI 排错时在 segatools.ini 里写一行中文注释 (UTF-8 多字节):

; 0 = 使用下方 [ir] 的独立 AIR 键位 (LINGNITHM 面板 AIR 走 HID 键盘)
ir=0

Wine 的 GetPrivateProfileIntW 解析器会把中文注释的下一行 (ir=0) 整行吞掉, 于是游戏读不到 ir, 回退到**默认值 0x20 (空格) ** → 进入”空格模拟 AIR”模式:

  • 空格能触发 AIR (虚拟手位置扫描)
  • 小键盘/面板 AIR 全都不响应

结论:

segatools.ini 请只用 ASCII (英文) 注释。 中文注释在 Windows 下没问题 (Windows 的 INI 解析器行为不同) , 但在 Wine 下会吞掉下一行配置。

4.2 游戏默认跑在核显导致帧数低

Wine 默认跑在 Intel 核显上。可以用 glxinfo 验证:

# Intel
glxinfo -B | grep "OpenGL renderer"   # → Mesa Intel(R) Iris(R) Xe Graphics

# NVIDIA
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia \
  glxinfo -B | grep "OpenGL renderer"  # → NVIDIA GeForce RTX 3060 Laptop GPU

把这两个变量写进 Lutris 的 env 即可 (mangohud 里能看到 NVIDIA 的占用率) 。

4.3 DXVK 启动白屏后静默退出

笔者为了性能试过把渲染从 wined3d 换成 DXVK:

  • DXVK 初始化成功 (日志能看到 Creating device: NVIDIA GeForce RTX 3060、 Setting display mode: 1920x1080@120、Present mode: FIFO)
  • 但游戏在交换链创建完成后立刻静默退出, 只能观测到白屏一闪就消失

结论: 这个游戏 + GE-Proton11-7 + DXVK 3.1 的组合下 DXVK 不可用, 只能用 wined3d。

4.5 wined3d 性能与 120fps 锁定

  • wined3d 虽然是 OpenGL 翻译层, 但在 RTX 3060 上将将够用
  • 音游的判定与帧挂钩, 需要稳定 120fps (游戏内是 120fps 模式)
  • 由于笔记本屏幕只有 60/165Hz 两档 (没有 120Hz 模式) , 用 mangohud 的帧率限制器锁 120:
system:
  env:
    MANGOHUD_CONFIG: fps_limit=120

5. 附录

5.1 start.bat 内容 (参考)

@echo off
set OPENSSL_ia32cap=:~0x20000000
pushd %~dp0
taskkill /f /im amdaemon.exe > nul 2>&1
start /min inject_x64.exe -d -k chusanamhook.dll amdaemon.exe -f -c config_common.json ...
inject_x86.exe -d -k chusanhook.dll -k duolinguo.dll chusanApp.exe
taskkill /f /im amdaemon.exe > nul 2>&1
echo Game processes have terminated
pause

5.2 坑合集

#症状根因修复
1AIR 全无反应、空格却能触发Wine 吞掉中文注释的下一行 → ir 回退默认值 0x20注释改 ASCII
2键盘没反应按键进了控制台窗口 (焦点问题)点游戏窗口 / 全屏
3帧数 60、GPU 20%跑在核显上PRIME offload 环境变量
4DXVK 白屏即崩DXVK 3.1 与游戏不兼容用 wined3d
5Lutris 启动即停game-paths.json 残留清空该文件
6触摸失效面板 USB 掉线 / COM1 映射错误重插面板
7帧率浮动 (60/165)vsync 跟随屏幕刷新率mangohud fps_limit=120
8启动慢 (3 分钟+)正常模式首次加载曲库数据库属正常, 等它加载完

本文档由排错过程中的实测数据整理, 所有结论均在 Arch + KDE Wayland + GE-Proton11-7 环境验证。

6. 结语

就这样,笔者的大学时光被出勤打舞萌和中二节奏毁了。

BTW I use Arch.

喜欢的话,留下你的评论吧~