使用 include 指令填充数组



今天早上我了解到著名的电子游戏超级马里奥64已经完全反编译回C源代码。只是出于好奇,我决定翻阅它,我注意到了一些我以前从未见过的东西。

// 0x09000000
ALIGNED8 const u8 machine_09000000[] = {
#include "textures/machine/ttc_textures.00000.rgba16.inc.c"
};

看起来他们在数组中放置了一个包含指令。这在整个程序中反复进行。
我已经学习C语言一段时间了,我认为自己对这种语言相当流利,但这对我来说是非常新颖的,我有很多关于它的问题。

1(做这样的事情真的合法甚至建议吗?
2(你为什么要这样做?
3(为什么包含是指*.c文件?
4(为什么类型设置为u8(如果我直截了当的话,这应该是无符号字符的标准别名(?
5(ALIGNED8宏是什么?这是标准的东西吗?

我试图自己收集信息,但找不到太多关于这个主题的信息。如果您想自己查看源代码,这里是链接:https://github.com/n64decomp/sm64

来自一个比我聪明一点的家伙——

1和2:我们包含一个转换为C的图像。除了 .c 代码中的数组之外,还有其他技术,但这是 sm64 开发人员使用的技术,所以我们模仿它。而不是复制粘贴 C 数组,我们让构建系统从图像自动生成(部分(C,然后 #included。它运作良好,在这种情况下我们能做的最好的事情。(假设我们想将所有内容都保留在 C 而不是汇编中 - 在汇编中,我们会使用 .incbin,这会更干净,但它变得不那么可移植。

3:.h 是错误的,因为它不是声明函数、类型等的头文件,而是数据(部分 C 文件(

  1. 它是 u8,因为我们包含的文件只是一个二进制数据块,我们不想做出字节序假设

  2. ALIGNED8实际上在 IDO 上被忽略了。它的作用是 GCC 上的数组进行 8 字节对齐。原因是发送到 RSP 的地址必须是 8 字节对齐的,如果没有这样的指令,这是无法保证的。特别是,GCC 愉快地以使它们非 8 字节对齐的方式对变量进行重新排序。IDO 不进行这种重新排序(它只是按源顺序发出数组(,但无论如何,变量恰好在那里以 8 字节对齐。 它有助于了解 #include 的作用,即仅包含另一个文件的文本 从这个定义可以看出,是的,在这种情况下使用它绝对是合法的;它是否明智是另一个问题。

在我进入任何事情之前,让我首先建议使用附加到该存储库的 Discord 链接,discord.gg/27JtCWs .我会尽力回答这个问题,但我绝对不是最了解编码标准和典型行为的人。我的经验是相关的,因为我与一些参与反编译的人密切合作。

1 & 2。我不认为这是一件理智的事情,但是重要的是要记住存储库的重点 - 允许轻松修改代码库,同时保留其编译 SM64 的 1:1 ROM 的能力。拆分文件可以更轻松地查找事物的相关位置,尽管这个特定的位置尚未命名。

  1. 所以inc.c文件是美化的头文件,只是在那个位置插入它们的代码。它被命名为.c文件,因为它有点像C,只是本身不是合法的C文件。这就是为什么它是.inc.c,因为它是INCluded>

  2. 这是一个标准的无符号字符,这是正确的。这可以在 types.h 中找到。这样做是因为实际上它只是导入一堆可以单独读取的数据。此特定文件不在存储库中,但如果提取资产,则可以看到这是插入在那里的图像。图像的数据只是被分成u8并放在那里,允许它被提取/插入并更容易编辑。

  3. ALIGNED8适用于编译器。存储库使用的 IDO 5.7 编译器通常会对齐 ROM 输出中的内容,而 ALIGN8 指令告诉它填充到 8 个字节。如果ALIGNED8不存在,则可能会过早插入该数据,从而移动ROM。

希望我没有犯任何错误,这很有帮助。重要的是要记住,整个GitHub并不是一个典型的GitHub,因为它不太担心内部一致性,而更担心外部(ROM(一致性,这通常意味着有时解决方案必须被黑客入侵才能允许功能。如果您还有其他问题,我将再次建议您在 Discord 中提问,因为这些家伙比我更了解情况。

最新更新