gengyunmaster/BallanceMiniInstaller

GitHub: gengyunmaster/BallanceMiniInstaller

该工具将大型 Ballance 游戏/整合包打包成约 20MB 的单文件 Windows 安装程序,通过有损预编码和安装时转码实现极高压缩比。

Stars: 0 | Forks: 0

# Ballance 迷你安装包构建器 将约 900 MB 的 Ballance 游戏/整合包打包成一个**约 20 MB 的单文件 Windows 安装程序** (`BallanceSetup.exe`) —— 只需一条命令,在 Linux 上完全离线运行。 该技术逆向工程自原始的 2005 年 Ballance 安装程序 (15 MB → 130 MB 游戏):**有损预编码 + 安装时转码**,而不是 更好的无损压缩器。本项目使用 2026 年的编解码器(WebP + Vorbis + LZMA2) 重新实现了这一技巧,并将其封装在一个静默、精良的安装程序中。 **目录**:[原始技巧](#the-original-trick-reverse-engineering-the-15-mb-installer) · [工作原理](#how-it-works) · [快速开始](#quick-start) · [安装程序用户体验](#the-installer-ux-what-players-see) · [可调参数](#tunables) · [自检](#self-check-s8) · [CI](#ci--releases) · [疑难解答](#troubleshooting--lessons-learned) · [第三方声明](#third-party-notices) · [法律声明](#legal-note) ## 原始技巧(逆向工程 15 MB 安装程序) 这个项目源于一个谜题:经典的 `Ballance_1.13_en.exe` 大小为 **15.7 MB**,却安装了 **130 MB** 的游戏 —— 而使用 7-Zip(LZMA,最高设置) 重新压缩安装后的文件,最低也只能达到 **42 MB**。 一个 2005 年的安装程序怎么可能比 LZMA 还要小 3 倍? ### 第 1 层:一个几乎不进行压缩的 Wise 外壳 该 exe 是一个 14 KB 的 PE 存根,外加一个 15.7 MB 的附加数据(熵 ≈ 8 bits/byte)。 字符串分析表明它是 **Wise Installation Wizard**(2000 年代产物)。 对 zlib 数据流的简单扫描发现了 31,770 个候选头信息 —— **全是误报** (在 15 MB 高熵数据中命中随机数据是意料之中的;教训是:务必通过 实际解压来进行验证)。真实的格式(根据 [REWise](https://codeberg.org/CYBERDEV/REWise) 和 [Archive Team wiki](http://fileformats.archiveteam.org/wiki/Wise_installer_package)) 是一个 Wise 头部,紧随其后的是 `[raw-DEFLATE entry][CRC32]` 记录,直到 EOF。 遍历该附加数据可得到 16 个条目,CRC 全部有效: | # | 偏移量 | 压缩后大小 | 解压后大小 | 内容 | |---|---|---|---|---| | 0 | 0x3aa9 | 20,428 | 40,362 | WiseColors.dib (140×144 安装向导图像) | | 1 | 0x8a79 | 3,445 | 12,606 | WiseScript.bin (安装脚本,对话框字符串) | | 2–7 | … | ~137 KB | ~504 KB | Wise 引擎 DLL,对话框模板,资源文件 | | 8–11 | … | ~2.4 KB | ~5 KB | 小型数据块 | | 12 | 0x2c34c | 61,622 | 153,088 | UNWISE.EXE (卸载程序) | | **13** | **0x3b406** | **15,430,382** | **15,431,518** | **MAIN.exe** — DEFLATE 比率为 1.00007 | | 14–15 | … | ~63 KB | ~317 KB | 卸载脚本数据 | 第 13 个条目就是铁证:DEFLATE 对它**毫无作用**(它已经被 压缩过了)。它的 CRC32 `7d872a8c` 与游戏自身的 `INSTALL.LOG` 记录 完全匹配 —— 实现了逐位精确恢复。Wise 包装器(构建于 2010 年)只是一个 交付载体;实际的有效载荷是 **MAIN.exe(构建于 2005-04-07,v4.16.0.0)**。 ### 第 2 层:MAIN.exe 是一个 7-Zip SFX ``` Type = 7z, Offset = 79360 ← 79 KB UPX-packed SFX stub Method = LZMA:24 BCJ, Solid = + ← 16 MB dictionary + x86 filter 358 files: 42,758,769 → 15,346,746 bytes ``` ### 第 3 层:有效载荷*并不是*安装后的字节 | 压缩包内容 | 安装后的结果 | 压缩率 | |---|---|---| | 62 × `.ogg` (3.35 MB) | 62 × `.wav` (34.3 MB) | 10.3× | | 62 × `.jpc` JPEG2000 (3.0 MB) | 62 × `.bmp` (~63 MB) | ~21× | | NMO/DLL/TGA/AVI/etc. (~36 MB) | 相同的文件,字节一致 | — | 压缩包中还包含 `temp/oggdec.exe` ("OggDec 1.0")、`temp/nicej2k.exe` (一个 JPEG2000 解码器)以及两个批处理脚本(`1.bat`/`2.bat`),它们负责在安装时 解码所有内容,然后删除源文件及其自身。 **证据**:重新解码 OGG 文件可以逐样本还原已安装的 WAV 文件 (0.05% 的样本存在 ±1 LSB 的误差 —— 这仅仅是解码器的舍入误差);已安装的天空 BMP 文件与 `.jpc` 解码结果完全匹配,像素差异为 **零**。 ### 答案 无损压缩器受限于你输入的字节的熵。 安装后的 WAV/BMP 字节具有约 42 MB 的熵,因此没有任何无损编解码器能够 达到 15 MB。安装程序根本就没有存储这些字节:它存储的是 **感知编码**的媒体(小 10–21 倍),并在安装时重新生成了 WAV/BMP 文件。 它是通过改变游戏规则获胜的,而不是通过把游戏玩得更好。 *(有趣的脚注:`2.bat` 包含一个拼写错误 —— `del /Q texures\atair.jpc` —— 因此 `Textures/atari.JPC` 在每次安装后都能幸存至今;而且 nicej2k 会 在转换后的每个 BMP 后填充 262,634 字节的未初始化尾部垃圾,导致每次安装中都会多出 约 16 MB 的无效负载。)* ## 工作原理 相同的架构,采用现代编解码器: ``` Build side (Linux, offline) Install side (Windows, offline) ───────────────────────────── ─────────────────────────────── Textures *.bmp BallanceSetup.exe double-clicked └─ downscale to ≤1024px + WebP q85 ──┐ ├─ 7z SFX stub unpacks payload Sounds *.wav │ ├─ "Ballance Setup" prompt shows └─ Vorbis q4 ────────────────────────┼─ 7z │ the real install path Everything else (NMO/DLL/EXE/AVI/...) │ LZMA2 ├─ run.vbs (hidden) drives install.bat: └─ stored as-is ─────────────────────┘ solid │ tools\dwebp.exe → BMPs + 7zSD.sfx stub ──→ BallanceSetup.exe tools\oggdec.exe → WAVs └─ desktop shortcut + uninstall entry, cleanup, silent exit ``` - **WebP 替代了 JPEG2000**(更好的压缩率,`dwebp.exe -bmp` 在安装时 可直接解码为 BMP) - **保留 Vorbis**(Opus 会强制使用 48 kHz 并改变每个文件的采样 率;Vorbis 保留了原始设置 —— 这与 2005 年打包工具的选择 一致) - **LZMA2 64 MB 字典 + BCJ2 + 固实压缩** 替代了 LZMA 16 MB - 带有**尾部垃圾**的 BMP(在原版文件中发现的老式 nicej2k 伪影) 在编码前会被截断为其声明的 `bfSize` —— 否则 ffmpeg 会 尝试将垃圾数据作为额外帧进行解码并导致失败 在一个 877 MB 的整合包上测试的结果:**23.6 MB** 安装包。在一个 130 MB 的原版 整合包上:**18.0 MB**(天空图像在 512px/q85 质量下从 743 MB 缩小到了 0.6 MB;即使是 1024px 的 安装分辨率,也依然是原版 512px 分辨率的 2 倍)。 ## 快速开始 ``` # 1. 下载 toolchain(官方来源,约 120 MB) ./fetch_tools.sh # 2. 将您的游戏打包为 .7z(请参阅下方的“Game package requirements”) # 3. Build(此后完全离线) ./build_installer.sh Ballance.7z BallanceSetup.exe ``` ### 游戏整合包要求 `.7z` 文件必须包含游戏根目录(一个包含 `Textures/` 和 `Sounds/` 的目录 —— 自动检测),并带有安装后的游戏应具备的所有内容。 接下来的构建过程会: - 将每个 `.bmp` → `.webp` 进行转换(将所有超过 `IMG_SCALE` 像素的图像进行缩小), - 将每个 `.wav` → `.ogg` 进行转换(Vorbis q4), - 如果存在 `VC_redist.*.exe` 则将其删除, - 保持其他所有文件字节完全一致, - 通过重放安装过程并与源文件进行 diff 对比来验证结果 (参见 [自检](#self-check-s8))。 示例(使用原版游戏):将你的 `Ballance/` 文件夹打包为 `Ballance.7z`,然后运行 `./build_installer.sh`(默认设置:输入为 `Ballance.7z`, 输出为 `BallanceSetup.exe`)。 ## 安装程序用户体验(玩家所看到的) 1. 双击 → 显示 7z 解压进度,然后弹出一个提示 显示真实的安装路径(`%LOCALAPPDATA%\Programs\Ballance`)的 **“Ballance Setup”**。 点击 OK 进行安装,点击 Cancel 则静默退出。 2. 其他所有操作都是不可见的(没有控制台窗口):文件被复制 (自动创建目录、自动覆盖),纹理被解码为 BMP,声音被解码为 WAV, 并带有逐步的退出代码检查和解码文件数量断言。 3. 安装成功:创建一个 `Ballance` 桌面快捷方式(→ `Bin\Player.exe`,起始位置为 `Bin`), 在“应用和功能”中添加一个带有可用卸载程序的条目(HKCU,无需管理员权限), 临时文件/解码器/脚本将被移除,随后静默退出。 4. 仅在失败时:弹出一个带有错误代码的消息框。 SFX 存根包含一个注入的应用清单(`supportedOS` Win7–Win11),因此 Windows 程序兼容性助手会保持静默 (参见 `patch_sfx_manifest.py`)。 ## 可调参数 位于 `build_installer.sh` 的顶部: | 变量 | 默认值 | 含义 | |---|---|---| | `IMG_SCALE` | `1024` | 像素;更大的图像会被缩小(保持长宽比) | | `IMG_Q` | `85` | WebP 质量 0–100(`75` ≈ 体积 −15%,视觉上更柔和) | | `IMG_METHOD` | `6` | cwebp 压缩力度(6 = 最佳压缩率) | | `QAUDIO` | `4` | Vorbis 质量(`6` ≈ 体积增加 +3 MB,动态余量更大) | ## 自检 (S8) 每次构建都会在 Linux 上重放安装过程,并与源代码树进行 diff 对比: - 非媒体文件:SHA1 必须匹配 - BMP 文件:尺寸/位深必须与缩小规则匹配 - WAV 文件:采样率/声道数/位深必须匹配;长度差值 ≤ 16 KB(Vorbis 尾部样本对齐是正常现象);能量比在 0.25×–4× 之间(防止 解码失败);打印原始 SNR 供参考 - 任何缺失/多出的文件都会导致构建失败 ## CI / Releases - `.github/workflows/ci.yml` — 在每次 push/PR 时:获取工具链, 生成一个**合成游戏**(`tests/make_synthetic_game.sh`:大/小尺寸 BMP,带垃圾尾部的 BMP,多采样率的 WAV),构建安装程序,并运行 自检。保持流水线免受回归问题影响。 - `.github/workflows/release.yml` — 手动触发 `workflow_dispatch`:为它提供一个 指向你的游戏 `.7z` 的 URL(由你自行托管 —— 绝不包含在此 repo 中)以及一个 tag;它会构建 并发布 `BallanceSetup.exe` + `SHA256.txt` 作为 GitHub Release。 或者在本地构建并运行 `gh release create BallanceSetup.exe SHA256.txt`。 ## 疑难解答 / 经验教训 以下所有内容都是在真实机器上经过惨痛教训学到的: - **`RunProgram="cmd /c install.bat"` 失败**(“系统找不到指定的 文件”) —— 原版 SFX 通过 `CreateProcess` 运行 `RunProgram`, 它无法正确处理带有参数的批处理命令。请使用 `ExecuteFile` + `ExecuteParameters`(通过 `ShellExecuteEx` 运行)。 - **从桌面快捷方式启动时出现“failed to initialize player”** —— Virtools 加载 组件时依赖于*工作目录*。资源管理器双击会将 CWD 设置为 exe 所在文件夹;快捷方式则使用其“起始位置”字段。它必须是 `...\Bin`,而不是游戏根目录。 - **在 Windows 10/11 上弹出 PCA 窗口**(“此程序可能未正确 安装”) —— 原版 `7zSD.sfx` 没有应用程序清单。 `patch_sfx_manifest.py` 会重建 PE 资源段并注入一个清单 (原有 8 个资源按字节原样保留)。此外,注册一个卸载 条也能满足 PCA 的安装程序启发式判定。 - **在某些 BMP 文件上出现 ffmpeg “Cannot write more than one file with the same name”** —— 原版 Ballance 的 BMP(由 2005 年的 nicej2k 生成)在声明的尺寸之外还 带有约 262 KB 的尾部垃圾;ffmpeg 会尝试将这些垃圾解码为 额外的帧。构建过程会先将其截断至 `bfSize`。 - **杀毒软件**可能会在解压过程中吃掉 `install.bat`/解码器 exe 文件 —— 如果 安装过程在解码步骤失败,请检查隔离日志。 - **无控制台窗口**:`wscript.exe`(GUI 子系统)+ `sh.Run(..., 0, True)` 会完全隐藏运行批处理;错误报告通过退出代码和 vbs 包装器的消息框进行。 ## 第三方声明 本项目仅分发**脚本**。在设置阶段,`fetch_tools.sh` 会从官方来源下载以下组件;它们的许可协议适用: | 组件 | 来源 | 许可证 | |---|---|---| | 7-Zip (`7zz`, `7zSD.sfx`) | [7-zip.org](https://www.7-zip.org/) | LGPL | | libwebp (`cwebp`/`dwebp`) | [WebM project](https://storage.googleapis.com/downloads.webmproject.org/releases/webp/) | BSD | | ffmpeg | [johnvansickle.com](https://johnvansickle.com/ffmpeg/) | GPL | | OggDec | [rarewares.org](https://www.rarewares.org/ogg-oggdec.php) | GPL | | `7zSD.sfx` 清单补丁 | `patch_sfx_manifest.py` (本仓库) | MIT (本项目) | 格式参考:[REWise](https://codeberg.org/CYBERDEV/REWise), [Archive Team — Wise installer package](http://fileformats.archiveteam.org/wiki/Wise_installer_package)。 ## 法律声明 Ballance 是一款商业游戏(Cyparade / Atari,2004 年)。**本仓库 不包含任何游戏文件,而且永远不会。**你必须提供自己合法 获取的副本。对于你如何分享自己构建的安装程序, 作者不持任何立场 —— 那是你自己的责任。请勿将包含游戏的 安装程序附加到本仓库的公共发布中。 ## 许可证 MIT(在仓库创建时选择)。本仓库中的脚本 (`build_installer.sh`、`fetch_tools.sh`、`verify_replay.py`、 `patch_sfx_manifest.py`、`tests/`)均基于 MIT 许可协议;第三方组件 仍受其各自的许可协议约束(见上文)。
标签:Cutter, 云资产清单, 安装包制作, 数据压缩, 游戏打包, 逆向工具, 逆向工程, 音视频转码