Sapphire CodeGen是Sapphire项目下的一个附属工具,用于链接库和SDK头文件生成。缺少它,Sapphire将无法完成编译。
Sapphire项目维护了一套基岩版的接口头文件,内含大量函数接口。若一个程序使用了里面的函数接口,例如:
SPHR_DECL_API("1.21.2,1.21.50,1.21.60", "call", "\xE8\x00\x00\x00\x00\x48\x8B\x8B\x00\x00\x00\x00\xBA\x00\x00\x00\x00\x48\x83\xC4")
public: void MinecraftGame::_update();那么就要有一个库导出该符号: ?_update@MinecraftGame@@QEAAXXZ。
Sapphire CodeGen则基于LLVM库,扫描Sapphire项目的接口头文件,自动生成包含所有接口的符号的库,提供给Sapphire自身和mod。
能够被生成符号的接口都必须包含SPHR_DECL_API注解,SPHR_DECL_API可以标记在函数或静态生命周期变量上,其接收2或3个参数:
SPHR_DECL_API("适用版本", "操作码序列", "特征码")
- 适用版本: 逗号分隔
- 操作码序列: 表示特征码扫描结果还需经过特定操作后得到最终结果。操作码序列由逗号分隔的若干个操作码组成。操作码是如下之一:
- "none": 等价于空: ""。
- "call": 将输入地址作为call指令,取call指令的目标地址
- "lea": 将输入地址作为lea指令,取lea指令的目标地址
- "mov": 将输入地址作为mov指令,取mov指令源操作数
- "deref32": 将输入解引用,取32位整数
- "deref": 将输入解引用,取64位整数
- "disp:N": 取 输入+N, N可为负数
- "rprl: M,N": 将输入地址作为一条汇编指令,取从 输入+M 开始的操作数作为结果,N为指令长度
SPHR_DECL_API("适用版本", "特征码")
- 等价于 SPHR_DECL_API("适用版本", "", "特征码")Sapphire CodeGen在收集所有标记了SPHR_DECL_API的符号后,就会生成一个包含所有符号的.def文件,和一个收集了所有特征码和操作码序列与符号的数据库文件,供Sapphire运行时使用。
Sapphire CodeGen还可以生成SDK头文件,输出为剔除SPHR_DECL_API注解后的SDK头文件。