adm244/ags2_decomp

GitHub: adm244/ags2_decomp

对经典冒险游戏引擎 AGS 2.x 运行时进行逆向工程和指令匹配的反编译项目,旨在为软件保存和教育目的还原接近原始版本的源代码。

Stars: 0 | Forks: 0

# AGS 2.x 反编译 Adventure Game Studio (AGS) 2.x 的匹配反编译项目。 目标是出于软件保存和教育目的,反编译所有公开发布的 AGS 2.x 版本。 本项目**仅**专注于 runtime engine,**不**包含编辑器组件(DOS 版的 `roomedit` 以及后来的 Windows 版 `agsedit`)。 本仓库中的代码是逆向工程、源码重构和指令匹配过程的结果。源码重构基于 AC 1.14 [roommake](https://archive.org/details/rmakesrc) 和 AGS [legacy](https://github.com/adventuregamestudio/ags/tree/legacy) 源码,主要目标是生成尽可能接近原始版本的源代码。 ## 状态 版本 2.00 已**完成**,demo game 可以完全游玩。下一个里程碑将是 2.05,因为这是第一个可以通过“真实”游戏进行测试的版本:LassiQuest。 有关更多信息,请参阅 [STATUS](./STATUS.md)。 ## 构建 要构建 DOS 可执行文件,您需要运行在 DOS 上的完整 [DJGPP 环境](https://archive.org/details/DJGPP_Development_System_August_1998)或 DJGPP [交叉编译器](https://github.com/andrewwutw/build-djgpp)。如果您计划进行指令匹配,请使用 DJGPP 环境;否则,建议使用交叉编译。 构建说明假定使用 **unix** 类操作系统,如果您使用的是 **windows**,请考虑使用兼容层或 DJGPP 环境方法。 ### 交叉编译 1. 下载并解压 DJGPP [交叉编译器](https://github.com/andrewwutw/build-djgpp/releases/tag/v2.6)。 2. 克隆或[下载](https://github.com/adm244/ags2_decomp/archive/refs/heads/main.zip)本仓库: ``` git clone https://github.com/adm244/ags2_decomp.git ``` 3. 进入您希望编译的 AGS 版本目录(例如 `ags200`): ``` cd ags2_decomp/ags200 ``` 4. 运行 GNU make 以创建构建目录结构(只需一次): ``` make prepare ``` 5. 运行 GNU make 进行编译。将 `DJGPP_DIR` 指向交叉编译器的根目录(即 `setenv` 所在的位置)(例如 `~/cross/4.9.4/djgpp`): ``` make DJGPP_DIR=~/cross/4.9.4/djgpp ``` 如果构建成功,您将在 `bin` 目录中找到编译后的二进制文件(例如 `ags200/bin`)。 要删除所有可执行文件和目标文件: ``` make clean ``` 或者要同时删除已编译的依赖项: ``` make distclean ``` ### DJGPP 环境 此方法允许使用与生成原始二进制文件相同的编译器版本,这是指令匹配所必需的。如果您不关心这一点,建议使用交叉编译。 尽管您可以使用任何 DJGPP 版本,但这些说明假定您使用的是 1998 年的[此](https://archive.org/details/DJGPP_Development_System_August_1998) CD ISO,它与原始环境非常匹配。 #### 准备环境 1. 创建一个包含 DJGPP 环境的目录(例如 `~/djgpp-env`)并进入该目录。 2. 创建 `DJGPP` 目录并将 `v2/djdev201.zip` 解压到其中。 3. 按照以下顺序将以下包解压到 `~/djgpp-env/DJGPP` 中: ``` v2gnu/bnu27b.zip # GNU binutils 2.7 (do NOT use 2.8.1) v2gnu/fil316b.zip # GNU fileutils 3.16 v2gnu/gcc281b.zip # GNU gcc 2.8.1 v2gnu/gdb416b.zip # GNU debugger 4.16 (optional) v2gnu/gpp281b.zip # GNU g++ 2.8.1 (unpack with replace) v2gnu/lgp2811b.zip # GNU libg++ 2.8.1.1 v2gnu/mak3761b.zip # GNU make 3.76.1 v2misc/mlp107b.zip # ML's djp 1.07 (optional) # 如果你需要 DPMI 也要解压这个: v2misc/csdpmi3b.zip # CS's DPMI 3 (names in UPPERCASE) ``` 4. 确保 `DJGPP/djgpp.env` 包含 `+LFN=n` 以禁用 LFN 支持。 此时,您应该在 `~/djgpp-env` 中拥有一个完整的 DJGPP 环境,已准备好进行编译步骤。 5. 克隆或[下载](https://github.com/adm244/ags2_decomp/archive/refs/heads/main.zip)本仓库到 `~/djgpp-env`: ``` git clone https://github.com/adm244/ags2_decomp.git ``` 6. 将 `ags2_decomp` 重命名为 `agsdec`(为了符合 8.3 规范,可选): ``` mv ags2_decomp/ agsdec/ ``` 如果您计划使用 DOSBOX(推荐使用 [DOSBOX-X](https://dosbox-x.com/)),请在 DJGPP 环境目录中创建具有以下内容的 `dosbox.conf`: ``` [autoexec] @SET PATH=C:\DJGPP\BIN;%PATH% @SET DJGPP=C:\DJGPP\DJGPP.ENV ``` 7. 从 `~/djgpp-env` 启动 DOSBOX。 #### 编译 以下说明假定您已将 DJGPP 环境目录挂载为 C 盘,并且本仓库的内容位于 `C:\AGSDEC`。 1. 进入您希望编译的 AGS 版本目录(例如 `AGS200`): ``` cd AGSDEC\AGS200 ``` 2. 运行 GNU make 以创建构建目录结构(只需一次): ``` make prepare ``` 3. 运行 GNU make 进行编译: ``` make ``` 如果构建成功,您将在 `BIN` 目录中找到编译后的二进制文件(例如 `AGS200\BIN`)。 ## 指令匹配 此过程确保重构的源代码在使用特定编译器版本编译时,能生成与原始二进制文件完全相同的汇编指令。匹配是通过一个简单的 diffing 脚本,对所有目标文件中的每个函数手动完成的。 请记住,这**不**保证输出是逐字节相同的,因为跳转指令可能具有不同的目标,并且全局变量被放置在不同的地址。因此,在此步骤之后应进行行为匹配过程,以确保行为完全一致。 指令匹配应在 **host** 系统上进行,因为 `diff_symbol.sh` 脚本需要相对较新版本的 `bash` 和 `binutils`,您还需要安装 `cat`(textutils 的一部分)、`grep`、`awk`、`diff` 和 `less`。 确保您已成功编译 `ac.exe` 并且 `obj` 目录中包含目标文件。 运行以下命令以匹配 `AC.O` 中的 `update_stuff` 函数: ``` make diff OBJECT=AC.O SYMBOL=update_stuff ``` 在某些情况下,可能有多个具有相似名称的函数,您可以指定符号索引来选择其中一个: ``` make diff OBJECT=AC.O SYMBOL=run_animation SYMBOL_INDEX=1 ``` 有关可以匹配的所有函数的列表,请参阅 `orig/ac_symbols.txt` 文件。该列表是通过逆向工程并从 Ghidra 导出标记的函数获得的。 有关指令匹配和 GCC2 特定模式的信息,请参阅 [GCC2_NOTES](./docs/GCC2_NOTES.md)。
标签:C++, DOS, UML, URL提取, 云资产清单, 反编译, 客户端加密, 数据擦除, 游戏引擎, 软件遗产, 逆向工程