luohoa97/cordial
GitHub: luohoa97/cordial
Cordial 是一个 Linux 兼容性运行时,通过自建 Android 运行时层直接加载 Roblox 官方 x86-64 引擎实现原生运行,无需模拟器或容器。
Stars: 0 | Forks: 0
# 在 Linux 上原生运行 Roblox — 插件,全为你而来。
Cordial 通过专门构建的 runtime 将 Roblox 官方的 Android x86-64 引擎直接加载到 Linux 上:包含 AOSP bionic linker、bionic/glibc shim、替代 Android 原生环境的 JNI VM,以及响应客户端调用的 framework 层。没有模拟器,没有容器,也没有虚拟机。它像任何原生应用程序一样,通过 Vulkan 或 GLES2 与你的 GPU 进行通信。
## 开始使用
- [阅读文档 📖](docs)
- [从这里开始 — 哪些可用,哪些受阻 🧭](docs/NEXT.md)
- [安装它 🔽](#install)
- [实际工作原理 🔬](docs/findings.md)
- [为什么永远不会有脚本执行 🔒](docs/adr/ADR-001-in-process-hooking.md)
- [报告 bug 🐛](https://github.com/luohoa97/cordial/issues)
- [贡献 🛠️](CONTRIBUTING.md)
**第一次来?** 请先阅读下方的警告,然后阅读
[`docs/NEXT.md`](docs/NEXT.md) — 这是为初次接触该项目的人编写的,
清楚地说明了哪些功能损坏了,以及哪些已经被排除。
### 声明
**这不是官方的 Roblox 客户端。本项目绝未得到 Roblox Corporation 的认可或赞助。** Roblox 是 Roblox Corporation 的商标。
**它由 [Claude Code](https://claude.com/claude-code) 在两天内构建** —
即 Anthropic 的 Claude,Opus 5 模型 — 其架构由与它并肩工作的人类指导。
这不是脚注。这就是为什么 commit 消息很长,为什么 `docs/` 会像记录有效的
内容一样仔细地记录被证伪的内容,以及为什么没有人应该假设人类审查了每一行代码。
工程是真实的,每一个发现都是通过运行该程序而不是对其进行推理来验证的。
只不过它目前仅仅存在了两天。
### 我们不支持利用(exploiting)
Cordial 是一个兼容性 runtime,而不是作弊工具,**我们不支持或容忍使用它来利用 Roblox 或在其上运行的任何体验。**
这不仅仅是一个立场,更是构建的属性。Cordial 没有脚本执行器,没有 hooking,没有对 Roblox 进程的内存访问,也没有任何 API 可以让插件请求这些功能 — 不是被禁用,而是*根本不存在*,因此在二进制文件中没有可以在 fork 中提取或重新启用的原语。插件在 capability broker 后台的独立进程中运行,无法读取 Cordial 的内存,更不用说 Roblox 的内存了。原因详见
[ADR-001](docs/adr/ADR-001-in-process-hooking.md) 和
[ADR-003](docs/adr/ADR-003-plugin-isolation.md),这是刻意作为承重设计的:限制可以在 fork 中解除,但从未构建的 capability 则不能。
如果你想要一个执行器,你来错项目了,添加执行器的 pull request 将会被拒绝。
## 状态:早期。它可以运行和渲染;但你目前无法登录。
| | |
|---|---|
| 原生加载 `libroblox.so` | ✅ |
| App shell 到达 `APP_READY (Landing)` | ✅ |
| 渲染 — Vulkan,带有 GLES2 回退 | ✅ |
| 网络 / HTTPS | ✅ |
| 鼠标和键盘输入到达引擎 | ✅ |
| 稳定性 | ✅ 连续 26 次干净启动 |
| 帧率 | ✅ 在 Vulkan 上稳定在约 27 fps(GLES 回退要慢得多) |
| 登录 | ❌ 未实现 |
| 插件 | ❌ 已设计,未构建 |
使用 `vkQueuePresentKHR` 测量:在三次运行中,24 秒内分别呈现了 656、656 和 655 次,不受注入输入的影响 — 因此它是持续渲染而不是按需渲染。GLES 回退路径要慢得多(约 1 fps),对于没有 Vulkan 的主机来说这是一个单独的未决问题;请参阅 [`docs/NEXT.md`](docs/NEXT.md)。
目前的阻碍是登录。没有会话,客户端会停留在已注销的着陆页上,因此没什么可做的。
**不要指望安装这个来玩 Roblox。** 如果你想参与开发,才安装它。
## 安装
### 1. 你需要什么
- x86-64 Linux
- **Clang** — AOSP bionic 在 C++ 头文件中使用 C11 `_Atomic`,而 GCC 会拒绝它
- X11 会话(Wayland 通过 XWayland 工作)
- Roblox 的官方 Android 客户端,**由你提供** — Cordial 不提供 Roblox 代码、APK 或资产,以后也绝不会提供
从已安装的 APK 中,你需要 `lib/x86_64/` 对象和基础 APK。
### 2. 构建它
Flatpak 是预期的安装方式。目前还没有托管的远程仓库,因此从源码构建:
```
git clone --recursive https://github.com/luohoa97/cordial
cd cordial
packaging/build-flatpak.sh --install
```
对于开发,跳过 Flatpak 并直接构建 loader:
```
git clone --recursive https://github.com/luohoa97/cordial
cd cordial
cargo build --release
```
### 3. 运行它
```
cargo run --release --bin cordial-load -- \
--lib-dir /path/to/lib/x86_64 --apk /path/to/base.apk \
--host-libc --game-activity --run 30
```
窗口打开,引擎启动,并以大约 27 fps 的速度渲染 Roblox 的已注销着陆页。`--run` 用于控制程序存活的秒数。
### 4. 实用的调节选项
| | |
|---|---|
| `CORDIAL_MONITOR=
` | 在第 n 个显示器而不是主显示器上打开 |
| `CORDIAL_FULLSCREEN=1` | 覆盖该显示器 |
| `CORDIAL_WINDOW_POS=,` | 显式位置,覆盖上述选项 |
| `CORDIAL_RESOLUTION=x` | 渲染分辨率,默认为 1280x720 |
| `CORDIAL_DPI_SCALE=` | Roblox 布局所基于的 UI 密度;1.0 是低密度手机 |
| `CORDIAL_ANDROID_TRACE=1` | 记录 Android API 调用 |
| `CORDIAL_COUNT_GL=1` | 在退出时报告图形调用次数 |
```
CORDIAL_MONITOR=1 CORDIAL_FULLSCREEN=1 cargo run --release --bin cordial-load -- \
--lib-dir /path/to/lib/x86_64 --apk /path/to/base.apk \
--host-libc --game-activity --run 30
```
`cordial-load --help` 列出了其余选项。
### 更改 FastFlags
Roblox 由 FastFlags 配置,Cordial 允许你覆盖它们中的任何一个。
创建 `~/.config/cordial/flags.json`(或将 `CORDIAL_FLAGS` 指向另一个文件),
包含一个扁平对象:
```
{
"DFFlagRbxTransportUseRtcioRna": false,
"FIntTaskSchedulerAutoThreadLimit": 8,
"FStringDebugGraphicsPreferredBackend": "Vulkan"
}
```
值可以写成布尔值、数字或字符串 — Roblox 将它们全
作为字符串存储,Cordial 会进行转换。这些覆盖项会被合并到引擎在启动时
读取的设置文档中,启动日志会报告已应用了多少个覆盖项。
**`FFlag`、`FInt` 和 `FString` 在启动时只读取一次**,因此更改它们
需要重新启动。只有 `DFFlag`/`DFInt`/`DFString` 系列会在客户端
运行时重新读取。如果你正在构建任何动态更改 flag 的东西,这个区别
很重要 — 在会话进行中途加载的插件无法更改启动 flag,无论它写入什么。
#### 层级与来源
Flags 来自多个地方,每个来源都有自己独立的文件:
```
~/.config/cordial/flags.json user (always wins)
~/.local/share/cordial/plugins//flags.json plugin
the client-settings document from Roblox base
```
插件永远不会写入你的文件。这确保了三件事:插件无法悄悄
覆盖你选择的值,移除插件即移除其 flags,并且“为什么这个 flag
被设置成那样?”总是有答案可循。冲突会被报告出来,
而不是被静默解决:
```
flags: FIntTaskSchedulerAutoThreadLimit = 8 from user
(overrides plugin:fps-tweaks=4, plugin:net-tuner=16)
```
两个插件不一致是真正的不一致,因此两者都会被点名。后一个生效,
因此结果是确定性的,并且没有任何东西被隐藏。
**如果界面看起来很粗糙**,那是因为它是在为低密度手机
进行布局。同时调高两者 — 渲染分辨率默认为 720p,`dpiScale` 为 1.0,
这是 Roblox 视为廉价手机的设置:
```
CORDIAL_MONITOR=1 CORDIAL_RESOLUTION=1920x1200 CORDIAL_DPI_SCALE=1.75 \
cargo run --release --bin cordial-load -- \
--lib-dir /path/to/lib/x86_64 --apk /path/to/base.apk \
--host-libc --game-activity --run 30
```
Roblox 的图形质量 FastFlags(`DebugFRMQualityLevelOverride` 和 MSAA
覆盖)经过测试,在这里没有任何改变,因为它们控制 3D 场景渲染,而已注销的着陆页是 2D 界面。分辨率和密度才是适用于它的调节杠杆。
### 5. 当出现问题时
**首先阅读引擎自身的日志。** Roblox 将其写入到
`/appData/logs/*.log`,并且它用自己的语言命名了子系统、阶段、路径和异常。它是项目中最好的诊断工具,大部分问题都可以通过该目录中最新的文件得到解答。
要检查输入是否到达引擎,请运行
`CORDIAL_ANDROID_TRACE=1` 并查找 `onTouchEventNative(...) -> true`。
## 文档
从 [`docs/NEXT.md`](docs/NEXT.md) 开始。其余的是参考。
| | |
|---|---|
| [`docs/NEXT.md`](docs/NEXT.md) | 从哪里开始,什么受阻,以及什么已经被排除 |
| [`docs/findings.md`](docs/findings.md) | 引导程序分析:架构结论和未知数 |
| [`docs/framework-api-inventory.md`](docs/framework-api-inventory.md) | framework 积压工作,从发布的 APK 中枚举 |
| [`docs/traces/`](docs/traces) | 同一 APK 在真实 Android 上的捕获 — 本项目用来核对自己的基本事实 |
| [`docs/adr/ADR-001-in-process-hooking.md`](docs/adr/ADR-001-in-process-hooking.md) | 为什么 Cordial 永远不会有进程内 hooking |
| [`docs/adr/ADR-004-plugin-asset-overrides.md`](docs/adr/ADR-004-plugin-asset-overrides.md) | 为什么插件不能替换 Roblox 的纹理或声音 |
| [`docs/adr/ADR-005-flag-service.md`](docs/adr/ADR-005-flag-service.md) | 为什么 flag 服务有两个交互面 |
| [`docs/design/path-to-a-frame.md`](docs/design/path-to-a-frame.md) | GameActivity、资产、surface |
| [`docs/design/instances-and-launch.md`](docs/design/instances-and-launch.md) | 多实例、多账户、`roblox://` 处理 |
| [`docs/base-evaluation.md`](docs/base-evaluation.md) | 对现有技术的移植与重写评估 |
| [`docs/multiarch.md`](docs/multiarch.md) | 多架构决策 |
## 主要发现
**Roblox 发布了完整的 x86-64 Android 构建。** `split_config.x86_64.apk`
包含 `lib/x86_64/libroblox.so` — 116 MB 的 x86-64 机器代码,由 NDK
r28c 构建。Cordial 原生执行它,并且**不需要 CPU 架构转换**,
只需要 CPU *特性*模拟。这就是一个可处理的系统项目与一个规模大一个数量级的项目之间的区别。
**Runtime 表面是有边界的:**链接了 13 个 Android 库,644 个未定义的符号,强制要求 GLES2 + EGL,并通过 `dlopen` 将 Vulkan 作为可选升级。
**Roblox 的游戏交互面是 AGDK `GameActivity`**,它是 Apache-2.0 开源
的 — 因此可以读取 activity、surface、input 和 IME 契约,而不是
去推断。
## 永久不在范围内
没有针对 Roblox 进程的进程内代码执行:没有 hooking,没有内存
修补,没有注入的脚本环境。不是“默认禁用” — 从 API 词汇中缺失,因此二进制文件中没有可提取的注入原语。推理详见 [ADR-001](docs/adr/ADR-001-in-process-hooking.md)。
同样被排除的还有:客户端完整性 flags 或水印,以及将混淆作为安全手段。
## 许可证
GPL-3.0-or-later。请参阅 [`LICENSE`](LICENSE)。
第三方组件保留其自己的许可证和声明, reproduced in
[`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md) 并由 Flatpak 随
二进制文件一起安装:
- [`third_party/libbadcpu`](third_party/libbadcpu) — MIT,源自
[Sober OSS](https://github.com/Z3ki/sober-oss)
- `mcpelauncher-linker` — MIT,ChristopherHX 和 MCMrARM
- AOSP bionic,包含在其中 — Apache-2.0 和 BSD
- `libjnivm` — MIT,ChristopherHX
只要组合作品在 GPL 下提供,并同时附带这些声明,
即满足 MIT 和 Apache-2.0 的要求。这是一个条件,而不是
客套。标签:Roblox, 兼容层, 可视化界面, 图形渲染, 安卓兼容, 运行时, 通知系统