# Phigros 4.0.1.2 安卓资源到静态网页的分析与迁移记录

本文件保留初版资源调查记录。后续 V2 的界面重建、bug 修复、生命周期与网页性能改进，以及当前验收范围，见同目录 `UPGRADE.md`。

分析日期：2026-10-29。输入为工作区唯一的 `Phigros_4.0.1.2.xapk`。本报告描述实际检查和实际产物，不把资源成功导出等同于原版游戏全部移植完成。

## 1. 结论与交付范围

已制作使用本包资源的静态网页重建版：334 个曲目入口、1,064 张谱面，配有曲目库、章节和难度筛选、搜索、收藏、原始音乐和曲绘、原版音符贴图与打击音、手动游玩接口、自动演示、暂停续播、设置、本地成绩及存档导入导出。服务器只需提供静态 HTTP(S) 文件。

这次交付采用 JavaScript / Canvas / Web Audio 运行时，复用并修改 GPL-3.0 的 SimPhiCore。它不是 Unity 项目恢复后的官方 WebGL 构建。原版剧情、章节解锁、SaturnOS、档案系统、TapTap 云存档、SDK 和专用原生场景演出没有实现。高级特效、隐藏曲和教学的表现可能与原版不同。特别是第八、九章中依赖 MonoBehaviour 的效果不能仅靠谱面 JSON 复现。

已通过全部谱面的数值预处理检查和本地资源完整性检查；浏览器访问被保存的权限设置或受管策略阻止。没有实际浏览器截图、实际扬声器播放、真实多指操作、整曲 AP、移动端性能或 Linux 服务器端到端测试。因此这是可部署的重建交付包，不能宣称原版完整移植或已完成实机验收。

## 2. 输入包与可复核证据

- XAPK 大小：2,792,895,314 字节。
- SHA-256：`aa2601280aa62c1964e9b3629173152658d3c55032d24094292945b565eef65c`。
- Manifest：包名 `com.PigeonGames.Phigros`，版本 `4.0.1.2`，version_code `160`，minSdk `26`，targetSdk `36`。
- Unity 序列化资源声明的版本：`2022.3.62f2`。
- IL2CPP 元数据 magic：`0xFAB11BAF`，元数据版本 `31`。
- `libil2cpp.so` 的 ELF class 为 2（64 位），e_machine 为 183（AArch64）。

| XAPK 条目 | 大小（字节） | 用途 |
| --- | ---: | --- |
| `com.PigeonGames.Phigros.apk` | 26,567,846 | Android 启动层、元数据、level0、全局资源 |
| `UnityDataAssetPack.apk` | 767,636,461 | Unity 场景、共享资源、材质和纹理 |
| `UnityStreamingAssetsPack.apk` | 1,969,888,492 | Addressables catalog 和曲目 AssetBundle |
| `config.arm64_v8a.apk` | 28,725,965 | ARM64 原生库 |
| `manifest.json` | 2,078 | XAPK 描述 |
| `icon.png` | 73,662 | 图标 |

原生库中，`libil2cpp.so` 解压后为 71,736,936 字节，`libunity.so` 为 20,253,848 字节；还有 `libmain.so`、`libnativeaudioe7.so` 和 `libtapsdkcore.so`。没有可直接重新导入 Unity 的完整工程、C# 源码、编辑器工程配置或可供浏览器执行的 Wasm。

## 3. 为什么不直接转换 APK

Android ELF 的 ARM64 指令、Android 启动生命周期、原生音频插件和 TapTap SDK 不能由浏览器直接执行。Unity 的 Web 构建需要把游戏代码和运行时针对 WebAssembly 重新编译；IL2CPP 的 Android 产物已经是目标平台机器码。把安装包解压到 Nginx、修改扩展名、或生成一个加载 APK 的 HTML 都不会完成这一步。

完整工程缺失时有三种路线：

| 路线 | 工程条件 | 结果与选择 |
| --- | --- | --- |
| 恢复工程并重新构建 Unity Web | 需恢复脚本、场景关联、插件替代和构建设置 | 可追求原版表现，但当前材料不足以可信地完整恢复；后续工作 |
| Android 远程运行并串流 | 服务器需 Android/图形环境和实时流服务 | 不能满足“只解压到静态网站目录”的交付方式 |
| 资源迁移并重建浏览器运行时 | 可解析曲目资源，有兼容谱面引擎 | 本次采用；提供静态部署与基础游玩能力 |

## 4. 资源索引和元数据的恢复

### Addressables

读取 `assets/aa/catalog.json` 的 Key、Bucket、Entry 三组 Base64 数据。Bucket 指向键与 Entry，Entry 指向 provider、internal ID 和 dependency。合计解析到 11,127 个索引条目，其中含重复的资源键 / 多类型条目。

本版本很多资源的 `internal` 是字符串 `0`。不能直接用它作为文件名。通过资源的 dependency key 再解析到 bundle entry，才能取得实际的 `assets/aa/Android/<hash>.bundle`。提取器保留原键、实际 bundle 和导出路径的对应关系。

### GameInformation

从基础 APK 的 `globalgamemanagers.assets` 和 `level0` 解析 MonoScript 关联。`GameInformation` 的 MonoBehaviour path_id 为 50，原始长度为 164,032 字节；其自定义字段没有内嵌完整 TypeTree。采用有版本记录的公开字段定义读取，并校验能读完整对象。

得到 `mainSongs` 57 条、`extraSongs` 248 条、`sideStorySongs` 22 条、`otherSongs` 1 条；共 328 条元数据，含教学。章节列表有 34 个条目。再加入资源中 `Random` 的 6 个分支，网页曲目入口合计 334。

曲名、曲师、曲绘作者、谱师、难度定数、难度对应的不同音乐 / 曲绘标志直接来自包内数据。章节使用明确的章节编号或合集名称展示；没有通过网络曲库补齐或替换歌曲。

### 特殊映射

- `Cristalisia` 的 IN 难度使用 `music_IN.wav`。
- `What do you want more than a Happy ending?` 的各难度使用各自的曲绘。
- `Random` 的 6 个分支使用自己的谱面和音乐，继承基础曲目的曲师 / 曲绘信息，并明确标为特殊入口。
- 普通 `Illustration.jpg` 和 `Illustration.jpg.c9Locked` 导出到不同文件名；优先选普通曲绘，避免锁定版本覆盖正常版本。

## 5. 资源导出结果

| 类型 | 数量 | 转换方式 |
| --- | ---: | --- |
| 谱面 | 1,064 | TextAsset 原始字节无损 gzip；1,035 张 formatVersion 3，29 张 formatVersion 1 |
| 音乐 | 335 | Unity AudioClip / FMOD 解码为 PCM，再分块编码成 OGG Vorbis；334 首基础音频及 1 份难度专用音频 |
| 曲绘及变体 | 341 | 解码 Unity Texture2D，输出最长 1920×1080 的 JPEG；另生成最长 480×270 的列表缩略图 |
| 音符 / 判定线贴图 | 12 | 从 `sharedassets12.assets` 的 Sprite 导出 PNG，保留透明度 |
| 打击音 | 3 | 从基础 APK 导出原始打击音到 WAV |

1,064 张谱面共包含 682,744 个音符：Tap 353,991、Drag 211,726、Hold 71,496、Flick 45,531。音乐是有损重编码；曲绘缩放与 JPEG 编码也不是无损转换。谱面 gzip 解压后的字节与导出记录中的 SHA-256 一致。

谱面压缩数据约 345.4 MB，音乐约 992.3 MB，曲绘主文件约 118.0 MB，另有缩略图与网页文件。准确文件大小和校验见 `asset-manifest.json` 及最终 ZIP 的 SHA-256 文件。没有把整个 XAPK 放入网站包让客户端再次下载。

