复活 Valve 已发布 15 年的电子书

Lobsters Hottest 新闻

摘要

一位爱好者详细介绍了如何通过反编译 SWF 文件并修补失效的外部网页依赖,让 Valve 于 2011 年发布的 Adobe AIR/Flash 电子书《The Final Hours of Portal 2》重获新生,并发布了一份 Steam 指南,帮助其他人恢复书中的投票、全景图、音频和演示内容。

<p><a href="https://lobste.rs/s/lzlkbr/reviving_valve_s_15_year_old_e_book">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/10/01 06:22

# 复活 Valve 15 年前的电子书 • Niko 的博客 来源:https://nikolan.net/posts/portal2/ > **如果你只是想享受 TFHoP2 的内容,并且不关心我把它修好的技术细节,请直接跳到下面的 Steam 指南来修补它。** [修复损坏的网页内容 Steam 指南缩略图Steam 指南修复损坏的内容 \[Windows\] \[2026\]我的周末项目 \- 修复《Portal 2: The Final Hours》中所有失效的内容。本指南将教你如何让投票、全景图、音频、视频和交互式演示重新工作。\](https://steamcommunity.com/sharedfiles/filedetails/?id=3766654296)## 前言 想象一下:有一款你非常喜欢的解谜游戏。你已经玩了超过 100 个小时,尽管主线故事只要 10.5 小时就能通关,整个游戏完整体验大约需要 22.5 小时。你太喜欢它了,以至于花好几个小时和朋友玩合作模式,在挑战模式里竞争最快通关时间。 这就是我与 Portal 2 的故事。 来自 HowLongToBeat 的 Portal 2 通关时长 然后你发现有一本交互式电子书,记录了整个开发过程,里面有各种有趣的内容。它只卖 0.63 欧元。你当然买了。 然后你启动它,兴奋地准备开始阅读。点击下面的播放按钮。 启动后,一个过时的 Adobe AIR 安装程序出现了: 启动《Portal 2: The Final Hours》后出现的过时 Adobe AIR 安装程序过时 Adobe AIR 安装程序的静态预览图。 ...然后你很快意识到,不像主游戏还会收到安全补丁和错误修复,这本电子书基本上没人维护了。虽然 Adobe AIR 仍由Wipro(https://www.wipro.com/newsroom/press-releases/2025/wipro-completes-acquisition-of-harmans-digital-transformation-solutions-dts-business-unit/)某种程度上维护着,但这本电子书安装的是 2011 年的版本。 如果这书还能正常工作的话,这甚至都不算什么大问题。让我们看看我找到的各种损坏的东西。 而我不想在每次翻页都提心吊胆、担心下一页会坏掉的情况下读书 :\( ## 为什么坏了? 电子书中大部分失效的功能都依赖于外部网络服务。 对于音乐,如果把歌曲打包进电子书,会让授权变得复杂。 而投票功能,使用网络几乎是唯一的选择。 不幸的是,随着时间推移,服务会不断重构,导致那些没人关心的旧接口失效。有时所有者忘记续费域名,于是被别人买走,放上了完全不相关的内容。还有些时候,服务仅仅因为缺乏维护而坏掉。这本电子书中包含了以上三种情况的例子。 全景图查看器是例外。它们的资源是本地存储的,但即使使用相同版本的 Adobe AIR,在较新版本的 Windows 上仍然无法工作。这一点我稍后再说。 现在让我们来弄清楚到底哪些东西坏了,首先来检查电子书的文件: 电子书的安装目录,包含 TheFinalHoursOfPortal2.swfSWF 文件。前面已经提到,电子书使用的是 Adobe Flash,所以我需要想办法反编译它们。因为我对此毫无经验,所以转向 Google 搜索: 一个搜索如何反编译 SWF 文件的 Google 搜索结果,指向 JPEXS Free Flash Decompiler它把我引向了最优秀的软件——JPEXS Free Flash Decompiler (https://github.com/jindrapetrik/jpexs-decompiler): JPEXS Free Flash Decompiler 的欢迎界面我搜索了主 SWF 文件以及另外五个附加的 SWF 文件,整理出了所有在线依赖项的清单。以下是我恢复每个依赖项的方式: ### 视频 这个应用使用的是 YouTube 古老的 ActionScript 3 Player API,该 API 已经停用了十多年。 原来的 API 工作原理是:从 YouTube 加载一个播放器 SWF 可执行文件。电子书通过`loadVideoById()`、`playVideo()`和`pauseVideo()`等方法来控制那个 SWF,同时监听播放事件。 由于我不会写 Flash 代码,我使用了 GPT-5.6-Sol 来帮忙编写一个替代的 ActionScript 播放器,并编译成 SWF 文件。它重建了 YouTube API 中电子书所需要的部分,但不用 YouTube,而是把这些调用转化为播放本地 MP4 文件。 但 YouTube 并不直接提供 MP4 文件,而且有些视频已经无法访问了。电子书中包含九个 YouTube 视频: - 第 3 章,第 10 页:https://www.youtube.com/watch?v=j7LFbmTHY78 - 第 3 章,第 10 页:https://www.youtube.com/watch?v=CkoMbxHQmuM - 第 6 章,第 4 页:https://www.youtube.com/watch?v=DnMdBnLWvpg - 第 7 章,第 3 页:https://www.youtube.com/watch?v=0Zzfdlxjx4Y - 第 7 章,第 5 页:https://www.youtube.com/watch?v=JpFNKyeckZc - 第 11 章,第 2 页:https://www.youtube.com/watch?v=VLqw5JW8OLY - 第 12 章,第 2 页:https://www.youtube.com/watch?v=GOMI0BxB0yA - 第 12 章,第 3 页:https://www.youtube.com/watch?v=Im6yRpQrsaY - 第 12 章,第 3 页:https://www.youtube.com/watch?v=pZaY1jV96jI 我使用了yt-dlp (https://github.com/yt-dlp/yt-dlp)来下载每一个视频。只有两个需要额外处理: - 一个是年龄限制的,但我通过向 yt-dlp 传递 cookies 成功下载了。 - 另一个是私密的。我把它的视频 ID 贴到 Google 上搜索了一番,找到了它的标题:"She's Too Good For Everyone."。在 YouTube 上搜索这个标题让我找到了一个重新上传的版本 (https://www.youtube.com/watch?v=K2FP77IIdE8)。 ### 3D 和游戏 电子书中包含三个 3D 可视化和一个交互式小游戏,这四个全都依赖于已失效的 URL: - 第 3 章,第 7 页 — Portal 小游戏:http://www.thefinalhoursofportal2.com/TFHoP2_assets/howto/diagram.html - 第 7 章,第 8 页 — Wheatley 3D:http://www.thefinalhoursofportal2.com/TFHoP2_assets/interactive/index.html - 第 9 章,第 1 页 — The Odd Couple 3D:http://www.thefinalhoursofportal2.com/TFHoP2_assets/oddcouple/ - 第 13 章,第 1 页 — Companion Cube 3D:http://www.thefinalhoursofportal2.com/TFHoP2_assets/companioncube/ 起初我很沮丧。这些 URL 都没有被存档,而那个域名已经被别人注册了,上面放的是一堆垃圾内容 :\( 搜索了大约一个小时后,我仍然找不到存档副本。看来重造它们是我最好的选择,于是我从 Portal 小游戏开始,做得相当不错: 原始 Portal 小游戏与复刻版的对比视频对比原始 Portal 小游戏和复刻版的视频。观看或下载视频。(https://nikolan.net/posts/portal2/images/comparvid.mp4)我觉得效果挺好的,特别是我只参考了一段 10 秒的视频。到那时,我已经心满意足了。 有一次我发现这本电子书还有一个原生的 iOS 版本。没抱什么特别的期待,我决定试试看。 在一番搜索之后,我在一个 173.7 GB 的Archive.org 合集(https://archive.org/details/missing-ipas/)"Missing IPAs" 里找到了它的 IPA 文件。它的描述只有一句话:"Some stuff",里面包含了超过一万个 IPA 文件。 如果你可能需要的话,这里是一个直接下载链接: https://archive.org/download/missing-ipas/com.joezeffdesign.finalhoursofportaltwo%20-%20Geoff.Keighley.Presents.The.Final.Hours.of.Portal.2.v1.7.iPad-Lz0PDA.ipa 自从 App Store 随 iPhone OS 2 推出以来,下载的应用都是以加密形式分发的。授权设备会在应用的可执行页面被加载到内存时对其进行解密。因为处理器要执行这些页面,它们必须以解密形式存在,所以可以从越狱设备的内存中提取它们。 幸运的是,有人正好已经对我找到的这个 IPA 做了这样的处理,这意味着我可以把它安装在我的 iPad 上,而不需要拥有原始应用。 然后我发现了一些有趣的事情: 那四个可视化居然全都正常工作了! 这是因为与 PC 版本不同,移动应用把所有可视化的代码和资源都打包在本地了。 我把`.ipa`文件重命名为`.zip`,然后在里面找到了这些资源。因为它们是标准的 HTML 文件,我只需要简单地把它们复制到我的电脑上就行了! 因为只是普通的 HTML 和 JavaScript,你可以在下面试试原始的 Portal 小游戏。你可以拖动小人到处走,把他扔进传送门里: 下面是修复后的 Portal 小游戏的静态预览图。打开链接的交互版本来玩它。 Portal 小游戏的静态预览图,包含一个角色和两个传送门 (https://tfhop2.nikolan.net/TFHoP2_assets/howto/diagram.html)Portal 小游戏的静态预览图。 ### 音乐 电子书从`mzstatic.com`域名加载了八首歌曲。 其中七首来自第 5 章的一个播放列表: - East Bound and Down:http://a5.mzstatic.com/us/r1000/050/Music/89/1f/6d/mzm.hmsvmlsc.aac.p.m4a - Queen of Denmark:http://a4.mzstatic.com/us/r1000/013/Music/9f/da/c0/mzi.dviddoso.aac.p.m4a - Polaroids and Red Wine:http://a1.mzstatic.com/us/r30/Music/2c/81/ca/mzi.wxxicnqc.aac.p.m4a - My Violent Heart \(Pirate Robot Midget\):http://a1.mzstatic.com/us/r1000/013/Music/90/2a/b7/mzm.ojhmmnlb.aac.p.m4a - Bang Bang Bang:http://a5.mzstatic.com/us/r1000/022/Music/24/12/e8/mzi.bukbidcp.aac.p.m4a - Bridges and Balloons:http://a4.mzstatic.com/us/r1000/026/Music/e4/6f/19/mzm.hcizchvw.aac.p.m4a - Bilar:http://a2.mzstatic.com/us/r1000/036/Music/d7/5e/9b/mzi.eyucogyw.aac.p.m4a 第八首出现在第 3 章,第 10 页 — Still Alive:http://a5.mzstatic.com/us/r30/Music/3e/c7/48/mzm.cxiybvxa.aac.p.m4a 基础域名`mzstatic.com`会重定向到`apple.com`,而电子书中的注释说明音频样本由 iTunes 提供。 我在music.apple.com (https://music.apple.com/) 上找到了所有八首歌曲。Apple Music 的网页版也提供预览,不需要身份验证。 我通过复制歌曲的 Apple Music 链接并取最后一个数字来找到每首歌曲的 ID: `https://music.apple.com/us/song/still-alive/270749989` 然后我使用 API 获取它的 30 秒预览: 一个使用 Apple Music 歌曲 ID 获取音频预览 URL 的 Python 脚本我重复这个过程,下载了每首歌的预览。 ### 投票 这些是投票的原始 URL: - 第 1 章,第 5 页 — 投票 1:http://www.gameslice.com/p2polls/poll1.php5 - 第 5 章,第 6 页 — 投票 6:http://www.gameslice.com/p2polls/poll6.php5 - 第 9 章,第 6 页 — 投票 3:http://www.gameslice.com/p2polls/poll3.php5 - 第 12 章,第 6 页 — 投票 4:http://ww.gameslice.com/p2polls/poll4.php5 - 第 13 章,第 3 页 — 投票 5:http://www.gameslice.com/p2polls/poll5.php5 - 第 14 章,第 5 页 — 投票 20:http://geoffkeighley.com/p2polls/poll.php5?id=20 - 第 14 章,第 8 页 — 投票 21:http://geoffkeighley.com/p2polls/poll.php5?id=21 所有链接都已失效。 有意思的是,我不认为他们是故意把投票下线的。我猜测是一次后端更新在没人注意的情况下把它们弄坏了。因为大多数 URL 返回的是`500 Internal Server Error`而不是`404 Not Found`: 浏览器控制台报告 500 Internal Server Error当我在Wayback Machine(https://web.archive.org/)中输入`http://www.gameslice.com/p2`并进入其 URL 部分后,我发现有一个投票被完整存档了,包括它的字体和样式: Wayback Machine 列出了一个存档的 Portal 2 投票及其支持文件存档的投票询问玩家对 Portal 2 的看法 这太好了,因为哪怕只有一个幸存的投票,也足够让我重现原始的风格和布局了。 复刻的 Portal 2 投票与其在 Visual Studio Code 中的源代码的对比然后我需要其余的内容。我找到了一个PDF 版本(https://valvearchive.com/Games/Portal%202/Documents/The_Final_Hours_of_Portal_2_ENG.pdf),里面包含了到第 13 章为止的其余问题,所以我把它们都记了下来。 问题在这里:第 14 章是在后续更新中加入的,包含两个投票。据我所知,这两个问题在任何地方都没有被存档。我花了大约两个小时搜索,什么也没找到。我找到的每一个 PDF、评测和录像,包括 iPad 版本,都只覆盖到第 13 章的内容。 我甚至找到了一个通过 Amazon 分发的版本。令人惊讶的是,它包含了第 14 章,但因为它是一个纯文本的离线电子书,所以没有投票。 **如果你有任何旧的录像、截图,或者其他可能帮助我恢复这两个投票的东西,请、请、请一定要联系我。** 顺便说一句,第 14 章还有一个我没能恢复的东西,看起来像是一个订阅表单: - 第 14 章,第 10 页 — 订阅表单:http://geoffkeighley.com/p2polls/subscribe/index.php5 ### 反馈表单 书的最后是一个反馈表单。这是唯一一个还能按预期加载的在线功能: 电子书的反馈表单及其原始读者评论但提交新评论后,它会卡在审核队列中。 和投票一样,我可以复制原始的 HTML 和 CSS。但所有旧评论怎么办呢?当这个最后还能工作的部分最终关闭后,那些旧评论会怎么样? 我决定也把这件事解决掉。一个Python 脚本(https://github.com/nikolan123/TFHoP2-server/blob/main/comments_archive/export.py)从旧的 Gameslice 服务器上抓取了所有分页的反馈页面,解析了每条评论的作者、内容和时间戳,并将结果保存为 CSV 文件,以便导入到替代服务器中。总共我备份了 2,662 条评论。 ### 本地例外:全景图 全景图与其他失效的功能不同,因为它们的资源是本地的,所以不需要重新托管。 尽管如此,所有三个全景图查看器在当前版本的 Windows 11 上都已停止工作。有意思的是,它们在较旧的 Windows 10 版本上仍然可以工作,即使两个系统安装的是相同版本的 Adobe AIR。 我在较新的、出问题的系统上能够一致地复现两个错误: - 错误 \#3207 出现在现有的`Security.allowDomain("*")`调用附近。 - 错误 \#3226 出现在从没有`allowCodeImport`的嵌套 SWF 中加载编译代码时。 我不知道那些 Windows 版本之间到底发生了什么变化,导致相同的 AIR 代码会触发这些错误。我最好的猜测是新的沙箱行为干扰了`HTMLLoader`嵌入嵌套 SWF 的方式。 我所知道的是修复方法:将`HTMLLoader`替换为原生的`Loader`,并显式允许代码导入。这样所有三个全景图都能重新工作了。我又一次使用了 GPT-5.6-Sol 来帮我弄清楚这一点,因为我对 Flash 一无所知。 ## 现在怎么办? ### 我最初的服务器 我已经恢复了外部资源,并弄清楚了如何修复本地的全景图。但怎么才能把所有东西真正放回去? 我的第一个目标是拼凑一个服务器来重新托管所有东西,只是为了看看这个概念是否可行。 我选择了 Python 和 FastAPI 作为技术栈,因为这是我熟悉的技术。 为了把原始请求重定向到我的电脑,我使用了 hosts 文件,它告诉系统去哪里找每个域名。我修改了它,让电子书联系的每个域名都指向我自己的电脑。这包括`youtube.com`、`thefinalhoursofportal2.com`等等。 然后我把所有静态资源按照它们的原始路径挂载好,包括自定义的 YouTube 复刻版本,然后启动了服务器。 我还需要一个地方来存储评论和投票数据,所以我用了一个基本的 SQLite 数据库来让所有东西持久化。 经过一些故障排除后,我让所有东西都工作了! 这就是结果: 修复后的交互式 3D Companion Cube 可视化正常工作的 3D 可视化 ### 公共服务器 完成的服务器可以在github.com/nikolan123/TFHoP2-server(https://github.com/nikolan123/TFHoP2-server)下载和自行托管。 接下来的问题是分发。我不能把 600 MB 的视频和一批受版权保护的歌曲打包进去。这样做会让开源服务器的分发变得困难得多,并且会造成明显的法律问题。 解决办法很简单。与其自己提供音频,我让客户端重定向到原始的预览 URL。 对于 YouTu

相似文章

逆向工程游戏:关于游戏反编译、重编译、VR 与网页/3D 移植的全部新闻

The Verge

The Verge 的这期盘点聚焦于逆向工程游戏的热潮:通过反编译和重编译技术,让《塞尔达》《Halo》《Lego Racers》等经典游戏摆脱专有代码和原始硬件的束缚,移植到新设备,或以彻底改变原作的方式进行改造——包括在 Vision Pro 上运行的 Half-Life: Alyx,同时探讨了 AI 辅助开发及法律灰色地带的问题。

逆向工程与现代化老游戏如何揭示AI的经济影响

Hacker News Top

一篇博客文章详细介绍了使用AI模型如Qwen-3.8-Flash-Next、Fable 5.1和GPT6 Astra对1989年的游戏War of the Lance进行逆向工程和现代化,强调了基于transformer的AI对游戏开发和模组制作的经济影响。