fuzziqersoftware/resource_dasm
GitHub: fuzziqersoftware/resource_dasm
一款面向经典 Mac OS 与 GameCube 的资源逆向与反汇编工具链,用于恢复、解析与调试遗留二进制资源。
Stars: 139 | Forks: 18
# resource_dasm
该项目包含多个用于逆向工程应用程序和游戏的工具。其中大多数工具针对经典 Mac OS(OSX 之前);少数针对任天堂 GameCube 游戏。
该项目中的工具包括:
* 通用工具
* **resource_dasm**:用于处理经典 Mac OS 资源库的工具。它可以从经典 Mac OS 资源库、AppleSingle/AppleDouble 文件、MacBinary 文件、Mohawk 归档文件或 HIRF/RMF/IREZ/HSB 归档文件中读取资源,并将资源转换为现代格式或按原样导出。它还可以创建和修改资源库。
* **libresource_file**:实现 resource_dasm 大部分功能的库。
* **m68kdasm**:68K、PowerPC、x86 和 SH-4 二进制汇编器和反汇编器。m68kdasm 也可以反汇编某些常见的可执行文件格式。
* **m68kexec**:68K、PowerPC、x86 和 SH-4 CPU 模拟器和调试器。
* **render_bits**:以多种颜色格式(包括索引格式)渲染原始数据。适用于查找嵌入式图像或理解未知文件格式中的二维数组。
* **replace_clut**:将现有图像从一种索引颜色空间重新映射到另一种。
* **assemble_images**:将多个图像合并为一个。适用于处理因格式限制将大图像拆分为多个小图像的游戏。
* **dupe_finder**:在多个资源文件中查找重复的资源。
* 特定格式的工具
* **render_text**:使用 FONT 或 NFNT 资源中的位图字体渲染文本。
* **hypercard_dasm**:反汇编 HyperCard 堆栈并绘制卡片图像。
* **decode_data**:解码某些自定义压缩格式(详见下文)。
* **macbinary_decode**:解码 MacBinary 文件。
* **render_sprite**:以多种自定义格式渲染精灵(详见下文)。
* **icon_unarchiver**:将图标归档文件中的图标导出为 .icns(详见下文)。
* **vrfsdump**:提取 Blobbo 中的 VRFS 归档内容。
* **gcmdump**:提取 GCM 文件(GameCube 磁盘镜像)或 TGC 文件(嵌入式 GameCube 磁盘镜像)中的所有文件。
* **gcmasm**:从目录树生成 GCM 图像。
* **gvmdump**:提取 GVM 归档(来自 Phantasy Star Online)中的所有文件到当前目录,并将 GVR 纹理转换为 Windows BMP 文件。也可在 GVM 归档之外解码单个 GVR 文件。
* **rcfdump**:提取 RCF 归档(来自 The Simpsons: Hit and Run)中的所有文件到当前目录。
* **smsdumpbanks**:提取 AAF、BX 或 BAA 格式中的 JAudio 乐器与波形库(来自 Super Mario Sunshine、Luigi's Mansion、Pikmin 等游戏)。有关“使用 smssynth”的更多信息,请参见下文。
* **smssynth**:合成并调试 BMS 格式(来自 Super Mario Sunshine、Luigi's Mansion、Pikmin 等游戏)或 MIDI 格式(来自经典 Macintosh 游戏)的音乐序列。参见“使用 smssynth”了解更多信息。
* **modsynth**:合成并调试 Protracker/Soundtracker MOD 格式的音乐序列。
* 游戏地图生成器
* **blobbo_render**:从 Blobbo 关卡生成地图。
* **bugs_bannis_render**:从 Bugs Bannis 关卡生成地图。
* **ferazel_render**:从 Ferazel's Wand 世界文件生成地图。
* **gamma_zee_render**:生成 Gamma Zee 迷宫地图。
* **harry_render**:从 Harry the Handsome Executive 世界文件生成地图。
* **infotron_render**:从 Infotron 关卡文件生成地图。
* **lemmings_render**:从 Lemmings 和 Oh No! More Lemmings 关卡及图形文件生成地图。
* **mshines_render**:从 Monkey Shines 世界文件生成地图。
* **realmz_dasm**:生成 Realmz 场景并反汇编场景脚本为可读的类似汇编的语法。
## 构建
* 安装所需依赖项:
* 如果尚未安装 zlib,请安装它。(macOS 和大多数 Linux 系统已预装,但某些 Linux 系统如 Raspbian 可能没有。如果系统没有,可以执行 `apt-get install zlib1g-dev`。)
* 安装 CMake。
* 构建并安装 phosg(https://github.com/fuzziqersoftware/phosg)。
* 安装可选依赖项:
* 安装 Netpbm(http://netpbm.sourceforge.net/)。仅在 resource_dasm 无法自行解码 PICT 资源时才需要——如果您不关心 PICT,可以跳过此步骤。这仅为运行时依赖项;如果发现需要,可以在之后安装而无需重新编译 resource_dasm。
* 安装 SDL3。仅在需要 modsynth 和 smssynth 实时播放音乐时需要;没有 SDL,它们仍可构建并生成 WAV 文件。
* 运行 `cmake .`,然后运行 `make`。
* 如果构建其他依赖 resource_dasm 的项目,请运行 `sudo make install`。
该项目应在较新版本的 macOS 和 Linux 上正确构建。
## 使用 resource_dasm
resource_dasm 是经典 Mac OS 资源库的反汇编器。它从任意文件的资源库中提取资源,并将许多经典 Mac OS 资源格式(图像、声音、文本等)转换为现代格式。
**示例:**
* 从特定文件导出所有资源并转换为现代格式(默认输出到 `.out` 目录):`./resource_dasm files/Tesserae`
* 导出文件夹中所有文件的资源,在当前目录中生成平行文件夹结构:`./resource_dasm "files/Apeiron ƒ/" ./apeiron.out`
* 从特定文件导出特定资源,保留现代格式与原始格式:`./resource_dasm "files/MacSki 1.7/MacSki Sounds" ./macski.out --target-type=snd --target-id=1023 --save-raw=yes`
* 导出 PowerPC 应用程序的资源并反汇编其代码:`./resource_dasm "files/Adventures of Billy" ./billy.out && ./m68kdasm "files/Adventures of Billy" ./billy.out/dasm.txt`
* 导出 Mohawk 归档中的所有资源:`./resource_dasm files/Riven/Data/a_Data.MHK ./riven_data_a.out --index-format=mohawk`
* 由于文件系统差异,文件的资源库可能存在于独立数据库中。要导出此类文件的资源:`./resource_dasm "windows/Realmz/Data Files/Portraits.rsf" ./portraits.out --data-fork`
* 创建包含 TEXT 和 clut 资源的新资源文件:`./resource_dasm --create --add-resource=TEXT:128@file128.txt --add-resource=TEXT:129@file129.txt --add-resource=clut:2000@clut.bin output.rsrc`
* 向现有资源文件添加资源:`./resource_dasm file.rsrc --add-resource=TEXT:128@file128.txt output.rsrc`
* 从现有资源文件删除资源:`./resource_dasm file.rsrc --delete-resource=TEXT:128 output.rsrc`
这并非 resource_dasm 的全部功能。运行不带参数(或查看 `print_usage()` in src/resource_dasm.cc)可获取所有选项的完整说明。
### 功能
resource_dasm 可以转换以下资源类型:
```
Type | Output format | Notes
------------------------------------------------------------------------
Text resources
bstr | .txt (one file per string) | *3
card | .txt |
finf | .txt (description of contents) |
FCMT | .txt | *3
FONT | .txt (description) and image (one image per glyph) | *E
lstr | .txt | *3
MACS | .txt | *3
minf | .txt | *3
mstr | .txt | *3
mst# | .txt (one file per string) | *3
NFNT | .txt (description) and image (one image per glyph) | *E
PSAP | .txt |
sfnt | .ttf (TrueType font) |
STR | .txt | *3
STR# | .txt (one file per string) | *3
styl | .rtf | *4
TEXT | .txt | *3
TwCS | .txt (one file per string) |
wstr | .txt |
------------------------------------------------------------------------
Image and color resources
actb | image (24-bit) | *E *8
acur | .txt (list of cursor frame IDs) |
cctb | image (24-bit) | *E *8
cicn | image (32-bit and monochrome) | *E
clut | image (24-bit) | *E *8
crsr | image (32-bit and monochrome) | *E *1
CTBL | image (24-bit) | *E
CURS | image (32-bit) | *E *1
dctb | image (24-bit) | *E *8
fctb | image (24-bit) | *E *8
icl4 | image (24 or 32-bit) and .icns | *E *0
icl8 | image (24 or 32-bit) and .icns | *E *0
icm# | image (32-bit) | *E
icm4 | image (24 or 32-bit) | *E *0
icm8 | image (24 or 32-bit) | *E *0
ICN# | image (32-bit) and .icns | *E
icns | image, .png, .jp2, .txt, .plist, .bin, etc. | *E *9
ICON | image (24-bit) | *E
ics# | image (32-bit) and .icns | *E
ics4 | image (24 or 32-bit) and .icns | *E *0
ics8 | image (24 or 32-bit) and .icns | *E *0
kcs# | image (32-bit) | *E
kcs4 | image (24 or 32-bit) | *E *0
kcs8 | image (24 or 32-bit) | *E *0
PAT | image (24-bit; pattern and 8x8 tiling) | *E
PAT# | image (24-bit; pattern and 8x8 tiling for each pattern) | *E
PICT | image (24-bit) or other format | *E *2
pltt | image (24-bit) | *E *8
ppat | image (24-bit; color, color 8x8, mono, mono 8x8) | *E
ppt# | image (24-bit; 4 images as above for each pattern) | *E
SICN | image (24-bit, one per icon) | *E
wctb | image (24-bit) | *E *8
------------------------------------------------------------------------
Sound and sequence resources
.mod | .mod (ProTracker module) |
ALIS | .txt (description of contents) |
cmid | .midi |
csnd | .wav or .mp3 | *5
ecmi | .midi |
emid | .midi |
esnd | .wav or .mp3 | *5
ESnd | .wav or .mp3 | *5
INST | .json | *6
MADH | .madh (PlayerPRO module) |
MADI | .madi (PlayerPRO module) |
MIDI | .midi |
Midi | .midi |
midi | .midi |
SMSD | .wav | *A
snd | .wav or .mp3 | *5
SONG | .json (smssynth) | *6
SOUN | .wav | *A
Tune | .midi | *7
Ysnd | .wav |
------------------------------------------------------------------------
Code resources
ADBS | .txt (68K assembly) | *C
adio | .txt (68K assembly) | *C
AINI | .txt (68K assembly) | *C
atlk | .txt (68K assembly) | *C
boot | .txt (68K assembly) | *C
CDEF | .txt (68K assembly) | *C
cdek | .txt (PPC32 assembly and header description) |
cdev | .txt (68K assembly) | *C
CDRV | .txt (68K assembly) | *C
cfrg | .txt (description of code fragments) | *D
citt | .txt (68K assembly) | *C
clok | .txt (68K assembly) | *C
cmtb | .txt (68K assembly) | *C
cmu! | .txt (68K assembly) | *C
CODE | .txt (68K assembly or import table description) | *B *C
code | .txt (68K assembly) | *C
dcmp | .txt (68K assembly) | *C
dcod | .txt (PPC32 assembly and header description) |
dem | .txt (68K assembly) | *C
dimg | .txt (68K assembly) | *C
drvr | .txt (68K assembly) | *C
DRVR | .txt (68K assembly) | *C
enet | .txt (68K assembly) | *C
epch | .txt (PPC32 assembly) |
expt | .txt (PPC32 assembly) |
FKEY | .txt (68K assembly) | *C
fovr | .txt (PPC32 assembly and header description) |
gcko | .txt (68K assembly) | *C
gdef | .txt (68K assembly) | *C
GDEF | .txt (68K assembly) | *C
gnld | .txt (68K assembly) | *C
INIT | .txt (68K assembly) | *C
krnl | .txt (PPC32 assembly) |
LDEF | .txt (68K assembly) | *C
lmgr | .txt (68K assembly) | *C
lodr | .txt (68K assembly) | *C
ltlk | .txt (68K assembly) | *C
MBDF | .txt (68K assembly) | *C
MDEF | .txt (68K assembly) | *C
mntr | .txt (68K assembly) | *C
ncmp | .txt (PPC32 assembly and header description) |
ndlc | .txt (PPC32 assembly and header description) |
ndmc | .txt (PPC32 assembly and header description) |
ndrv | .txt (PPC32 assembly and header description) |
nift | .txt (PPC32 assembly and header description) |
nitt | .txt (PPC32 assembly and header description) |
nlib | .txt (PPC32 assembly and header description) |
nsnd | .txt (PPC32 assembly and header description) |
nsrd | .txt (PPC32 assembly) |
ntrb | .txt (PPC32 assembly and header description) |
osl | .txt (68K assembly) | *C
otdr | .txt (68K assembly) | *C
otlm | .txt (68K assembly) | *C
PACK | .txt (68K assembly) | *C
pnll | .txt (68K assembly) | *C
ppct | .txt (PPC32 assembly and header description) |
proc | .txt (68K assembly) | *C
PTCH | .txt (68K assembly) | *C
ptch | .txt (68K assembly) | *C
pthg | .txt (68K or PPC32 assembly and header description) | *C
qtcm | .txt (PPC32 assembly and header description) |
ROvr | .txt (68K assembly) | *C
RSSC | .txt (68K assembly) | *C
scal | .txt (PPC32 assembly and header description) |
scod | .txt (68K assembly) | *C
SERD | .txt (68K assembly) | *C
sfvr | .txt (PPC32 assembly and header description) |
shal | .txt (68K assembly) | *C
sift | .txt (68K assembly) | *C
SMOD | .txt (68K assembly) | *C
snth | .txt (68K assembly) | *C
tdig | .txt (68K assembly) | *C
tokn | .txt (68K assembly) | *C
vdig | .txt (68K or PPC32 assembly and header description) | *C
wart | .txt (68K assembly) | *C
WDEF | .txt (68K assembly) | *C
XCMD | .txt (68K assembly) | *C
XFCN | .txt (68K assembly) | *C
------------------------------------------------------------------------
MacApp resources
68k! | .txt (description of memory config for 680x0) |
CMNU | .txt (description of menu) |
cmnu | .txt (description of menu) |
errs | .txt (description of error ranges) |
mem! | .txt (description of memory config) |
ppc! | .txt (description of memory config for PPC) |
res! | .txt (string list of always resident segments) |
seg! | .txt (string list of segments) |
TxSt | .txt (description of text style) |
------------------------------------------------------------------------
Miscellaneous resources
ALRT | .txt (alert parameters) |
APPL | .txt (description of contents) |
audt | .txt (description of contents) |
BNDL | .txt (description of contents) |
CMDK | .txt (list of keys) |
CNTL | .txt (description of control) |
CTY# | .txt (description of cities) |
dbex | .txt (description of contents) |
DITL | .txt (dialog parameters) |
DLOG | .txt (dialog parameters) |
FBTN | .txt (description of buttons) |
FDIR | .txt (description of contents) |
fld# | .txt (description of folders) |
flst | .txt (description of font family list) |
fmap | .txt (description of finder icon mappings) |
FREF | .txt (description of file references) |
FRSV | .txt (list of font IDs) |
FWID | .txt (font parameters) |
gbly | .txt (description of Gibbly aka. System Enabler) |
GNRL | .txt (description of contents) |
hwin | .txt (description of help window) |
icmt | .txt (icon reference and comment) |
inbb | .txt (description of contents) |
indm | .txt (description of contents) |
infs | .txt (description of contents) |
inpk | .txt (description of contents) |
inra | .txt (description of contents) |
insc | .txt (description of contents) |
itl0 | .txt (international formatting information) |
ITL1 | .txt (short dates flag value) |
itlb | .txt (internationalization parameters) |
itlc | .txt (internationalization parameters) |
itlk | .txt (keyboard mappings) |
KBDN | .txt (keyboard name) |
LAYO | .txt (description of layout) |
mach | .txt (description of contents) |
MBAR | .txt (list of menu IDs) |
mcky | .txt (threshold values) |
MENU | .txt (description of menu) |
mitq | .txt (description of queue sizes) |
nrct | .txt (rectangle boundaries) |
PAPA | .txt (printer parameters) |
PICK | .txt (picker parameters) |
ppcc | .txt (description of contents) |
ppci | .txt (description of contents) |
PRC0 | .txt (description of contents) |
PRC3 | .txt (description of contents) |
pslt | .txt (description of Nubus pseudo-slot lists) |
ptbl | .txt (description of patch table) |
qrsc | .txt (description of queries) |
RECT | .txt (description of the rectangle) |
resf | .txt (list of fonts) |
RMAP | .txt (type mapping and list of ID exceptions) |
ROv# | .txt (list of overridden resource IDs) |
rtt# | .txt (list of database result handlers) |
RVEW | .txt (description of contents) |
scrn | .txt (screen device parameters) |
sect | .txt (description of contents) |
SIGN | .txt (description of contents) |
SIZE | .txt (description of parameters) |
slut | .txt (description of mapping) |
thn# | .txt (description of 'thng' mapping) |
TMPL | .txt (description of format) |
TOOL | .txt (description of contents) |
vers | .txt (version flags and strings) |
WIND | .txt (window parameters) |
Notes:
*0: Produces a 32-bit image if a corresponding monochrome resource exists
(ICN# for icl4/8, icm# for icm4/8, ics# for ics4/8, kcs# for kcs4/8). If
no monochrome resource exists, produces a 24-bit image instead. All
color information in the original resource is reproduced in the output,
even for fully-transparent pixels. If the icon was originally intended
to be used with a nonstandard compositing mode, the colors of fully-
transparent pixels may have been relevant, but most modern image viewers
and editors don't have a way to display this information.
*1: The hotspot coordinates are appended to the output filename. As in *0,
resource_dasm faithfully reproduces the color values of transparent
pixels in the output file, but most modern image editors won't show
these "transparent" pixels.
*2: resource_dasm implements multiple PICT decoders. It will first attempt
to decode the PICT using its internal decoder, which usually produces
correct results but fails on PICTs that contain complex drawing opcodes.
This decoder can handle basic QuickTime images as well (e.g. embedded
JPEGs and PNGs), but can't do any drawing under or over them, or
matte/mask effects. PICTs that contain embedded JPEGs or PNGs will
result in a JPEG or PNG file rather than the format specified by
--image-format (which is BMP by default). If the internal decoder fails,
resource_dasm will fall back to a decoder that uses picttoppm, which is
part of NetPBM. There is a rare failure mode in which picttoppm hangs
forever; resource_dasm gives it 10 seconds to do its job before killing
it and giving up. If picttoppm is not installed, fails to decode the
PICT, or is killed due to a timeout, resource_dasm will prepend the
necessary header and save the data as a PICT file instead.
*3: Text is assumed to use the Mac OS Roman encoding. It is converted to
UTF-8, and line endings (\r) are converted to Unix style (\n).
*4: Some rare style options may not be translated correctly. styl resources
provide styling information for the TEXT resource with the same ID, so
such a resource must be present to properly decode a styl.
*5: RMF archives can contain snd resources that are actually in MP3 format;
in this case, the exported sound will be a .mp3 file. Otherwise, the
exported sound is an uncompressed WAV file, even if the resource's data
is compressed. resource_dasm can decompress IMA 4:1, MACE 3:1, MACE 6:1,
A-law, and mu-law (ulaw) compression.
*6: JSON files from SoundMusicSys SONG resources can be played with smssynth
(http://www.github.com/fuzziqersoftware/gctools). The JSON file refers
to the instrument sounds and MIDI sequence by filename and does not
include directory names, so if you want to play these, you'll have to
manually put the sounds and MIDI files in the same directory as the JSON
file if you're using --filename-format.
*7: Tune decoding is experimental and will likely produce unplayable MIDIs.
*8: For color table resources, the raw data is always saved even if it is
decoded properly, since the original data contains 16-bit values for
each channel and the output image file has less-precise 8-bit channels.
*9: icns resources are decoded into many different file types depending on
the contents of the resource. For subfields that have split alpha
channels (that is, the transparency data is in a different subfield),
resource_dasm produces an original image and one with transparency
applied. Some icns resources also contain metadata, which is exported as
.bin, .txt, and .plist files, except for the Icon Composer version used
to create the file, which is ignored. If you want the result in Icon
Composer format, use --save-raw=yes and resource_dasm will save it as a
.icns file.
*A: These resources appear to have a fixed format, with a constant sample
rate, sample width and channel count. You may have to adjust these
parameters in the output if it turns out that these are configurable.
*B: The disassembler attempts to find exported functions by parsing the jump
table in the CODE 0 resource, but if this resource is missing or not in
the expected format, it skips this step and does not fail. Generally, if
any "export_X:" labels appear in the disassembly, then export resolution
succeeded and all of the labels should be correct (otherwise they will
all be missing).
*C: Some coprocessor and floating-point opcodes (F-class) are not
implemented and will disassemble with the comment "// unimplemented".
*D: Most PowerPC applications have their executable code in the data fork.
To disassemble it, use m68kdasm (example above).
*E: The output image format can be specified using --image-format. The
default output format is bmp (Windows bitmap); other supported formats
are png and ppm.
```
如果 resource_dasm 无法转换某资源,或不认识该类型,它会尝试使用对应的 TMPL(模板)资源进行解码。若无合适 TMPL、TMPL 损坏或无法解码,resource_dasm 将输出资源的原始数据。
大多数解码器实现基于对现有软件的逆向工程和对旧文档的梳理,因此部分稀有资源类型可能尚不支持。但本项目力求尽可能完整,如果您有认为应可解码但目前无法解码的资源,请发送给我(可通过 GitHub issue 附加文件),我会尽力使其支持。
#### 压缩资源
resource_dasm 会透明解压被资源管理器标记为压缩的资源。
资源管理器的压缩方案从未被 Apple 正式文档化或公开,因此这些解压器的实现基于对 ResEdit 及其他经典 Mac OS 代码的逆向工程。总体而言,资源通过执行 68K 或 PowerPC 代码从 dcmp 或 ncmp 资源中解压,这些资源会在运行时从打开的资源文件链中查找(通常与压缩资源位于同一文件或 System 文件中)。实际中,相关的 dcmp/ncmp 通常包含在源文件本身或 System 文件中。存在两种压缩资源格式,对应两种 6K 解压缩器格式;resource_dasm 支持两者。
resource_dasm 内置了四种 Mac OS System 文件的原生解压器实现:
* dcmp 0(DonnDecompress)可用
* dcmp 1(DonnDecompress 变体)未测试
* dcmp 2(GreggyDecompress)未测试
* dcmp 3(类似 LZSS 的方案)可用
resource_dasm 包含用于运行非默认解压器的 68K 与 PowerPC 模拟器。这些模拟器也可运行默认解压器(已内置)。当前已测试的解压器状态如下:
* System dcmp 0 可用
* System dcmp 1 未测试
* System dcmp 2 未测试
* System dcmp 3 可用
* Ben Mickaelian 的 After Dark 自修改 dcmp 128 可用
* FutureBASIC(可能)dcmp 200 可用
可能还有其他未见过的解压器无法工作。若使用 resource_dasm 时出现“warning: failed to decompress resource”警告,请在 GitHub 上创建 issue 并上传导致失败的导出压缩资源(.bin 文件)以及同一源文件中的所有 dcmp 和 ncmp 资源。
### 作为库使用
运行 `sudo make install` 可将头文件与库复制到相应路径。安装后,可包含 ``(例如)并链接 `-lresource_file`。该库无文档说明,详见头文件内容。
该库包含以下有用的函数与类:
* AudioCodecs.hh:MACE3/6、IMA4、mu-law 和 A-law 音频解码器
* DataCodecs/Codecs.hh:部分通用与自定义数据格式的解压器与压缩器
* Emulators/M68KEmulator.hh:68000 CPU 模拟器与反汇编器
* Emulators/PPC32Emulator.hh:PowerPC CPU 模拟器、汇编器与反汇编器
* Emulators/SH4Emulator.hh:SuperH-4 汇编器与反汇编器(尚未实现模拟器)
* Emulators/X86Emulator.hh:x86 CPU 模拟器、汇编器与反汇编器
* ExecutableFormats/...:多种可执行文件格式的解析器
* IndexFormats/Formats.hh:多种资源归档格式的解析器与序列化器
* Lookups.hh:多种资源类型中使用的常量值索引
* LowMemoryGlobals.hh:经典 Mac OS 低内存全局变量的结构定义与字段查找
* ResourceDecompressors/System.hh:标准资源压缩格式的解压器
* ResourceFile.hh:资源归档的加载表示,包含多种类型的解码函数
* ResourceTypes.hh:表示常见资源类型的常量
* TextCodecs.hh:Mac OS Roman 解码器
* TrapInfo.hh:经典 Mac OS 68K 系统调用索引
## 使用 m68kdasm
使用 m68kdasm 非常直接。运行 `m68kdasm --help` 可查看完整选项列表。
目前 m68kdasm 可反汇编以下类型的数据:
* 原始 68K、PowerPC、x86 或 SH-4 二进制代码
* PEF(经典 Mac OS PowerPC 可执行文件)
* DOL(Nintendo GameCube 可执行文件)
* REL(Nintendo GameCube 库)
* PE(Windows EXE/DLL 等)
* XBE(Microsoft Xbox 可执行文件)
* ELF 文件
其中部分可执行文件格式支持 m68kdasm 不支持的 CPU 架构;遇到此类情况时,代码段会以数据段形式输出。
m68kdasm 也可将 PowerPC、x86 和 SH-4 汇编代码汇编为原始二进制。(不支持将 M68K 文本汇编为二进制,未来计划支持。)每种架构的输入语法与反汇编语法一致;对于 PowerPC 和 SH-4,并非标准语法,而是与大多数其他工具不同。
## 使用 m68kexec
m68kexec 是针对 Motorola 68000、32 位 PowerPC 和 x86 架构的 CPU 模拟器与调试器。我常用于理解老旧代码的行为,或将用现代语言转写的代码与原始代码的行为进行比较。此类用途通常需要设置一个或多个输入区域(包含测试数据)和一个或多个输出区域(供模拟代码写入)。
或许通过示例最能说明问题。以下命令用于执行 Phantasy Star Online Blue Burst 中的加密上下文生成函数,并与 [newserv](https://github.com/fuzziqersoftware/newserv/blob/342f819f50cbde25816c1cd7f72c5ec0f3369994/src/PSOEncryption.cc#L288) 中的实现进行比较:
```
./m68kexec --x86 --trace \
--mem=A0000000/2AC43585C46A6366188889BCE3DB88B15C2B3C751DB6757147E7E9390598275CC79547B2E5C00DD145002816B59C067C \
--mem=A1000000:1048 \
--load-pe=files/windows/pso/psobb.exe \
--pc=00763FD0 \
--reg=ecx:A1000000 \
--push=00000030 \
--push=A0000000 \
--push=FFFFFFFF \
--breakpoint=FFFFFFFF
```
`--mem` 选项用于设置输入区域;A0000000 区域包含加密种子(30 字节),A1000000 区域将保存函数返回后的生成上下文。`--load-pe` 选项加载待执行代码,`--pc` 指定模拟器启动地址(默认从入口点开始,此处我们希望调用特定函数)。`--reg` 选项将函数中的 `this` 指针设为我们分配的内存空间。`--push` 选项设置函数参数与返回地址。返回地址设为 FFFFFFFF(未分配内存),但我们设置了 `--breakpoint` 在该地址触发,在异常抛出前停止模拟。
由于使用了 `--trace`,模拟器会在每条指令后打印寄存器状态,便于逐步跟踪并与外部实现对比。函数返回触发断点后,可通过 `r A1000000 1048` 查看生成的数据,也可与外部实现结果对比。
## 使用 smssynth
**smssynth** 处理 BMS 与 MIDI 音乐序列程序。它可反汇编、转换为 .wav 文件或实时播放。实现基于对多款游戏的逆向工程,未使用官方源码,因此输出与真实游戏音效可能存在差异。
### GameCube 与 Wii 游戏的使用
运行 smssynth 前,可能需要完成“获取辅助文件”部分步骤。对于循环序列,除非按下 Ctrl+C 或设置时间限制,否则 smssynth 会持续运行。
准备好文件后,可使用 `--list` 列出可用序列,`--play` 播放,或 `--output-filename` 生成 .wav 文件。
以下为 GameCube 游戏的一些使用示例:
- 列出 Luigi's Mansion 的所有序列:`smssynth --audiores-directory=luigis_mansion_extracted_data/AudioRes --list`
- 将 Super Mario Sunshine 的 Bianco Hills 转为 4 分钟 WAV(禁用 Yoshi 鼓):`smssynth --audiores-directory=sms_extracted_data/AudioRes k_bianco.com --disable-track=15 --output-filename=k_bianco.com.wav --time-limit=240`
- 实时播放 Bianco Hills:`smssynth --audiores-directory=sms_extracted_data/AudioRes k_bianco.com --play`
- 实时播放 Pikmin 的 The Forest Navel:`smssynth --audiores-directory=pikmin_extracted_data/dataDir/SndData --play cave.jam`
### Classic Mac OS 游戏的使用
smssynth 也可反汇编并播放使用 SoundMusicSys(miniBAE)的经典 Mac OS 游戏序列。需提供由 resource_dasm 从 SONG 资源生成的 JSON 环境文件,且不要移动或重命名该目录下的其他文件(JSON 文件通过文件名引用采样)。可通过以下命令生成 JSON 文件:
`resource_dasm "Creep Night Demo Music" ./creep_night.out`
之后可播放(如):
`smssynth --json-environment="./creep_night.out/Creep Night Demo Music_SONG_1000_smssynth_env.json" --play`
`--disassemble` 与 `--output-filename` 在使用 JSON 文件时也有效,但 `--list` 不适用。
### 兼容性
测试的 GameCube 游戏及其近似正确性如下:
- __Luigi's Mansion__:60%。多数歌曲接近原声,少数乐器错误且部分效果缺失,使职员滚动听起来更酷,但计划修复。
- __Mario Kart: Double Dash!!__:80%。所有歌曲可播放,部分音量效果缺失。
- __Pikmin__:70%。游戏使用轨道音量效果;smssynth 未实现,歌曲与原声略有差异但可识别。
- __Super Mario Sunshine__:95%。多数歌曲完美,仅少数损坏。注意使用 `--disable-track=15` 禁用 Yoshi 鼓。
- __The Legend of Zelda: Twilight Princess__:<20%。多数无法播放或音质差。
- __Super Mario Galaxy__:<20%。同上。
经典 Mac OS 游戏(使用 SoundMusicSys)表现更好:
- __After Dark__:100%
- __Castles - Siege and Conquest__:100%
- __ClockWer__:100%
- __Creep Night Pinball__:100%
- __DinoPark Tycoon__:100%
- __Flashback__:100%
- __Holiday Lemmings__:100%
- __Lemmings__:100%
- __Mario Teaches Typing__:100%
- __Monopoly CD-ROM__:100%,但与原声略有不同(原始实现会省略某些音符,smssynth 不会)。
- __Odell Down Under__:100%
- __Oh No! More Lemmings__:100%
- __Prince of Persia__:100%
- __Prince of Persia 2__:100%。无 SONG 资源;使用 `resource_dasm --index-format=mohawk` 从 NISMIDI.dat 和 MIDISnd.dat 提取 MIDI 文件,并提供生成的 JSON 环境文件。
- __SimAnt__:100%
- __SimCity 2000__:100%
- __SimTown (demo)__:100%。完整版可能包含更多歌曲(未测试)。
- __Snapdragon__:100%
- __The Amazon Trail__:100%
- __The Yukon Trail__:100%
- __Troggle Trouble Math__:100%
- __Ultimate Spin Doctor__:100%
- __Widget Workshop__:100%
### 从 GameCube 游戏获取辅助文件
Luigi's Mansion 可直接使用 `--audiores-directory` 指向解压后的目录。
#### 获取 Super Mario Sunshine 的 msound.aaf
需手动复制 msound.aaf 到 AudioRes 目录:
- 从光盘镜像提取 nintendo.szs(使用 gcmdump 等工具)
- 使用 yaz0dec([szstools](http://amnoid.de/gc/))解压
- 解压归档(使用 rarcdump,同样来自 [szstools](http://amnoid.de/gc/))
- 将 msound.aaf 复制到 AudioRes 目录
#### 获取 Pikmin 的 sequence.barc
需从 default.dol 手动提取 BARC 数据。使用十六进制编辑器查找 "BARC----",从此位置复制至少 0x400 字节并保存为 sequence.barc,放入 SndData/Seqs/ 目录。随后可使用 smsdumpbanks 和 smssynth,需将 `--audiores-directory` 指向包含 sequence.barc 的 SndData 目录。
#### 获取 Mario Kart: Double Dash 的 Banks 目录
解压 AudioRes 后,将 Waves 子目录重命名为 Banks。
#### 获取 The Legend of Zelda: Twilight Princess 的文件
序列存储在压缩的 RARC 文件中,未列在环境索引中(因此 `--list` 无效,需手动指定序列文件)。解压步骤:
- 使用 yaz0dec([szstools](http://amnoid.de/gc/))解压序列文件
- 使用 rarcdump([szstools](http://amnoid.de/gc/))提取序列
#### 获取 Super Mario Galaxy 的文件
与 Twilight Princess 类似,序列存储在 RARC 归档中,但每个序列单独压缩,索引也压缩。均为 Yaz0 格式:
- 使用 yaz0dec([szstools](http://amnoid.de/gc/))解压索引
- 使用 rarcdump([szstools](http://amnoid.de/gc/))提取序列
- 对每个序列再次使用 yaz0dec 解压
## 使用其他工具
### render_bits
render_bits 用于回答“这些随机二进制数据是否可能是图像或二维数组?”提供颜色格式和二进制数据后,会生成完整的彩色 BMP 文件供图像查看或编辑。若有颜色表(由 resource_dasm 从 clut 资源生成的 .bin 文件),也可提供。若输出异常,可尝试调整宽度和颜色格式。
运行 `render_bits` 无参数可查看用法。
### render_text
render_text 可预览使用位图字体(FONT/NFNT)渲染的实际文本。获取 FONT 或 NFNT 资源的 .bin 文件(例如通过 `resource_dasm --save-raw`),然后运行 `render_text` 查看使用方法。
### replace_clut
在逆向过程中,图像内容正确但颜色错误时,很可能使用了错误颜色表。可使用 replace_clut 将像素从一种颜色空间映射到另一种。
运行 `replace_clut` 无参数可查看用法。
### assemble_images
某些游戏将大图像拆分为多个小纹理,assemble_images 可程序化合并为单一图像。运行 `assemble_images` 无参数可查看用法。
### dupe_finder
dupe_finder 可在单个或多个资源文件中查找重复的同类型资源。
运行 `dupe_finder` 无参数可查看用法。
### 针对特定格式的解压器/解档器
* HyperCard 堆栈:`hypercard_dasm stack_file [output_dir]`,或仅运行 `hypercard_dasm` 查看所有选项
* Alessandro Levi Montalcini 的 Icon Archiver:`icon_dearchiver archive_file [output_dir]` 解压图标为 .icns
* VRFS 文件:`vrfs_dump VRFS_file [output_dir]`
### decode_data
decode_data 可解码并解压部分游戏使用的自定义编码格式。具体支持:
```
Game/App/Library | Encoding | CLI option | Notes
-------------------------------------------------------------
DinoPark Tycoon | LZSS | --dinopark | %0
DinoPark Tycoon | RLE | --dinopark |
Flashback | LZSS | --presage | %0
MacSki | COOK | --macski |
MacSki | CO2K | --macski |
MacSki | RUN4 | --macski |
PackBits (compress) | PackBits | --pack-bits |
PackBits (decompress) | PackBits | --unpack-bits |
Pathways Into Darkness | Pathways | --unpack-pathways |
SoundMusicSys | LZSS | --sms | %0
Notes:
%0: Although these are all variants of LZSS (and are indeed very similar to
each other), they are mutually incompatible formats.
```
decode_data 可单独用于解压数据,也可作为 resource_dasm 的外部预处理器以透明解压某些格式。例如,对 MacSki 资源可运行:
`resource_dasm --external-preprocessor="./decode_data --macski" input_filename ...`
### render_sprite
render_sprite 可渲染多种自定义游戏精灵格式。对部分格式,需额外提供颜色表资源(.bin 文件,由 resource_dasm 从 clut/pltt/CTBL 资源生成,通常位于同一文件或游戏应用中)。运行 `render_sprite` 无参数可查看用法。
支持格式:
```
Game | Type | CLI option | Need color table | Notes
---------------------------------------------------------------------------
Beyond Dark Castle | PBLK | --PBLK | No |
Beyond Dark Castle | PPCT | --PPCT | No |
Beyond Dark Castle | PSCR | --PSCR-v2 | No |
Blobbo | BTMP | --BTMP | No |
Blobbo | PMP8 | --PMP8 | Yes | $9
BodyScope | Imag | --Imag | Yes | $2 $3
Bonkheads | Sprt | --Sprt | Yes |
Bubble Trouble | btSP | --btSP | Yes |
Dark Castle (color) | DC2 | --DC2 | No | $4
Dark Castle (monochrome) | PPCT | --PPCT | No |
Dark Castle (monochrome) | PSCR | --PSCR-v1 | No |
DinoPark Tycoon | BMap | --BMap | No |
DinoPark Tycoon | XBig | --XBig | No | $2
DinoPark Tycoon | XMap | --XMap | Yes | $2 $7
Dr. Quandary | Imag | --Imag | Sometimes | $1 $2 $3
Factory | 1img | --1img | No |
Factory | 4img | --4img | Yes |
Factory | 8img | --8img | Yes |
Flashback | PPSS | --PPSS | Yes | $2 $8
Fraction Munchers | Imag | --Imag-fm | Sometimes | $1 $2 $3
Greebles | GSIF | --GSIF | Yes |
Harry the Handsome Executive | HrSp | --HrSp | Yes | $9
Lemmings | SHPD | --SHPD-v1 | Sometimes | $0 $1 $2 $5
Marathon | .256 | --.256-m | No | $2
Mario Teaches Typing | Pak | --Pak | Sometimes | $1 $2
Mars Rising | btSP | --btSP | Yes |
Number Munchers | Imag | --Imag-fm | Sometimes | $1 $2 $3
Odell Down Under | Imag | --Imag | Sometimes | $1 $2 $3
Oh No! More Lemmings | SHPD | --SHPD-v2 | Sometimes | $0 $1 $2 $5
Pathways Into Darkness | .256 | --.256-pd | No | $2
Prince of Persia | SHPD | --SHPD-p | Sometimes | $0 $1 $2 $5
Prince of Persia 2 | SHAP | --SHAP | Yes |
SimCity 2000 | SPRT | --SPRT | Yes | $2
SimTower | | | No | $A
Slithereens | SprD | --SprD | Yes | $2
SnapDragon | Imag | --Imag | Sometimes | $1 $2 $3
Spectre | shap | --shap | No | $6
Step On It! | sssf | --sssf | Yes | $2
Super Munchers | Imag | --Imag-fm | Sometimes | $1 $2 $3
Swamp Gas | PPic | --PPic | Sometimes | $0 $2 $3
The Amazon Trail | Imag | --Imag | Sometimes | $2 $3
The Oregon Trail | Imag | --Imag | Sometimes | $1 $2 $3
TheZone | Spri | --Spri | Yes |
Word Munchers | Imag | --Imag-fm | Sometimes | $1 $2 $3
Notes:
$0: render_sprite can't tell from the contents of the resource whether it is
color or monochrome, so it assumes the resource is color if you give a
color table on the command line. If decoding fails with a color table,
try decoding without one (or vice versa).
$1: These games contain some color and some monochrome graphics. It should
be obvious which are which (usually color graphics are in a separate
file), but if not, you can give a clut anyway in these cases and
render_sprite will ignore it if the image is monochrome.
$2: These sprite formats contain multiple images, so render_sprite will
produce multiple image files.
$3: Resources of this type can contain embedded color tables; if you're
rendering a color image that doesn't have a color table, you'll have to
provide one via a command-line option. If the resource (or individual
images therein) contain their own color tables or are monochrome, no
color table is required on the command line, and any provided color
table via the command line will be ignored.
$4: You can get DC2 sprites from the DC Data file with
`resource_dasm --index-format=dc-data "DC Data"`.
$5: The graphics files contain resources that refer to segments of the data
fork in the same file. So, this option expects the original Graphics or
BW Graphics or Persia file (with both data and resource forks present),
not an already-extracted resource.
$6: shap resources contain 3D models and 2D top-down projections of them.
When given a shap resource, render_sprite produces an STL file and an
OBJ file for the 3D model, and an SVG file for the 2D top-down view.
$7: Some XMap resources are stored inside CBag archives. You can extract
them with `resource_dasm --index-format=cbag `.
$8: This game has only one clut and it's huge - far longer than the usual
256 entries. It seems PPSS image sets are meant to be rendered with a
subset of this clut, but I haven't been able to figure out (yet) how the
game chooses what subset of it to use.
$9: The game doesn't contain any color tables. You can use a 256-color clut
resource from the Mac OS System file, or use the --default-clut option.
$A: The game stores its sprites in normal PICT resources with an incorrect
type. Use `resource_dasm --copy-handler=PICT:%89%E6%91%9C` to decode
them instead of using render_sprite.
```
### icon_dearchiver
icon_dearchiver 将 Icon Archiver(由 Alessandro Levi Montalcini 创建)归档中的图标解压为 .icns。运行无参数可查看用法。
### 游戏地图生成器
* Blobbo 地图:先用 resource_dasm 获取 PMP8 和 Blev 资源,再用 render_sprite 将 PMP8 128 转为 .bmp,最后运行 `blobbo_render `
* Ferazel's Wand 地图:`ferazel_render` 在数据文件目录中,或运行 `ferazel_render --help` 查看选项
* Gamma Zee 地图:`gamma_zee_render gamma_zee_application levels_filename`
* Harry the Handsome Executive 地图:`harry_render --clut-file=clut.bin` 或仅运行 `harry_render` 查看所有选项
* Infotron 地图:`infotron_render` 在 Info Datafiles 目录中
* Lemmings(Mac 版)地图:`lemmings_render --clut-file=clut.bin` 或运行 `lemmings_render --help` 查看选项
* Monkey Shines 地图:`mshines_render world_file [output_directory]`
* Oh No! More Lemmings(Mac 版)地图:使用 `lemmings_render`,并添加 `--v2` 选项
* Realmz 地图与脚本:`realmz_dasm global_data_dir [scenario_dir] out_dir`(若未提供 scenario_dir,则反汇编共享数据)
该项目包含多个用于逆向工程应用程序和游戏的工具。其中大多数工具针对经典 Mac OS(OSX 之前);少数针对任天堂 GameCube 游戏。
该项目中的工具包括:
* 通用工具
* **resource_dasm**:用于处理经典 Mac OS 资源库的工具。它可以从经典 Mac OS 资源库、AppleSingle/AppleDouble 文件、MacBinary 文件、Mohawk 归档文件或 HIRF/RMF/IREZ/HSB 归档文件中读取资源,并将资源转换为现代格式或按原样导出。它还可以创建和修改资源库。
* **libresource_file**:实现 resource_dasm 大部分功能的库。
* **m68kdasm**:68K、PowerPC、x86 和 SH-4 二进制汇编器和反汇编器。m68kdasm 也可以反汇编某些常见的可执行文件格式。
* **m68kexec**:68K、PowerPC、x86 和 SH-4 CPU 模拟器和调试器。
* **render_bits**:以多种颜色格式(包括索引格式)渲染原始数据。适用于查找嵌入式图像或理解未知文件格式中的二维数组。
* **replace_clut**:将现有图像从一种索引颜色空间重新映射到另一种。
* **assemble_images**:将多个图像合并为一个。适用于处理因格式限制将大图像拆分为多个小图像的游戏。
* **dupe_finder**:在多个资源文件中查找重复的资源。
* 特定格式的工具
* **render_text**:使用 FONT 或 NFNT 资源中的位图字体渲染文本。
* **hypercard_dasm**:反汇编 HyperCard 堆栈并绘制卡片图像。
* **decode_data**:解码某些自定义压缩格式(详见下文)。
* **macbinary_decode**:解码 MacBinary 文件。
* **render_sprite**:以多种自定义格式渲染精灵(详见下文)。
* **icon_unarchiver**:将图标归档文件中的图标导出为 .icns(详见下文)。
* **vrfsdump**:提取 Blobbo 中的 VRFS 归档内容。
* **gcmdump**:提取 GCM 文件(GameCube 磁盘镜像)或 TGC 文件(嵌入式 GameCube 磁盘镜像)中的所有文件。
* **gcmasm**:从目录树生成 GCM 图像。
* **gvmdump**:提取 GVM 归档(来自 Phantasy Star Online)中的所有文件到当前目录,并将 GVR 纹理转换为 Windows BMP 文件。也可在 GVM 归档之外解码单个 GVR 文件。
* **rcfdump**:提取 RCF 归档(来自 The Simpsons: Hit and Run)中的所有文件到当前目录。
* **smsdumpbanks**:提取 AAF、BX 或 BAA 格式中的 JAudio 乐器与波形库(来自 Super Mario Sunshine、Luigi's Mansion、Pikmin 等游戏)。有关“使用 smssynth”的更多信息,请参见下文。
* **smssynth**:合成并调试 BMS 格式(来自 Super Mario Sunshine、Luigi's Mansion、Pikmin 等游戏)或 MIDI 格式(来自经典 Macintosh 游戏)的音乐序列。参见“使用 smssynth”了解更多信息。
* **modsynth**:合成并调试 Protracker/Soundtracker MOD 格式的音乐序列。
* 游戏地图生成器
* **blobbo_render**:从 Blobbo 关卡生成地图。
* **bugs_bannis_render**:从 Bugs Bannis 关卡生成地图。
* **ferazel_render**:从 Ferazel's Wand 世界文件生成地图。
* **gamma_zee_render**:生成 Gamma Zee 迷宫地图。
* **harry_render**:从 Harry the Handsome Executive 世界文件生成地图。
* **infotron_render**:从 Infotron 关卡文件生成地图。
* **lemmings_render**:从 Lemmings 和 Oh No! More Lemmings 关卡及图形文件生成地图。
* **mshines_render**:从 Monkey Shines 世界文件生成地图。
* **realmz_dasm**:生成 Realmz 场景并反汇编场景脚本为可读的类似汇编的语法。
## 构建
* 安装所需依赖项:
* 如果尚未安装 zlib,请安装它。(macOS 和大多数 Linux 系统已预装,但某些 Linux 系统如 Raspbian 可能没有。如果系统没有,可以执行 `apt-get install zlib1g-dev`。)
* 安装 CMake。
* 构建并安装 phosg(https://github.com/fuzziqersoftware/phosg)。
* 安装可选依赖项:
* 安装 Netpbm(http://netpbm.sourceforge.net/)。仅在 resource_dasm 无法自行解码 PICT 资源时才需要——如果您不关心 PICT,可以跳过此步骤。这仅为运行时依赖项;如果发现需要,可以在之后安装而无需重新编译 resource_dasm。
* 安装 SDL3。仅在需要 modsynth 和 smssynth 实时播放音乐时需要;没有 SDL,它们仍可构建并生成 WAV 文件。
* 运行 `cmake .`,然后运行 `make`。
* 如果构建其他依赖 resource_dasm 的项目,请运行 `sudo make install`。
该项目应在较新版本的 macOS 和 Linux 上正确构建。
## 使用 resource_dasm
resource_dasm 是经典 Mac OS 资源库的反汇编器。它从任意文件的资源库中提取资源,并将许多经典 Mac OS 资源格式(图像、声音、文本等)转换为现代格式。
**示例:**
* 从特定文件导出所有资源并转换为现代格式(默认输出到 `标签:68K, AppleDouble, AppleSingle, Bash脚本, CLUT, CPU仿真, Findomain, GameCube, HIRF, HSB, Icon Archiver, IREZ, MacBinary, Mohawk, PowerPC, RMF, SH-4, SOC Prime, VRFS, Wayback Machine, x86, 云资产清单, 位图字体, 压缩解码, 反汇编, 图像拼接, 图形渲染, 工具集, 开发工具, 数据恢复, 文件格式解析, 游戏资源, 索引色, 经典Mac OS, 网络连接监控, 资源分叉, 逆向工程, 重复资源查找