Skip to content

fix(libretro): 支持模拟摇杆方向输入,修复 RetroArch 中无法移动的问题 - #129

Merged
AloysHF merged 1 commit into
masterfrom
fix/libretro-analog-stick-input
Sep 27, 2026
Merged

AloysHF merged 1 commit into
masterfrom
fix/libretro-analog-stick-input

Conversation

@AloysHF

@AloysHF AloysHF commented Sep 27, 2026

Copy link
Copy Markdown
Owner

问题与影响

RetroArch 加载《赤刃》EPOP/EBBLADE.smf 后,模拟摇杆无法控制角色移动;独立版模拟器的实体摇杆正常。

核心原先只接收十字键方向和 A/B 按键。当 RetroArch 没有开启 Analog to Digital Type(模拟摇杆转十字键) 时,手柄摇杆轴输入没有进入游戏,角色位置不变。这个缺失影响核心的方向输入,并非《赤刃》专属逻辑。

原因与历史定位

query_joypad_buttons() 只调用 input_state(port, RETRO_DEVICE_JOYPAD, 0, id),从未读取 RETRO_DEVICE_ANALOG 的 X/Y 轴。

  • 首次加入 libretro 核心的提交 9feda2de74bad206377f9f680516f05d57e7af6c(2026-06-06)就只有十字键和 A/B 映射。
  • 后续工作区重构和输入处理修复也没有增加模拟摇杆轴读取。因此,这是一直存在的功能缺失,不是近期修改移除了已有支持。
  • 独立版在 be5ea41(2026-09-13)通过 gilrs 添加了实体手柄支持;libretro 前端没有同步实现对应的轴映射。
  • 如果旧版曾经可以使用摇杆,一种可能解释是 RetroArch 在前端把摇杆转换成了十字键。此处是可能原因,不代表已确认反馈者过去的配置。

修改方案

  1. 每帧通过 libretro 输入回调读取端口 0 的左右摇杆 X/Y 轴,补齐标准摇杆索引和轴 ID 常量。
  2. 将两根摇杆映射到 Native32 的四个方向,使用约 50% 死区:只有轴值严格超过 ±0x4000 才触发方向,中心及阈值以内不触发。
  3. 按 libretro 的 Y 轴约定映射上下方向:负值向上、正值向下。独立版 gilrs 的 Y 轴符号不同,因此不能直接照搬其判断。
  4. 将十字键和双摇杆方向合并,同一方向只产生一个 Native32 keycode;斜向保留两个独立方向值,避免重叠 keycode 被当成位掩码。
  5. 输入继续进入现有 set_buttons() 路径,保持 A/B 映射、交换选项及自动重复处理。
  6. 更新 README 和 RetroArch 使用文档,说明双摇杆、死区及无需前端模拟转数字设置。

效果与验证

修复后,核心自身支持左右摇杆控制移动,无需依赖 RetroArch 的模拟摇杆转十字键设置。用户已在 RetroArch 中验证修复有效。

自动化回归

  • 覆盖双摇杆的四方向、斜向、中心状态、死区边界和刚超过边界的输入。
  • 覆盖十字键与左右摇杆同时输入时的方向去重,以及 A/B 按键兼容性。
  • 新增需要本地游戏资源的回归测试:从 EPOP/EBBLADE.smf 启动,隔离存档并通过真实场景切换进入 BBPLAY10.SSL,从同一初始状态分别测试双摇杆的四方向,断言角色坐标朝正确方向变化,并与十字键的移动结果比较。
  • 禁用轴读取以模拟旧输入路径时,该回归测试失败,角色坐标保持 (53, 188);启用修复后通过。
  • 默认 CI 不包含游戏资源,因此真实游戏测试标为 #[ignore],在本地显式运行;资源和生成的 DLL 不提交到仓库。

本地真实游戏回归中,每个方向保持 30 帧,左右摇杆均得到以下结果:

输入 初始坐标 最终坐标
左 (53, 188) (14, 188)
右 (53, 188) (125, 188)
上 (53, 188) (53, 152)
下 (53, 188) (53, 213)

此外,通过 ctypes 加载发布版 DLL,调用实际导出的 retro_load_game、retro_run 和存档接口,注入 libretro 输入回调,验证了双摇杆四方向均能移动。该验证属于回调模拟输入;实体手柄的 RetroArch 验证由用户完成。

已完成检查

  • cargo test --workspace
  • cargo test -p native32emu-libretro -- --include-ignored(包括《赤刃》回归,4 项通过)
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • cargo build -p native32emu-libretro --release
  • 发布版 DLL 的实际 libretro API 回调验证
  • 用户在 RetroArch 中验证通过

@AloysHF
AloysHF merged commit 18a811f into master Sep 27, 2026
4 checks passed
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant