Phigros 第九章《穹顶孤舟》网页解谜复盘:从 Chaocipher 到 13 段碎片拼字

9370 字
47 分钟
Phigros 第九章《穹顶孤舟》网页解谜复盘:从 Chaocipher 到 13 段碎片拼字

这篇是 2026-09-25 晚上的解谜复盘。官方在 TapTap 发了一段密文,指向一个带倒计时的隐藏页,顺着挖下去是一整条链:Chaocipher、PNG 尾部拼接、零宽字符隐写、Nihilist 密码、按指纹分发的碎片,最后靠竖读拼出两个词。链尾还有一页「End」,而这一环的密码,就是 End 页那句 slogan。

先说清楚两件事:

本文大部分推断由 GPT / GLM 生成,仅供参考

链条里每一步的手法(Chaocipher 的字母表、PNG 切分位置、零宽字符映射、Nihilist 的减法、acrostic 的读法)都尽量用本地脚本复算过。

但这些步骤意味着什么——比如哪些页面是官方有意给的、13 段碎片为什么这样分发、两个拼出来的词最后要怎么用——大部分是 GPT 和 GLM 的推断。成链的关键步骤已经和 Phigros 解密 3 群(社区)交叉核对过(见文末致谢),但仍不是官方口径,看结论可以,别当成官方答案。

本页的社区来源

下面几处关键思路来自社区玩家,不是我们独立想出来的:outside_the_birdcage 的 FFT 线索、零宽字符 → 摩尔斯 → AROUSAL、以及标题 nihilist 指向的 Nihilist 解法(5×5 方阵 + AROUSAL 减法 → JUSTENGAGEWTH)。这些来自 QQ 群里的整理(__polar_ice 转述,Soucirif 等人的截图),字母表本身出自官方第九章 PV 简介。

一、从 Solivault 到 End:整条链的样子#

一句话版:公告密文 → Solivault(倒计时页)→ 源码里那张图 → FFT → outside_the_birdcage → 13 段碎片排成表 → Cogito, ubi sit refugium → DISORIENTATION → JUSTENGAGEWTH → 栅栏 + 之字形读表 → NOL2re@etiKdA3!ig9t~UmSO(End 页)→ slogan 就是最终密码。

先搞清楚:这些隐藏页的链接是怎么来的

第九章的网页解谜入口不在游戏里,而是从两条公开线索接进林泊百科(wiki.pigeon-games.com):

  1. 官方公告线:TapTap 公告给的密文 + 两张字母盘 → Chaocipher 解出德语明文 WERJETZTALLEINISTWIRDESLANGEBLEIBEN → 直接拼在 wiki 域名后面 → 隐藏页 /WERJETZT…/(标题 Solivault,倒计时到 2026-10-02 17:00)。细节见 第 0 步。
  2. 网页源码线:某个网页的源码里藏着一张黑洞图 → 对它做 FFT → 浮出 Outside_the_birdcage → 拼到 wiki 域名后 → /outside_the_birdcage/。细节见 第 1 步。

两条线都落在同一台 wiki 上。之后的 Cogito, ubi sit refugium、DISORIENTATION、JUSTENGAGEWTH、NOL2re@… 全都是同一个套路:把解出来的词当路径,一页一页走下去 —— 换句话说,每解出一个词,就等于拿到了下一站的链接。

这一页的资料是从哪来的

两条来源,分开说清楚:

  • 主干 + 最后一步(End 页地址):来自 Phigros 解密 3 群(第九章解谜的社区)。13 段碎片的收集与排序、「黄色格子顺时针读」、Nihilist 六步,以及最后「栅栏 + 之字形读表」读出 NOL2re@etiKdA3!ig9t~UmSO,都是社区一起解出来的;后面的 13×12 表格图和那张「变化后」的读表图,也来自社区。
  • 本页的验证与细节:我们自己去抓的那部分 —— start.png 的字节切分、api.php 的指纹分发、decodeCopy 复算、JUSTENGAGEWTH 复制提示池的采样,以及 End 页 / 《Sky of Your Vault》那两页的接口实测。

所以:链条是大家一起解出来的,这篇只是把它按顺序整理成一条线,再把能验的地方都验一遍。

第一步是入口 Solivault:

对这张图做 FFTTapTap 公告密文 + 26 字母表Chaocipher 解密德语明文接到 wiki 域名后隐藏页 Solivault倒计时 10-02 17:00源码里的图c9.gaoice.run/start.png浮现 outside_the_birdcage
对这张图做 FFTTapTap 公告密文 + 26 字母表Chaocipher 解密德语明文接到 wiki 域名后隐藏页 Solivault倒计时 10-02 17:00源码里的图c9.gaoice.run/start.png浮现 outside_the_birdcage

第二步起就在 wiki 里一页接一页往下走,终点是 End:

黄色格子顺时针读栅栏 + 之字形读表从 NO 读到 SO/outside_the_birdcage/13 段碎片按末字母排序摆成 13×12 表格Cogito, ubi sit refugium/Cogito,_ubi_sit_refugium/零宽字符 → 摩尔斯DISORIENTATION/DISORIENTATION/标题 nihilist → 5×5 方阵JUSTENGAGEWTH/JUSTENGAGEWTH/Fence? + 复制出的提示NOL2re@etiKdA3!ig9t~UmSOEnd 页 slogan= 最终密码/Backward,…/《Sky of Your Vault》收尾
黄色格子顺时针读栅栏 + 之字形读表从 NO 读到 SO/outside_the_birdcage/13 段碎片按末字母排序摆成 13×12 表格Cogito, ubi sit refugium/Cogito,_ubi_sit_refugium/零宽字符 → 摩尔斯DISORIENTATION/DISORIENTATION/标题 nihilist → 5×5 方阵JUSTENGAGEWTH/JUSTENGAGEWTH/Fence? + 复制出的提示NOL2re@etiKdA3!ig9t~UmSOEnd 页 slogan= 最终密码/Backward,…/《Sky of Your Vault》收尾

按顺序列一遍(每步都能在下面找到对应小节):

#在哪干了什么得到
0TapTap 公告Chaocipher 解密德语明文 → 隐藏页 Solivault
1Solivault源码里的 start.png(尾部另外拼了一张同款图)→ 对它做 FFToutside_the_birdcage
2/outside_the_birdcage/slogan 由 api.php 按浏览器指纹分发13 段碎片
313 段碎片按末字母排成 13×12 表格(右侧列 = DISPOSSESSION、左侧列 = IGNORANCE)一张表
4那张表黄色格子顺时针读Cogito, ubi sit refugium
5/Cogito,_ubi_sit_refugium/文案里的零宽字符 → 摩尔斯DISORIENTATION
6/DISORIENTATION/标题 nihilist + Hint2「移除干扰」→ 5×5 方阵 + AROUSAL 减法JUSTENGAGEWTH
7/JUSTENGAGEWTH/标题 Fence?(栅栏密码)+ 复制出的提示读法:之字形、从 NO 读到 SO
8回到那张表照上面的读法读表NOL2re@etiKdA3!ig9t~UmSO = End 页
9End 页读 slogan最终密码
10/Backward,…/《Sky of Your Vault》星空留言墙收尾(彩蛋)

各阶段谜底速查#

阶段这一步在干什么谜底
阶段一源码里的黑洞图做 FFTOutside_the_birdcage → /outside_the_birdcage/
阶段二13 段碎片排成表,黄色格子顺时针读Cogito, ubi sit refugium → /Cogito,_ubi_sit_refugium/
阶段三文案里的零宽字符 → 摩尔斯DISORIENTATION → /DISORIENTATION/
阶段四标题 nihilist → 5×5 方阵 + AROUSAL 减法JUSTENGAGEWTH → /JUSTENGAGEWTH/
阶段五标题 Fence? → 栅栏 + 之字形读表(从 NO 读到 SO)NOL2re@etiKdA3!ig9t~UmSO → End 页

用到了哪些东西、在哪一步用上#

手法 / 工具用在哪一步跳到
Chaocipher(双盘轮转)公告密文 → Solivault第 0 步
PNG 字节切分(找第一个 IEND)拆 start.png,拿到页面真正渲染的那张图第 1 步
傅立叶变换(FFT)从图里读出 Outside_the_birdcage第 1 步
零宽字符 → 摩尔斯解出 AROUSAL / DISORIENTATION第 2 步
Nihilist(5×5 方阵 + 数字相减)解出 JUSTENGAGEWTH第 3 步
base64url + 逐字节 XOR复算 decodeCopy() 的 try for yourself第 4 步
浏览器指纹 + api.php13 段碎片按人分发第 5 步
acrostic 竖读DISPOSSESSION / IGNORANCE(排序与校验)竖读那一节
栅栏密码 + 之字形读表从 13×12 表里读出 End 页地址最后一环
接口只读探测验证 End 页 / 星空留言墙的行为星空留言墙实测

| 最终 | 读 End 页 slogan | Backward, go backward, turn back to the antemundane realm, go back to the - = 密码 |

二、第 0 步:Chaocipher 解出隐藏 URL#

公告给了一段密文和两张字母盘:

  • 密文:ZGJGDGTDNUIOSQQCLIWWCWIIADNOFQDAEMG
  • 左盘:标准 A–Z
  • 右盘:PSZLMYQEBJARTFCHNUGVKDOXIW(来自官方第九章 PV 简介,社区玩家提供的链接是 BV16vbN6REhD)

Chaocipher 的规则按模型给的说法是:每解出一个字母,把命中的字母转到盘首,再把第 2 到第 14 位整体轮转一位。按这个规则解完得到:

WERJETZTALLEINISTWIRDESLANGEBLEIBEN

断词是 WER JETZT ALLEIN IST, WIRD ES LANGE BLEIBEN —— 德语,「此刻孤独的人,会孤独很久」。把这串字母直接拼在 wiki 域名后面,就是一个隐藏页:

https://wiki.pigeon-games.com/WERJETZTALLEINISTWIRDESLANGEBLEIBEN/

页面 <title> 是 Solivault,中间一个写死的倒计时,终点 2026-10-02 17:00。页面底部还留了两行注释,一行是 how to read code in phone?:add /index.html?code or /index.php?code,一行是 GUGUGU~。

更新(10-02 前):Solivault 开始播歌了,歌里藏着 SSTV 图#

倒计时临近时这个页面换了壳:本体只剩一个几十行的引导脚本,先请求 state.php 拿状态({sound, open, sound_enabled, open_at, close_at}),再按状态加载 song.html(会响)或 nosong.html(静音)。音频是加密下发的:

state.php决定 song / nosongsong.html混淆过的播放器key.php?n=1发 P-256 公钥 + nonceplay.php?id=1/2/3AES-GCM 加密的音频分片WebCrypto 解密→ AudioContext 播放
state.php决定 song / nosongsong.html混淆过的播放器key.php?n=1发 P-256 公钥 + nonceplay.php?id=1/2/3AES-GCM 加密的音频分片WebCrypto 解密→ AudioContext 播放

我们用 Playwright 打开页面并 hook decodeAudioData,直接拿到了解密后的完整音频:单声道 44.1kHz / 16-bit / 111.356 秒的 WAV。

后续(09-26 确认):这个播歌阶段已经下线

写完这篇之后我们复查了一次:主页恢复成了原来的老代码(start.png 两图拆分 + 倒计时),state.php 与 key.php 接口已撤(404 / 错误页),song.html 现在返回的是 wiki 回退首页 —— 整套加密音乐系统被完整移除了。所以上面这段「播歌 + SSTV」是限时窗口期的内容,我们抓到的音频与 SSTV 图是当时的完整存档;文内的音频试听与图片都来自那个窗口期。

这段声音的分析结论:

  1. BPM ≈ 139.7(能量包络自相关最强峰),频谱质心 2.6~3.5kHz,是一段带人声切片的电子曲。
  2. 语音识别(whisper base)在 60s 与 90s 处两次听到「Sper, sper, sper…」(罗马尼亚语「我希望」),但 no_speech_prob 高达 0.83~0.91,更可能是节奏切片造成的识别幻觉,先存疑。
  3. 真正的彩蛋是 SSTV:每 0.43 秒(正好一个节拍)出现一次 1200Hz 同步脉冲,后面跟着 1500~2300Hz 的图像数据 —— 也就是把 SSTV 传输按节拍藏进了歌里。用 SSTV 解码器跑一遍,解出一张 320×256 的图(Robot 36 模式标准尺寸):

Solivault 歌曲里藏的 SSTV 图:一位黑发黄瞳、白衣黑颈环的角色(320×256,Robot 36)
Solivault 歌曲里藏的 SSTV 图:一位黑发黄瞳、白衣黑颈环的角色(320×256,Robot 36)

上图:SSTV 解码结果,横向噪纹是 SSTV 的固有失真。图来自游戏第九章 ARG 的 Solivault 页面。

倒放的音频里没有第二张图,正放这张就是全部。图上是一位黑发、黄绿色眼睛、白色裙装、黑色颈环的角色 —— 具体是谁、对应哪首新曲,等官方揭晓。

顺带核对了一个细节:key.php?n=1 的响应里还有个 au 字段,指向 c9.gaoice.run/Solivault-<每会话不同哈希>.png(1920×1080,裸 curl 会吃 403)。让浏览器正常加载页面后把图拿下来做像素级比对 —— 和第一阶段 start.png 里的 part1.png 相关系数 1.000、dHash 距离 0/992,就是同一张黑洞图。所以这首歌的「封面」没有新内容,本次更新唯一的新图就是上面的 SSTV 角色图。另外 state.php 里的 close_at 换算后正是 2026-10-02 17:00,和原倒计时一致。

这篇声音分析的完整实录(含音频在线试听、频谱图、解码脚本)单独成了一篇:Solivault 的歌里藏了什么:一次 SSTV 解码实录。

这一步的明文结果

Chaocipher 的明文结果是确定的:URL 能直接打开,页面标题就是 Solivault。本文就按上面这套盘序与轮转规则来记,不再引外部文档。

how to read code in phone?: 那行注释当时很容易想歪,以为是「密码输入框」。后来确认 code-dialog.js 只是个「在手机上看页面源码」的小工具:加 ?code 显示当前页源码,?code=<文本> 显示指定文本。它是工具,不是谜题的一部分。

一个当时踩到的坑

海外 IP 访问 wiki.pigeon-games.com 会随机拿到 HTTP 502 或者一个 773「访问被拒绝」页。同一时间用国内 IP 访问一切正常。后面所有请求都是在国内 IP 下做的。

三、第 1 步:start.png 里其实有两张图#

链上位置:Solivault → 拆 start.png → FFT → outside_the_birdcage

Solivault 的 JS 会去 https://c9.gaoice.run/start.png 拉一张图,但它不用整张文件:它找第一个 PNG 的 IEND 块,把后面的字节当成另一张 PNG 渲染。

所以这个文件是「拼接」的。按 PNG chunk 结构走一遍就能看到边界:

start.png3,722,963 B第一张 PNG到第一个 IEND 结束3,139,455 B尾部 583,508 B4 字节垃圾 + PNG 签名切出第二张 PNG583,504 B
start.png3,722,963 B第一张 PNG到第一个 IEND 结束3,139,455 B尾部 583,508 B4 字节垃圾 + PNG 签名切出第二张 PNG583,504 B
import struct
d = open("start.png", "rb").read()
pos, i = [], 8
while i < len(d):
ln = struct.unpack(">I", d[i:i + 4])[0]
if d[i + 4:i + 8] == b"IEND":
pos.append(i + 8) # 第一张 PNG 的结束位置
i += 12 + ln
tail = d[pos[0]:] # 3,722,963 − 3,139,455 = 583,508 字节
sig = b"\x89PNG\r\n\x1a\n" # PNG 签名
part2 = tail[tail.find(sig):] # find() 返回 4 → 正好跳过那 4 个垃圾字节
open("part2.png", "wb").write(part2)

拼接处很讲究:尾部数据开头有 4 个垃圾字节 ae 42 60 82,然后才是标准的 PNG 签名 89 50 4E 47 0D 0A 1A 0A。这 4 个字节的作用就是让浏览器把整张文件当成一张正常图片解析、不报错;而页面 JS 只认签名,从偏移 4 处切开。

文件尺寸格式大小
part1.png1920×10808-bit RGB3,139,455 B
part2.png1920×10808-bit colormap583,504 B

两张图内容几乎一样,就是下面这张:一张黑洞的特写,一根针状的细线斜穿而过,紫灰色的虚化背景,纯意象。(第一眼看也像眼珠,社区习惯叫它“黑洞图”。)

从 start.png 尾部切出的第二张 PNG,也是页面 JS 真正渲染的那张
从 start.png 尾部切出的第二张 PNG,也是页面 JS 真正渲染的那张

上图:start.png 尾部藏的那张 1920×1080 图(社区叫它“黑洞图”),缩放后导出。文件本身不含文字,它就是这一关的「画面」。

社区玩家的补刀:对这张图做 FFT

社区里有人把官方壁纸(也就是这张黑洞图)做了傅里叶变换:频谱图里出现一个十字星芒,星芒上下各有一行被打散的白色文字,拼起来是 outside_the_birdcage。这直接指向 wiki 下的同名页面,也是我们后面能顺着找到 4 个氛围页的起因。

这属于社区发现,不是我们独立解出来的——记在这里是因为它确实在链条里。

对这张图做傅里叶变换后的结果,星芒上下浮现出 outside_the_birdcage
对这张图做傅里叶变换后的结果,星芒上下浮现出 outside_the_birdcage

上图:FFT 后的结果图,十字星芒处能看到 outside_the_birdcage。图来自 Phigros 解密 3 群(社区)。

四、第 2 步:氛围页、零宽字符与摩尔斯#

链上位置:outside_the_birdcage → 氛围页 → 零宽字符 → AROUSAL / DISORIENTATION

wiki 下还有 4 个能直接访问的静态页,都返回 200:

URL页面标题
/outside_the_birdcage/Birdcage
/Cogito,_ubi_sit_refugium/.Bravo _Charlie ␣Delta
/DISORIENTATION/nihilist
/JUSTENGAGEWTH/Fence?

注意 DISORIENTATION 的标题叫 nihilist —— 这是官方给的密码类型提示,后面会用到。

其中 Cogito,_ubi_sit_refugium 这个页名不是猜出来的:把 13 段碎片排成 13×12 的表格后,表格里黄色格子顺时针读就是这句 Cogito, ubi sit refugium(拉丁语,“我在想,避难所在何处”)。

黄色格子是哪几格?看 /outside_the_birdcage/ 页面里那些小三角形落在哪 —— 三角形指到的格子就是黄格,顺着它们顺时针读即可。

页面 slogan 也有问题:

In what sense, exactly,​‌‍​‌​‍‌‌‌‍​​‌‍​​​‍​‌‍​‌​​ do we “truly” inhabit the “world”?

记三个字符就够解这一页

U+200B = 点(.)| U+200C = 划(-)| U+200D = 字母分隔

exactly, 和 do we 之间藏了 26 个零宽字符。Cogito 页的 slogan 里藏了 43 个。编码规则很直白:

源码里 humanity 后面那串零宽字符(​‌ 交替)
源码里 humanity 后面那串零宽字符(​‌ 交替)

上图:F12 里看到的零宽字符串。图来自 Phigros 解密 3 群(社区)。

U+200B摩尔斯序列U+200CU+200D(字母分隔)DISORIENTATION 页 →AROUSALCogito 页 → DISORIENTATION
U+200B摩尔斯序列U+200CU+200D(字母分隔)DISORIENTATION 页 →AROUSALCogito 页 → DISORIENTATION
import re
html = open("DISORIENTATION.html", encoding="utf-8").read()
seq = re.search(r"[\u200b\u200c\u200d]+", html).group() # 26 个零宽字符
table = {"\u200b": ".", "\u200c": "-", "\u200d": " "} # ZWSP=点, ZWNJ=划, ZWJ=字母分隔
print("".join(table[c] for c in seq)) # .- .-. --- ..- ... .- .-.. → AROUSAL

也就是 U+200B 当点、U+200C 当划、U+200D 当字母分隔符,查摩尔斯表得到 AROUSAL。解出来 Cogito 页藏的词是它自己的 URL 名,两页互相印证了规则没解错。

这里拿到的 AROUSAL 不是终点,它是下一关的钥匙(这也是这一题设计得好的地方:线索先给,用处后面才出现)。

五、第 3 步:meta 里的数字是 Nihilist 密文#

链上位置:DISORIENTATION(标题 nihilist)→ 5×5 方阵 + 减法 → JUSTENGAGEWTH

DISORIENTATION 页头部藏了一串数字:

<meta name=" " content="56 75 65 76 35 56 75 63 97 66 67 47 72">
这一步一共就五下

标题点名密码类型 → 去掉 I 排出 5×5 → AROUSAL 去重查表得到钥匙 → 循环相减 → 坐标查回字母 → JUSTENGAGEWTH

一共 13 个数。加上页面标题 nihilist,指向 Nihilist 密码:经典的 Nihilist 是「5×5 方阵 + 数字相减」,而这里两样东西都齐了 —— 官方 PV 简介给的那 26 个字母,去掉 I 正好排成 5×5:

行 \ 列12345
1PSZLM
2YQEBJ
3ARTFC
4HNUGV
5KDOXW

这里为什么要「去重」?页面上的 Hint2 已经把规则说了:你拿到的元素不能直接用,要观察加密规则、把干扰项去掉 —— AROUSAL 里重复的 A 就是要去掉的干扰,剩下的 AROUSL 才是钥匙。

于是流程就很清楚了:把 AROUSAL 去重(A R O U S A L → AROUSL)当钥匙,查方阵得到 31 32 53 43 12 14,循环重复这 6 个数去减 meta 里的 13 组数字,得到的坐标再查回字母:

meta:13 组两位数56 75 65 … 47 72逐位相减AROUSAL 去重 → AROUSL查方阵 → 31 32 53 43 12 14明文坐标25 43 12 … 33 41PV 字母表去掉 I→ 5×5 方阵坐标查回字母JUSTENGAGEWTH
meta:13 组两位数56 75 65 … 47 72逐位相减AROUSAL 去重 → AROUSL查方阵 → 31 32 53 43 12 14明文坐标25 43 12 … 33 41PV 字母表去掉 I→ 5×5 方阵坐标查回字母JUSTENGAGEWTH
ALPHA = "PSZLMYQEBJARTFCHNUGVKDOXIW" # 官方第九章 PV 简介给的字母表
GRID = ALPHA.replace("I", "") # 去掉 I → 5×5 = 25 格
def code(ch):
i = GRID.index(ch)
return (i // 5 + 1) * 10 + (i % 5 + 1) # 行号列号拼成两位数,例:A → 31
def char(n):
r, c = divmod(n, 10)
return GRID[(r - 1) * 5 + (c - 1)] # 两位数 → 字母
meta = [56, 75, 65, 76, 35, 56, 75, 63, 97, 66, 67, 47, 72]
key = [code(c) for c in dict.fromkeys("AROUSAL")] # 去重 → AROUSL → [31, 32, 53, 43, 12, 14]
plain = [n - key[i % len(key)] for i, n in enumerate(meta)]
print("".join(char(n) for n in plain)) # JUSTENGAGEWTH
key codes : 31 32 53 43 12 14
meta : 56 75 65 76 35 56 75 63 97 66 67 47 72
明文坐标 : 25 43 12 33 23 42 44 31 44 23 55 33 41
明文 : J U S T E N G A G E W T H

于是这一环的答案是 JUSTENGAGEWTH,又是一个页面名:https://wiki.pigeon-games.com/JUSTENGAGEWTH/。

顺带一提:那串数字还有另一种读法

把这 13 个数直接当成十进制字节值(chr() 一下),会得到 8KAL#8K?aBC/H:

print("".join(chr(int(n)) for n in "56 75 65 76 35 56 75 63 97 66 67 47 72".split()))
# 8KAL#8K?aBC/H

这个读法本身没错,但它和这一环的解法无关——#、? 都不在 base64 字母表里,也看不出下一步。真正能走通的是上面的 Nihilist 减法。

六、第 4 步:JUSTENGAGEWTH 页,和「1 step」#

链上位置:JUSTENGAGEWTH → 标题 Fence? + 复制出的提示 → 读出读法

打开 /JUSTENGAGEWTH/,注释写着 just need 1 step。它页面 JS 里有个 pendingCopy 字符串、一段 base64url + 逐字节 XOR 的 decodeCopy():

function decodeCopy(s) {
let t = s.replace(/-/g, "+").replace(/_/g, "/");
while (t.length % 4) t += "=";
const bin = atob(t);
const bytes = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++)
bytes[i] = bin.charCodeAt(i) ^ (0x37 + (i % 29));
return new TextDecoder("utf-8").decode(bytes);
}

对页面里硬编码的 pendingCopy = "Q0pAGl1TTx5GLzQwMCEpIA" 本地复算(base64url 解码 → 每字节 XOR 0x37 + i % 29)得到明文 try for yourself,也就是”你自己点点看”。真实内容要走 api.php?act=copy(点在 slogan 上触发)拿。

补挖:c 其实是按人给的小提示#

一开始以为 try for yourself 是固定占位符。补测发现:带上指纹去请求,c 会变,解出来的东西也不一样:

import base64, json, subprocess
def decode_copy(s): # 和页面里的 decodeCopy() 等价
t = s.replace("-", "+").replace("_", "/")
while len(t) % 4:
t += "="
raw = base64.b64decode(t)
return bytes(b ^ (0x37 + i % 29) for i, b in enumerate(raw)).decode()
fp = "67bd94f64711f889db59d5c7f3341957"
url = f"https://wiki.pigeon-games.com/JUSTENGAGEWTH/api.php?act=copy&fp={fp}"
c = json.loads(subprocess.run(["curl", "-sS", url], capture_output=True, text=True).stdout)["c"]
print(c, "->", decode_copy(c)) # eXcU -> NO-
请求c解出来
不带 fp(默认)Q0pAGl1TTx5GLzQwMCEpIAtry for yourself(占位符)
fp=67bd94f6…(我们的指纹)eXcUNO-
另一个指纹Gmt2-SO
另一个指纹RVdOABsIAh4Kfwrow: 4? 5?
另一个指纹axdlFWcT\/\/\/

多采一轮定论:40 次请求里 33 次拿到(7 次是 wiki 那个老毛病 502,约 18%),分布是:

解出来次数
try for yourself8
NO-8
\/\/\/7
-SO7
row: 4? 5?3

所以提示池正好 5 条(4 条真提示 + 1 条占位符),按指纹抽——33 次抽 5 个值,期望各 6.6 次,实测 8/8/7/7/3,随机性的偏差不显著。而且同一个指纹永远是同一条(同一个 fp 连测三次都是 NO-),说明是 fp → 提示的确定性映射,不是每次请求现抽。

这 5 条提示合起来 = 一套读表说明书

NO- 起点 | -SO 终点 | \/\/\/ 之字形 | row: 4? 5? 行号定位 | t 字符提示

这几条提示现在都能读通了 —— 它们说的就是「从哪读、怎么读」:

复制出来的提示它的作用
NO-读表的起点:从表格里 NO 那两个字符开始读
-SO读表的终点:一直读到 SO 为止
\/\/\/之字形读法(对上页面标题 Fence?=栅栏密码)
row: 4? 5?行号定位:在表里确认行(第 4 行还是第 5 行),和起点一起决定从哪一格起读
t同组的字符提示(官方复制内容里给过这一条)
try for yourself占位符(不带指纹请求时返回的那条)

把提示池和标题 Fence? 合起来看,读法其实已经被讲完了:用栅栏密码、按之字形、从 NO 读到 SO。照这个读法回到那张 13×12 表格,读出来的就是 24 个字符的 NOL2re@etiKdA3!ig9t~UmSO,也就是 End 页的地址(细节见 9.5)。

(复现脚本:hint_pool.py,只读、请求之间自动放慢 2.5 秒。)

这里没有再往下的接口

把 birdcage 的 api.php 试了一圈:act=copy / url / end / next / state / all / list —— 七个动作返回的是同一份数据({"index":2,"text":"IV7aN2emf9nS","total":13}),act 参数被直接忽略。也就是说这一侧没有”下一页/下一个 token”的口子。

七、第 5 步:核心机制 —— 按指纹分发 13 段密文#

链上位置:outside_the_birdcage 的 slogan → 13 段碎片 → 13×12 表格

outside_the_birdcage 页的 JS 是这样的:算一份浏览器指纹(UA、语言、平台、CPU 核数、屏幕、时区、canvas、WebGL,四次 FNV-1a 拼成 32 位 hex),然后发给 api.php?fp=...,服务端返回一个 index 和一段短文本,页面把 slogan 替换掉。

api.php页面 JS浏览器(Playwright)api.php页面 JS浏览器(Playwright)total=13 → 一共 13 段,每人按指纹只分到一段打开 outside_the_birdcagefingerprint() → 32 位 hexGET api.php?fp=67bd94f6...1957ok=true, index=0, total=13, text=?aT?~!4*jK^D
api.php页面 JS浏览器(Playwright)api.php页面 JS浏览器(Playwright)total=13 → 一共 13 段,每人按指纹只分到一段打开 outside_the_birdcagefingerprint() → 32 位 hexGET api.php?fp=67bd94f6...1957ok=true, index=0, total=13, text=?aT?~!4*jK^D

几个关键观察:

  1. 必须是真浏览器。 裸 curl 要么拿到默认段、要么拿到 773/502 页——因为它要完整指纹和 Cookie。用 Playwright 开页面、监听 api.php 的响应,才能拿到真实结果:
// browser_probe.js 的核心:别自己拼请求,监听页面真正发出的那个 api.php
page.on("response", async (res) => {
if (res.url().includes("api.php"))
console.log("[API]", res.status(), res.url(), "->", await res.text());
});
await page.goto("https://wiki.pigeon-games.com/outside_the_birdcage/", { waitUntil: "networkidle" });
  1. fp 必须是 32 位 hex,否则 400。&index=N 参数存在但被忽略,返回的仍是该指纹算出来的那一段。
  2. 随机枚举 300 个 32-hex 指纹,同一个 IP 下只刷出了 index 0 和 index 2。说明分发里还混了 IP/会话维度,单机收不齐 13 段——这是一个强制社区协作的设计。

最后我手上只有 4 段,其余从社区截图里补齐:

#密文首字母末字母
1?aT?~!4*jK^D?D
2S6&Dj#f=6T+ISI
3IV7aN2emf9nSIS
4GFToCYqyuH8PGP
5NF9etodigrAONO
6OU/@ig=!9~VSOS
7R#m6Aya#N=$SRS
8ALessK0@Mt=mEAE
9N2riNdAuY-USNS
10C4_tubAxU+/SCS
11E&rJaM\9-_IEI
12u-D4wBeN31_OuO
131SR&fuH6AbuN1N

13 段碎片排成的 13×12 表格,左右两侧是 IGNORANCE 与 DISPOSSESSION
13 段碎片排成的 13×12 表格,左右两侧是 IGNORANCE 与 DISPOSSESSION

上图:社区把 13 段碎片按末字母排好的表,两侧列就是 IGNORANCE / DISPOSSESSION。图来自 Phigros 解密 3 群(社区)。

破解:把字母竖着读#

13 段碎片本身是「乱码」,单看没意义。把每段的最后一个字母从上往下读:

D I S P O S S E S S I O N → DISPOSSESSION(剥夺)
frags = ["?aT?~!4*jK^D", "S6&Dj#f=6T+I", "IV7aN2emf9nS", "GFToCYqyuH8P",
"NF9etodigrAO", "OU/@ig=!9~VS", "R#m6Aya#N=$S", "ALessK0@Mt=mE",
"N2riNdAuY-US", "C4_tubAxU+/S", r"E&rJaM\9-_I", "u-D4wBeN31_O",
"1SR&fuH6AbuN"]
print("".join(f[-1] for f in frags)) # DISPOSSESSION
print("".join(f[0] for f in frags)) # ?SIGNORANCEu1

再读每段的第一个字符那一列:

? S I G N O R A N C E u 1
1 2 3 4 5 6 7 8 9 10 11 12 13

第 3 到第 11 个字符连起来正好是 IGNORANCE(无知);开头那个 ? 和结尾的 u、1 是干扰字符——和注释里那句 This hint has been destroyed by Chaos / remove any interference 对得上。

官方的 hint2:remove any interference
官方的 hint2:remove any interference

上图:DISORIENTATION 页里的 Hint2。图来自 Phigros 解密 3 群(社区)。

我们手上的 4 段(第 1、3、5、6 段)末字母正好是 D / S / O / S,和总串完全吻合,所以这个解法可以确认是对的。

两个词还能和官方别的文本对上:官方另有一段看起来是 Atbash 的密文(Lmob Xszlh xzm ...),按 Atbash 解读出来是「Only Chaos can shatter the mirage that plagues the ignorant Fool.」——IGNORANCE 对应 ignorant Fool,DISPOSSESSION 对应「穹顶孤舟」失去一切的主题。

顺带一提,JUSTENGAGEWTH 的标题是 Fence?(栅栏):碎片被「栅栏」切开、强制 13 个玩家各自领一段、再拼起来。这个解释是推断,但和机制数据对得上。

八、第 6 步:两个关键词是表格的排序与校验,不是「下一站」#

链上位置:表格两侧 → IGNORANCE / DISPOSSESSION(排序与校验)

先把死路说清楚:把这两个词塞回 URL 走不通 —— /DISPOSSESSION/、/IGNORANCE/ 都返回 200,但 wgPageName 是「首页」(MediaWiki 回退),也就是说 wiki 上没有这两个词条。

现在能确定它们真正的用途了:它们就是那张 13×12 表格的两侧列。

  • 右侧(末字母那一列)从上往下读 = DISPOSSESSION → 用来确定 13 段碎片的排列顺序;
  • 左侧(首字母那一列)从上往下读 = IGNORANCE(我们那份转录里混进了几个干扰字符,见上一节)→ 用来校验顺序对不对。

表格的左右两侧本身就是这两个词:右侧那一列竖读是 DISPOSSESSION(定顺序),左侧那一列竖读是 IGNORANCE(做校验)。所以它们不是通往下一站的地址,而是把表格拼对、拼准的钥匙 —— 拼对了,后面的「黄色格子顺时针读」和最后的「之字形读表」才成立。

九、尾声:End 页与《Sky of Your Vault》#

链上位置:JUSTENGAGEWTH → 之字形读表 → End 页 → 最终密码 → 《Sky of Your Vault》

第六步之后还有一页 —— /JUSTENGAGEWTH/ 那句「只差一步(only one step)」,指的就是它。

9.1 End 页:地址是一串 token,提示就是下一页#

把 slogan 当 URL 打开index.php?api=messagesindex.php?api=highlightsSolivault 倒计时页End 页/NOL2re@etiKdA3!ig9t~UmSO/Sky of Your Vault终点页留言写进星空cookie + 后端各留一份读到别人最近的留言随机点亮 50% 的星星
把 slogan 当 URL 打开index.php?api=messagesindex.php?api=highlightsSolivault 倒计时页End 页/NOL2re@etiKdA3!ig9t~UmSO/Sky of Your Vault终点页留言写进星空cookie + 后端各留一份读到别人最近的留言随机点亮 50% 的星星

GET /NOL2re@etiKdA3!ig9t~UmSO/ → 200,<title>End</title>。它不是 wiki 词条(页面里没有 wgPageName),和 Solivault、几个氛围页是同一类独立页。页面里有漂移的三角形 canvas、一张背景图,以及一句可以点击复制的 slogan:

Backward, go backward, turn back to the antemundane realm, go back to the -

这句话本身就是下一页的地址。 把它当 wiki 路径丢进浏览器:

https://wiki.pigeon-games.com/Backward,%20go%20backward,%20turn%20back%20to%20the%20antemundane%20realm,%20go%20back%20to%20the%20-/

→ 200,标题变成 Sky of Your Vault。所以「backward / 回退」的意思是回到提示本身去找路,而不是去反转字符串。

这句 slogan 本身就是这一环的密码(已实测验证)

已经确认,并且实际验证通过:Backward, go backward, turn back to the antemundane realm, go back to the - 就是这一环要交出的密码(答案),不是随手写的氛围词。

它一物两用:

  • 当路径用:把它丢进 wiki 地址栏,就是终点页《Sky of Your Vault》的地址(本节上面那段);
  • 当答案用:终点页那句「带着你刚刚获得的答案回到该去的地方吧」,说的就是它 —— 所以还要把它带回前面的流程里用掉。

也正因为它是密码,End 页才特意做了「点一下复制全文」,省得你手打这一长串(注意末尾那个孤零零的 - 也在密码里,别漏)。

顺手确认:/End/、/END/、以及把 token 整体反转的 /OSmU~t9gi!3AdKite@er2LON/ 都不是有效页面(会落到 wiki 回退首页 Limbo Wiki),只有原 token 是。

背景图也查了:background_NOL2re@etiKdA3!ig9t~UmSO.png(在 c9.gaoice.run 上)是 1920×1080 的普通图,第一个 IEND 之后只剩 4 字节——没有 start.png 那种「尾部再拼一张图」。

9.2 Sky of Your Vault:结局 + 星空留言墙#

这一页带着自己的后端:index.php?api=...(注意不是 api.php)。打开约半秒后弹出对话框:

终于,你亦抵达了这里。
带着你刚刚获得的答案回到该去的地方吧。
还是说,你还在试图向着无序的宇宙呼唤,企图得到点什么回应?
如果你想的话,说说便是,因为这已没有任何意义。

这段话信息量不小:它明确说这里不用再解谜了,而是让你「带着刚刚获得的答案回到该去的地方」。页面的 <meta name="robots"> 还写着 noindex, nofollow, noarchive, nosnippet, noimageindex——官方不想让搜索引擎收录它。

关掉弹窗,星空和「说话条」才浮出来:三层星(far / mid / near,只有中、近层可点),能拖着转、有惯性;点星星会高亮并显示那颗星上的留言。然后是一个输入框——placeholder 是「向无序的宇宙说点什么……」,署名可以留空,正文上限 130 字。点发送之后:

  1. 随机挑一颗星(按离画面中心的距离做高斯加权),把你的话挂上去;
  2. 署名留空 → 显示 ——无名;
  3. 本地留一份:cookie player_messages(base64url 的 JSON,最多 20 条、24 小时);
  4. 上后端:POST index.php?api=messages(带 X-CSRF-Token),失败就只留本地。
调用作用
GET index.php?api=bootstrap发一个 CSRF token,返回 {"ok":true,"csrf":"…","ttl":21600}
POST index.php?api=messages提交一条留言
GET index.php?api=highlights&count=10&lang=zh拉别人最近的留言(前端随机打散后点亮 50% 的星星)
GET …&count=50连续用大 count 会被限流:429

9.3 只读实测:星空上到底写了什么#

这一节只做了 GET,没往官方留言墙里写任何东西。要点是:highlights 光有地址不行,必须先拿到会话 cookie,再带上 CSRF。

Terminal window
UA='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
VAULT='https://wiki.pigeon-games.com/Backward,%20go%20backward,%20turn%20back%20to%20the%20antemundane%20realm,%20go%20back%20to%20the%20-/'
curl -sS -A "$UA" -c jar.txt -o /dev/null "$VAULT" # 1) 先拿会话 cookie
curl -sS -A "$UA" -b jar.txt -c jar.txt "$VAULT/index.php?api=bootstrap" # 2) 拿 csrf
# → {"ok":true,"csrf":"<32 字符>","ttl":21600}
curl -sS -A "$UA" "$VAULT/index.php?api=highlights&count=10&lang=zh"
# → 401 {"ok":false,"error":"unauthorized"} ← 没有会话就是这样
curl -sS -A "$UA" -b jar.txt -H "X-CSRF-Token: $CSRF" -H "Referer: $VAULT" \
"$VAULT/index.php?api=highlights&count=10&lang=zh"
# → 200 {"ok":true,"items":[{"id":"…","text":"…"}, …]}

拉回来 16 条不同的留言,长度 8~40 字符,全是乱码风格短串、没有一条是自然语言:

8 q0cpcLTL
15 mJ8eq4yiDosyfy0
16 Wa3p_7F1-u8si4li
19 jSNFdjoW_yZ6RSYcR8g
24 -orGOJgC7t_NHXhhrgj8O7fr
29 UP8YXeFBvmwps9TQqCFPMDA6Ef1hQ
40 QGGip0WrIe-PKELkWUgu82WjtbMVU-IQYBcikoXK

也就是说,玩家们不是在聊天,而是在把自己解出来的 token / 碎片「呼唤」进星空。这和弹窗那句「这已没有任何意义」完全对得上:留言墙是彩蛋,不是下一环。

9.4 这一页说明了什么#

  • 命名:隐藏页叫 Solivault,终点页叫 Sky of Your Vault——合起来就是这条 ARG 的名字。
  • 密码已经确定并验证通过:Backward, go backward, turn back to the antemundane realm, go back to the -(End 页 slogan)。它既是终点页的地址,也是这一环要交出的答案。
  • 终点页不再需要解密:它是「结局 + 留言墙」,作用是收尾,并提醒你把上面那句密码带回该去的地方用掉。
  • 也因此,DISPOSSESSION / IGNORANCE 更像是中途的路标而不是终点答案;它们是否还有别的用途,得看 2026-10-02 17:00 倒计时归零后游戏里会不会有对应入口。

9.5 End 页的地址是怎么来的:之字形读表(已由社区解开)#

最后一环:栅栏 + 之字形读表

起点 NO → 之字形(\/\/\/)→ 终点 SO,读出 24 个字符。

正确的读法是「栅栏密码 + 之字形读表」:

从 NO- 开始,到 SO- 结束13 段碎片按末字母排成13×12 表格按提示之字形(rail fence)读表NOL2re@etiKdA3!ig9t~UmSO/NOL2re@…/ 即 End 页slogan = 最终密码
从 NO- 开始,到 SO- 结束13 段碎片按末字母排成13×12 表格按提示之字形(rail fence)读表NOL2re@etiKdA3!ig9t~UmSO/NOL2re@…/ 即 End 页slogan = 最终密码
  • /JUSTENGAGEWTH/ 的提示 Fence? = 栅栏密码;
  • 复制出来的 \/\/\/ = 之字形(zigzag);
  • NO- 是起点、-SO 是终点(我们采样的提示池里就有这两条,只是当时没读出来);
  • 回到最开始那张 13×12 碎片表,按之字形从 NO 读到 SO,就得到 24 字符的 NOL2re@etiKdA3!ig9t~UmSO。

这张表的每一格都来自玩家各自领到的那段碎片,所以不同玩家的表长得不一样 —— 但读法完全一样,完整流程就在本文里:

  1. 把 13 段碎片按末字母排成 13×12 表格(就是上面那张表);
  2. 在表里找到 NO 作为起点(row: 4? 5? 这个提示就是让你确认行号),再找到 SO 作为终点;
  3. 按 \/\/\/ 提示的之字形(栅栏式)路径一格一格读,读到 SO 为止;
  4. 读出来的 24 个字符就是 NOL2re@etiKdA3!ig9t~UmSO(红色路径见上图)。

对照本文的两张表图,这条流程可以一步步照着走,不需要再去找别的地方。

把这张表按提示变化后,标出之字形读取路径
把这张表按提示变化后,标出之字形读取路径

上图:社区那张“变化后”的表,红色格子标出了之字形的读取路径(从 NO 到 SO)。图来自 Phigros 解密 3 群(社区)。

当时的真实尝试(以及一次走错)

社区记录里记了过程:拿到提示后,先被 NO- 和 -SO 吸引 —— 在表里确实能连出一条 24 字符的串,形状是「SO 开头、NO 结尾」。他们先把它连成 NOUf9/@etigod=!ig9~rAVSO,又按 row: 4? 5? 把栅栏栏数试到 5(因为 5 栏的锯齿图案长得像 \/\/\/),解出 NtgOeii9OU@g!~Sf/o=rV9dA —— 结果粘到地址栏跳回了主页,说明这一串是错的。

最后他们在表格本身上按 \/\/\/ 的之字形路径连字符(从 NO 读到 SO),才拿到正确的 NOL2re@etiKdA3!ig9t~UmSO。也就是说:Fence? 讲的不是”把串拿去跑工具”,而是在表里沿锯齿走。

至于直觉上最像的那条线索 —— NO- 和 -SO 正好是 token 的头两个字符 NO 和尾两个字符 SO —— 现在也说得通了:它们本来就是在告诉你从哪读到哪里。

致谢#

这一页能写完整,是大家一起拼出来的:

  • Phigros 解密 3 群:13 段碎片的收集与排序、表格的整理、Cogito, ubi sit refugium 的顺时针读法、零宽字符转摩尔斯、Nihilist 六步解法、栅栏 + 之字形读表得出 End 页地址,都出自这个群的协作。
  • 群里在链上留下信息的几位玩家:__polar_ice(转述整理)、Soucirif(黑洞图 FFT)、unDefFtr(指出 meta 串的 ASCII 读法)、以及最早分享 End 页链接的人。
  • 官方侧的依据:TapTap 公告、第九章 PV 简介里的字母表、以及 Limbo Wiki 上那些氛围页。

没有这个群的”拼桌子”,最后那一环根本走不完 —— 谢谢各位。

十、信息来源#

这一页里的东西不是一个人挖出来的,标一下出处:

内容来源
第一章密文、26 字母表 PSZLMYQEBJARTFCHNUGVKDOXIW官方 TapTap 公告 / 第九章 PV 简介(社区玩家提供 B 站链接 BV16vbN6REhD)
黑洞图 FFT → outside_the_birdcage社区玩家(QQ 群截图,Soucirif 等人)
零宽字符 → 摩尔斯 → AROUSAL社区玩家(__polar_ice 转述的群内整理)
标题 nihilist → 5×5 方阵 + AROUSAL 减法 → JUSTENGAGEWTH社区玩家整理
13 段碎片的两层 acrostic(DISPOSSESSION / IGNORANCE)社区集齐片段后共同读出
PNG 尾部切图、api.php 指纹抓包、decodeCopy 复算我们本地脚本(browser_probe.js、grab_all.py、各解码脚本)
End 页 →《Sky of Your Vault》这条尾巴、index.php?api= 只读实测我们自己补挖(end_chain_probe.sh,只做 GET 不做 POST)
本轮密码 = End 页 slogan已确认,并已实测验证通过(密码即那句 Backward, … go back to the -)
13 段表格黄色格子 → Cogito, ubi sit refugium、Nihilist 六步、栅栏 + 之字形读表 → End 地址Phigros 解密 3 群(社区)
提示池(NO- / -SO / \/\/\/ / row: 4? 5?)的采样统计本地只读探测(hint_pool.py)
每步「意味着什么」的解释大部分由 GPT / GLM 推断,仅供参考

十一、环境与工具#

事项说明
海外 IPwiki 全线 502 / 773,必须国内 IP
api.php需要真浏览器指纹 + 国内 IP;裸 curl 只能拿默认段或错误页
playwrightnpm i playwright + npx playwright install chromium-headless-shell,脚本 browser_probe.js
抓碎片grab_all.py(随机指纹枚举)、grab_index.py(探测 index 参数)
解码zw_decode.py(零宽摩尔斯)、combine.py(Chaocipher / 碎片拼接)、rot_clean.py
防转录污染关键计算全部改成「脚本写文件 → read 回读」再采信,不信终端里直接打印的结果

十二、最后再说一次#

已核实、可复现的部分:start.png 的字节边界、零宽字符 → AROUSAL、decodeCopy 解出 try for yourself、Nihilist 减法 → JUSTENGAGEWTH、13 段末字母的 acrostic → DISPOSSESSION、提示池按指纹分配(NO- / -SO / \/\/\/ / row: 4? 5?)、尾声两页(End 页 slogan 当 URL → Sky of Your Vault;index.php?api= 的 csrf / 401 / 429 行为、留言全是乱码短串),以及最后的栅栏 + 之字形读表 → NOL2re@etiKdA3!ig9t~UmSO(社区)。

密码(已确认并实测验证通过):Backward, go backward, turn back to the antemundane realm, go back to the -。

仍带推测的部分:Chaocipher 那一步的盘序与轮转细节(明文结果能确认,规则按本文记的这套),以及 meta 数字按十进制 ASCII 读出的 8KAL#8K?aBC/H(另一种读法,不参与主线)。这些多来自 GPT / GLM 的推断,仅供参考。

倒计时到 10-02 17<00> 之后,如果游戏里真的出现了 DISPOSSESSION 或 IGNORANCE 的入口,这篇就当是提前写好的答案笔记;如果没出现,那就当我和一群玩家、外加两个模型,一起做了一次网页考古。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
Phigros 第九章《穹顶孤舟》网页解谜复盘:从 Chaocipher 到 13 段碎片拼字
https://blog.wmc.pub/posts/phi9-solivault-walkthrough/
作者
Milk
发布于
2026-09-25
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
Phigros 第九章 ARG 收官:17:00 归零那一刻,与藏在控制台里的致谢
技术Solivault 的倒计时在 2026-10-02 17:00 归零。终点页在归零后两分钟内换了一版:源码从混淆变回明文、版本号从 2.2.0 跳到 2.4.0,并多出一段只在浏览器控制台里打印的制作人员名单。这篇记录我抓到的完整时间窗和那几个藏起来的机制。
2
穹顶孤舟:Phigros 主线全章总结(含从秘密包里解出的终章)
随笔主线已经收束。这篇把一~九章连起来讲一遍:Legacy 里的一~四章、五《方舟蜃景》到八《弭刻日》的门槛与关底、第九章《穹顶孤舟》的 12 首曲与解密档案,以及最后从客户端秘密包里解出来的 C9S6 终章对白。
3
Phigros 4.0.1 第九章客户端全解:从启动到退出,这一章在程序里究竟发生了什么
技术把 Phigros 4.0.1 客户端里第九章的整条链路走完:启动时怎么恢复解锁与密钥、选曲与难度动画、关卡结算如何推进章节进度、Phase 2 换形态、谜题与推演、密码背后的 AES 方案(含 8 个秘密包的解密与加载/卸载)、Hate→DS→Message→Credits 的演出顺序,以及「退出应用」那一处——附 68 个脚本类各自干了什么。
4
穹顶孤舟 · 素材馆:把第九章整个装进一页
随笔第九章的全部可听可见之物都在这:选难度的六路视频、12 首曲的官方试听与 12 张曲绘、隐藏曲 PV、结局循环、秘密曲、31 段音效切片、10 张材质(噪域/故障/网格/密码界面)、8 组界面截图,以及完整清单表与出处。
5
Solivault 的歌里藏了什么:一次 SSTV 解码实录
技术Solivault 页面改成会播歌之后,我们把音频从 WebCrypto 解密链路里捞出来,发现节拍里藏着一条 SSTV 传输——解出一张 320×256 的角色立绘。
随机文章随机推荐

评论区

Profile Image of the Author
Milk
AWMC Founder
分类
标签
站点统计
文章
10
分类
3
标签
22
总字数
58,773
运行时长
0 天
最后活动
0 天前
文章目录