## 6. 浏览器运行时实现

### 引擎

上游：[lchzh3473/sim-phi](https://github.com/lchzh3473/sim-phi)，使用的提交为 `1046c4e6b5fe807f48d9ea2dc35d301bc402fa1a`，版本 1.5.9.2。保留 GPL-3.0 许可证和作者信息。新增的集成接口及网页代码随包提供源码。

修改内容：

1. 保留原生 PGS format 1 / 3 读取器，移除本项目不需要的私有 `@sim-phi/extends` 依赖与 PEC / RPE 路线。
2. 移除在线曲库、演示扩展、远程资源包和全站 Service Worker 注册。网页没有运行时 CDN 依赖。
3. 通过同源 iframe 暴露 `load / play / pause / resume / stop` 接口。退出时移除 iframe，释放本曲运行时；不同曲目不会一直累积解码后的音频。
4. 使用本包的原版音符贴图、判定线和打击音；部分打击粒子、结算绘制仍由模拟引擎生成。
5. 直接设置每次游玩的音量、偏移、音符缩放、背景暗度、模糊与低分辨率选项。
6. 新建 DOM 输入适配器，连接鼠标、多点触摸和键盘。P / Escape 请求暂停，Shift 保留引擎暂停操作。
7. 明确区分手动成绩与自动演示，不把自动演示写入网页成绩表。
8. 修复一个原始数据计数不一致：`明鏡烈火` HD 声明总数 564，音符数组实际为 566。运行时从数组重新计算各层和全谱面总数，原始 JSON 不变。此处理防止计分分母失真。

本版判定和画面以该模拟引擎实现为准，没有从 Android 原生方法逐条证明与官方实现完全一致。键盘以无位置的辅助判定工作：任意普通键的按下 / 按住可用于音符；触屏和鼠标则使用位置与滑动事件。

### 网页壳

无需构建即可运行的 `index.html + app.css + app.js`。提供中文曲目库、搜索、章节筛选、难度筛选、排序、收藏、难度选择、曲目作者信息、最高分及准确率、随机选曲、全屏请求、暂停页、结算页、设置、JSON 存档导入导出。

所有资源使用相对路径或从当前页面 URL 解析的同源绝对 URL，可以放在 `/phigros/` 之类的子目录。首页只请求目录和当前可见图片；加载歌曲时才请求该谱面、音频和曲绘。谱面文件是自带 gzip 头的静态字节文件，由浏览器 DecompressionStream 解压，不要求服务器添加 Content-Encoding 配置。

### 存储

使用当前浏览器当前网站 origin 的 localStorage 保存成绩、收藏和设置。成绩导入采用最高分合并，导入数据经数值与格式检查。自动演示独立标识，不参与手动成绩。未实现官方账号、原生存档导入、跨设备同步或排行榜。

## 7. 执行计划与完成状态

| 阶段 | 验收内容 | 状态 |
| --- | --- | --- |
| A 安装包调查 | 校验版本、split APK、ELF、IL2CPP 和 Unity 版本 | 已完成 |
| B 元数据恢复 | 资源键到 bundle，曲名 / 作者 / 定数 / 章节，难度专用资产 | 已完成 |
| C 资源迁移 | 全部谱面、曲目音频、曲绘、核心音符贴图与打击音 | 已完成并保留对应关系 |
| D 基础游玩重建 | 接入模拟引擎、输入、时序、暂停、结算和本地成绩 | 已实现；数值测试通过，浏览器验收待完成 |
| E 网站交付 | 相对路径、静态部署说明、源码 / 许可证和 ZIP | 已完成 |
| F 原版系统复刻 | 剧情、解锁、专用演出、SDK / 云存档 | 未实现，属于后续工程 |
| G 端到端验收 | 浏览器画面 / 触摸 / 音频、整曲与移动端性能、Linux 部署 | 被浏览器访问策略阻止，待实际设备验证 |

## 8. 实际测试与证据

- Vite 生产构建成功；网站主脚本通过 Node 语法检查。
- 1,064 / 1,064 张谱面通过运行时 PGS 解析、预处理、时间戳和坐标数值检查，无解析错误与数值错误。每张检查 0 秒、1 秒、曲长 25% / 75% / 接近末尾及回退到 0 秒的事件定位。此检查不生成画面。
- 对 1920×1080、720×1280、844×390 与缩放分辨率的坐标范围进行了离线检查。
- 计分检查：100 个 Perfect 得 1,000,000 分 / 100% / 100 连击；100 个 Good 得 685,000 分 / 65%；100 个 Miss 得 0 分 / 0%。
- 所有谱面文件经过 gzip 解压、JSON 格式和 SHA-256 核对；另从原始 AssetBundle 重新抽样提取 17 张谱面进行独立字节校验。
- 所有曲绘及缩略图经过图片解码校验；所有音乐完整分块解码并核对采样帧数和时长。
- 曲目目录引用与 ZIP 条目做存在性、相对路径及完整性检查。
- 实际浏览器访问曾申请授权，用户允许后仍因保存的权限或受管策略被工具拒绝；没有切换其他浏览器或直接浏览器协议绕过。浏览器视觉、音频设备和交互结果均未验证。

详细机器报告随包放在 `docs/reports/`。报告中的离线成功不应被解释为实际浏览器端到端成功。

## 9. 部署与后续验收

把最终 ZIP 内容解压到现有网站目录，访问该目录的 HTTP(S) URL 即可。入口在 ZIP 根目录的 `index.html`。不需要 Node.js、Python、PHP、数据库、Docker 或 Android 环境来运行成品。浏览器需要 JavaScript、Canvas 2D、Web Audio、OGG Vorbis、createImageBitmap 和 gzip DecompressionStream。

首次打开先选曲、选难度，点击“开始游玩”，待该曲资源加载后再点一次开始，使音频在用户手势下启动。手机建议横屏；触屏和低延迟有线音频的实际体验仍需验证。

可继续推进的工作按依赖顺序为：

1. 解除本机预览的保存权限阻止，完成 Chrome / Firefox 和真实 Android、iOS 浏览器验收。
2. 用原版录像与真实手动输入核对同步、Tap / Hold / Drag / Flick、AP / FC / Miss、暂停后长按恢复、旋转和切后台。
3. 对最复杂谱面测内存、首次加载时间与帧率，并根据设备调整事件索引 / 渲染优化。
4. 从 IL2CPP 类和场景资源重建章节专用脚本，包括第八、九章的演出和交互；再逐曲建立视觉 / 时序回归样本。
5. 只有在恢复足够的原版代码和工程设置后，才能另行追求 Unity WebAssembly 原版重编译；当前 ZIP 不包含这种构建。

## 10. 参考来源与代码归属

- Unity [IL2CPP 概述](https://docs.unity.cn/Manual/scripting-backends-il2cpp.html) 和 [Web 技术构建说明](https://docs.unity.cn/2021.1/Documentation/Manual/webgl-gettingstarted.html)：说明目标平台编译差异。
- [UnityPy](https://github.com/K0lb3/UnityPy)：本地 Unity 资源解析，使用 1.25.4。
- [7aGiven/Phigros_Resource](https://github.com/7aGiven/Phigros_Resource)：自定义 GameInformation 字段定义参考，GPL-3.0；定义快照随源码保留。
- [SimPhiCore](https://github.com/lchzh3473/sim-phi)：浏览器谱面引擎，GPL-3.0。
- 游戏曲目、曲绘、谱面、图标、贴图与音频归 Pigeon Games 及对应作者所有；网页保存原作者字段。

源码包中提供工具、字段定义、修改后的引擎、网站源文件、依赖锁文件及许可证。Python 资源提取依赖仅用于重建，不需要上传服务器运行。
