# portmaster_chrono **Repository Path**: windstarry/portmaster_chrono ## Basic Information - **Project Name**: portmaster_chrono - **Description**: 开源掌机移植游戏超时空之轮 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-25 - **Last Updated**: 2026-06-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Chrono Trigger Android 移植项目 > **本项目基于 [felc18-blip/nextos_ports_android](https://github.com/felc18-blip/nextos_ports_android) 进行移植和扩展。** > **非 PortMaster 移植** — 通过 so-loader 运行 Android 二进制文件。PortMaster 仅用于启动/打包。 将《chrono Trigger》(Android版) 移植到 ARM64 Linux 设备 (Rocknix/Mali G31) 的完整解决方案。 ## 📋 项目简介 本项目使用 **so-loader 技术** 将 Chrono Trigger Android 版 (Cocos2d-x 3.14.1 引擎) 移植到 Rocknix 设备 (XiFan XF35H, Mali Bifrost G31)。通过手动加载 Android 原生库 `libchrono.so` 并模拟 JNI 环境,实现在 Linux 系统上运行原本为 Android 设计的应用。 ### 🎯 核心特性 - ✅ **完整渲染**: GLES2 1280x720 渲染 (标题画面 → 菜单 → 游戏) - ✅ **物理控制器**: 原生支持 Xbox 标准控制器 (通过 SDL2) - ✅ **音频系统**: OpenSL ES → SDL2/PulseAudio 音频桥接 - ✅ **中文本地化**: 支持中文简体显示 (语言代码=6) - ✅ **双字体回退**: LiberationSans (Latin) + DroidSansFallback (CJK) - ✅ **PortMaster 兼容**: 符合 PortMaster 打包标准 ## 🏗️ 技术架构 ### 核心组件 | 组件 | 功能描述 | |------|----------| | `so_util.c/h` | ELF 手动加载器 (支持 AArch64, RELR 重定位) | | `jni_shim.c/h` | 假 JNI 环境 (模拟 Android JNI 调用) | | `imports.c/h` | bionic→glibc 桥接层 (处理 Android 特有函数) | | `main.c` | 主加载流程: load → relocate → resolve → init_array → JNI_OnLoad → main loop | | `opensles_shim.c/h` | OpenSL ES → SDL2 音频桥接 | | `text_render.c` | FreeType 文本渲染 (支持双字体) | ### 技术栈 - **编译环境**: Docker (aarch64-linux-gnu-gcc 10.2.1 / Ubuntu 20.04) - **图形**: OpenGL ES 2.0 / SDL2 - **音频**: OpenSL ES to SDL2/PulseAudio - **文本**: FreeType 2.x - **构建工具**: CMake / Ninja / Docker+QEMU ## 📦 构建指南 ### 前置要求 - Docker (推荐) 或 aarch64-linux-gnu 交叉编译工具链 - FreeType 开发库 - SDL2 开发库 ### 使用 Docker 构建 (推荐) ```bash cd chrono/ docker build --no-cache --platform linux/arm64 -t chrono-builder . # 提取编译产物 docker run --rm -v "$(pwd)/output:/output" chrono-builder \ cp /build/chrono /output/chrono ``` ### 本地构建 ```bash cd chrono/ ./build.sh ``` 编译输出: `chrono/` 目录下的 `chrono` 二进制文件 (约 160KB) ## 🚀 部署指南 ### 文件结构 部署到目标设备 (`/storage/roms/ports/chrono/`): ``` /storage/roms/ports/chrono/ ├── chrono # 主程序二进制 ├── libchrono.so # Android 原生库 (从 APK 提取) ├── libc++_shared.so # Android C++ 运行时 ├── libencrypt.so # 资源解密库 ├── assets/ # 游戏资源 (从 APK 提取) │ ├── 001.dat - 008.dat │ ├── 007-en.dat # 英文字符串表 │ ├── Shaders/ # GLSL ES2 着色器 │ └── Game/ # 游戏数据 ├── Roboto-Regular.ttf # Latin 字体 └── DroidSansFallback.ttf # CJK 字体 ``` ### 使用部署脚本 **最终部署** (推荐): ```bash python3 deploy_final.py ``` **中文语言包部署**: ```bash python3 deploy_chinese.py ``` ### 手动部署 1. 将编译好的 `chrono` 二进制上传到设备 2. 从 Chrono Trigger APK 提取 `libchrono.so`, `libc++_shared.so`, `libencrypt.so` 3. 提取 APK 中的 `assets/` 目录 4. 复制字体文件到游戏目录 ## ⚙️ 配置说明 ### 启动脚本 使用 PortMaster 标准启动脚本 (`Chrono Trigger.sh`): ```bash #!/bin/bash # PortMaster 启动脚本 export HOME="$GAMEDIR" export LD_LIBRARY_PATH="/usr/lib:$GAMEDIR" # NEVER force SDL_VIDEODRIVER/SDL_AUDIODRIVER # SDL2 会自动选择合适的驱动 cd "$GAMEDIR" ./chrono ``` ### 环境变量 | 变量 | 说明 | 默认值 | |------|------|--------| | `CHRONO_LOC` | 语言代码 (0=ja, 1=en, 6=zh-Hans) | 6 (中文简体) | | `CHRONO_FONT` | 自定义字体路径 | 内置 Roboto | | `CHRONO_AUTOPRESS` | 自动点击测试 (调试) | 0 | | `CHRONO_TEXTLOG` | 文本渲染日志 (调试) | 0 | | `CHRONO_JNILOG` | JNI 调用日志 (调试) | 0 | | `CHRONO_ABUF` | 音频缓冲区大小 (KB) | 32 | | `CHRONO_GAIN` | 音频增益 (0.0-1.0) | 0.65 | ## 🐛 已知问题与解决方案 ### 问题 1: GLIBC_2.43 not found **现象**: `./chrono: /usr/lib/libm.so.6: version 'GLIBC_2.43' not found` **原因**: 目录中存在旧的预编译二进制 **解决**: 使用 Docker 重新编译 (Ubuntu 20.04, glibc 2.31) ### 问题 2: SDL 视频驱动不可用 **现象**: 所有 SDL_VIDEODRIVER 都不可用 **原因**: 直接运行 `./chrono` 缺少 PortMaster 环境 **解决**: 必须通过 `Chrono Trigger.sh` 启动 ### 问题 3: __vsnprintf_chk 无限递归 (已修复) **现象**: SIGSEGV 崩溃 **原因**: glibc 2.40 与 bionic 符号冲突 **解决**: 删除 `imports.c` 中的 `__vsnprintf_chk` 和 `__vsprintf_chk` 定义 ### 问题 4: 字体缺失 (方块字符) (已修复) **现象**: 游戏显示方块 (□□□) **原因**: 设备缺少字体或 FreeType 兼容性问题 **解决**: 实现双字体回退机制 (LiberationSans + DroidSansFallback) ### 问题 5: 音频卡顿 (已修复) **现象**: 音频播放不流畅 **原因**: 音频缓冲区过浅 **解决**: 固定缓冲区 32KB + 专用音频线程 ## 📁 项目结构 ``` chrono-port/ ├── chrono/ # 主项目目录 │ ├── src/ # C 源代码 │ │ ├── main.c # 主加载器 │ │ ├── so_util.c # ELF 加载器 │ │ ├── jni_shim.c # JNI 模拟 │ │ ├── imports.c # bionic 桥接 │ │ ├── opensles_shim.c # 音频桥接 │ │ ├── text_render.c # 文本渲染 │ │ └── util.c # 工具函数 │ ├── build.sh # 本地构建脚本 │ ├── build_docker.sh # Docker 构建脚本 │ ├── Chrono Trigger.sh # PortMaster 启动脚本 │ ├── Dockerfile # Docker 构建定义 │ ├── README.md # 原版 README (葡萄牙语) │ └── HANDOFF.md # 开发日志 ├── deploy_chinese.py # 中文部署脚本 ├── deploy_final.py # 最终部署脚本 ├── fix_encoding.py # 编码修复工具 ├── patch_clean.py # 补丁清理工具 ├── LESSONS.md # 经验总结 └── lib/ # 依赖库 └── *.so # 预编译共享库 ``` ## 🔧 开发指南 ### 修改语言设置 编辑 `src/main.c`: ```c // 修改默认值 int chrono_forced_lang() { return 6; // 6 = zh-Hans (中文简体) } ``` 编辑 `src/jni_shim.c`: ```c // 修改 getLocationCode 返回值 jint getLocationCode(JNIEnv *env, jobject obj) { return 6; // 6 = zh-Hans } ``` ### 添加调试日志 ```c // 在 relevant 源文件中添加 debugPrintf("debug: variable=%d\n", value); ``` 查看日志: ```bash cat /storage/roms/ports/chrono/debug.log ``` ### 编译选项 修改 `build.sh` 或 `Dockerfile` 中的编译标志: ```bash CFLAGS="-O2 -g -DDEBUG" # 调试版本 CFLAGS="-O3" # 优化版本 ``` ## 📝 技术细节 ### so-loader 工作流程 1. **加载**: `so_load()` 读取 ELF 文件,分配内存 2. **重定位**: `so_relocate()` 处理动态重定位 (RELR/AARCH64) 3. **解析**: `so_resolve()` 解析导入符号 4. **初始化**: 调用 `init_array` 中的构造函数 5. **JNI 初始化**: 调用 `JNI_OnLoad` 6. **主循环**: `nativeInit()` → `nativeRender()` → `SDL_GL_SwapWindow()` ### JNI 模拟实现 关键 JNI 函数实现: - `GetStringChars()` / `ReleaseStringChars()` (UTF-16) - `NewByteArray()` / `SetByteArrayRegion()` - `CallStaticObjectMethod()` - `GetMethodID()` / `GetStaticMethodID()` ### 控制器映射 SDL 控制器事件 → Cocos2d-x 控制器事件: ```c SDL_CONTROLLER_BUTTON_A → nativeControllerButtonEvent(1004) SDL_CONTROLLER_BUTTON_DPAD_RIGHT → nativeControllerButtonEvent(1013) ``` ## 🤝 贡献指南 ### 提交规范 - 保持 master 分支稳定 - 不包含 co-author 信息 - 提交信息使用英文或中文 ### 测试清单 - [ ] 图像渲染正常 (标题/菜单/游戏) - [ ] 控制器输入响应 - [ ] 音频播放流畅 - [ ] 文本显示正确 (中/英/日) - [ ] 无内存泄漏 - [ ] 无崩溃 (0 SIGSEGV) ## 📚 参考资料 - [Cocos2d-x 3.14.1 文档](https://docs.cocos.com/cocos2d-x/v3/) - [Android NDK ABI](https://developer.android.com/ndk/guides/abis) - [PortMaster 文档](https://portmaster.games/) - [GLIBC 符号版本控制](https://www.gnu.org/software/libc/manual/html_node/Symbol-Versioning.html) ## 📄 许可证 本项目仅提供技术实现代码。Chrono Trigger 游戏内容版权归 Square Enix 所有。 **BYO-data**: 您需要合法拥有 Chrono Trigger Android 版 APK 才能使用本项目。 ## 致谢 本项目基于 **[felc18-blip/nextos_ports_android](https://github.com/felc18-blip/nextos_ports_android)** 进行移植和扩展。 核心源自 **[syberia_arm64](https://github.com/mtojek/syberia_arm64)** 和 **[lswtcs_arm64](https://github.com/mtojek/lswtcs_arm64)**(**mtojek**,**Apache-2.0** 许可)。此框架将该方法通用化。 --- **最后更新**: 2026-06-25 **项目状态**: ✅ 生产可用 (图像+控制器+音频+中文)