mattcurrie/mgbdis
GitHub: mattcurrie/mgbdis
一款将 Game Boy ROM 反汇编为 RGBDS 兼容汇编代码的工具,支持通过符号文件精确标注代码、数据和图像块。
Stars: 317 | Forks: 45
# mgbdis
一个 Game Boy ROM 反汇编器。
## 功能
- 生成兼容 RGBDS 的汇编代码
- 支持多 bank 的 ROM
- 支持 .sym 文件来定义标签、代码、数据、文本和图像块
- 输出用于重新构建 ROM 的 makefile
- 使用 hardware.inc 中的定义来表示硬件寄存器([来源](https://github.com/gbdev/hardware.inc))
- 处理大型 ROM 时速度较慢
## 环境要求
需要 Python v3.6 或更高版本。
mgbdis 生成的汇编文件旨在使用 [RGBDS](https://rgbds.gbdev.io) v0.8.0 或更高版本进行汇编。
## 用法
反汇编一个 ROM:
```
./mgbdis.py some-game.gb
```
默认输出目录是 ```disassembly```。你可以通过运行 ```make``` 来验证反汇编的结果,然后检查生成的 ```game.gb```(或 ```game.gbc```)文件:
```
cd disassembly && make
```
还有许多可用的选项可以控制生成汇编代码的格式和指令风格。你可以通过运行以下命令来查看它们:
```
./mgbdis.py -h
```
## 符号文件
符号文件允许你标明 ROM 中代码、数据、文本和图像数据块的位置。
Game Boy CPU (SM83) 的指令具有不同的长度,并且数据可以与代码在 ROM 中交替排列,因此并不总是能够准确识别指令的开始和结束位置。在符号文件中定义代码块有助于避免 mgbdis 在指令中间尝试反汇编而引发的问题。
如果你没有符号文件,可以尝试使用我的 Game Boy 模拟器 —— [Beaten Dying Moon](https://mattcurrie.com/bdm/) 来生成一个。你可以使用 Web 演示版,或者使用提供的 Windows 和 macOS 版本。它可以根据你在游戏过程中实际执行过的指令地址生成一个包含代码块定义的符号文件,从而避免指令对齐问题。
要在 mgbdis 中使用符号文件,它应该与 ROM 位于同一目录下且同名,只需将扩展名改为 ```.sym``` 即可。
所有值(除了图像宽度外)都应采用十六进制。条目以 bank 编号开头,后跟内存地址。
可以通过使用 ```.code```、```.data```、```.text```、```.padding``` 和 ```.image``` 魔法标签,后跟以字节为单位的块长度,来定义块类型。
### 代码
为一段代码添加标签:
```
03:47f2 Read_Joypad_State
```
### 数据
为 512 字节的数据添加标签:
```
0d:4800 Level_Data
0d:4800 .data:200
```
为 48 字节的数据添加标签,每行 3 字节:
```
0d:4900 Level_Pointers
0d:4900 .data:30:3
```
### 文本
为 16 字节的文本添加标签:
```
00:3d00 Character_Name
00:3d00 .text:10
```
### 填充
为 256 字节的填充添加标签:
```
0d:3e00 .padding:100
```
#### 自定义字符映射
如果游戏不使用 ASCII 编码,使用一个或多个[字符映射](https://rgbds.gbdev.io/docs/v0.9.1/rgbasm.5#Character_maps)可能会很实用。
1. 需要让 mgbdis 知道这些 charmap;这可以通过使用 `--character-map-path` 传递一个路径来完成。
2. 然后,你可以通过使用 `cm` 或 `charmap` 后跟你想要使用的字符映射的索引或名称,将任何文本标签标记为使用这些字符映射之一,而不是默认的字符映射。
使用第一个字符映射为 16 字节的文本添加标签:
```
00:3d00 Character_Name
00:3d00 .text:10:charmap=0
```
### 图像
```.image``` 魔法标签允许你在 ROM 中定义每像素 1 位或 2 位的图块数据块。图像将作为 PNG 文件输出到反汇编目录的 ```/gfx``` 文件夹中,并由 makefile 使用 rgbgfx 转换回 1bpp 或 2bpp 的图块数据。如果在图像块的地址处指定了标签,它将被用作 PNG 文件的名称。
以字节为单位的块长度应该是 16 的倍数,因为每个图块需要 16 字节的图像数据。
图像宽度(以像素为单位)可以指定为以 ```w``` 为前缀的十进制数字。宽度值应该是 8 的倍数,并且块长度和图像宽度的组合必须能够生成一个没有任何空图块的矩形图像。默认的图像宽度是 ```128``` 像素,或者如果块长度表示图块数为奇数,则会生成一个只有单行图块的图像。
调色板是一个字节大小的值,用于选择生成图像时要使用的灰度。它使用与位于 ```0xFF47``` 的 BGP 寄存器相同的格式。该值可以指定为以 ```p``` 为前缀的十六进制数。默认调色板为 ```E4```。
默认情况下,会将其视为每像素 2 位的图块数据。可以提供 ```1bpp``` 选项以将数据视为每像素 1 位的图块数据。
为 1280 字节的图块数据添加标签,宽度为 128 像素,调色板为 0xE4:
```
02:791a Title_Screen_Tile_Data
02:791a .image:500:w128,pe4
```
生成的图像:

1bpp 图块数据的示例:
```
05:4000 Font
05:4000 .image:200:w128,1bpp
```
生成的图像:

## 注意事项
- RGBDS 会自动在 ```STOP``` 之后添加 ```NOP``` 指令,因此如果原始 ROM 中的该指令后面没有跟着 ```NOP```,反汇编器会将此指令作为数据字节输出。
标签:Game Boy, Python, RGBDS, Wayback Machine, 云资产清单, 反汇编, 安全报告生成, 嵌入式, 无后门, 逆向工具, 逆向工程