Arrays 用include指令填充数组

Arrays 用include指令填充数组,arrays,include,static-linking,precompile,Arrays,Include,Static Linking,Precompile,今天早上我得知著名的视频游戏Super Mario 64已经完全反编译回C源代码。出于好奇,我决定翻阅一下,发现了一些我以前从未见过的东西 // 0x09000000 ALIGNED8 const u8 machine_09000000[] = { #include "textures/machine/ttc_textures.00000.rgba16.inc.c" }; 看起来他们在数组中放入了include指令。这在整个计划中重复进行。 我学习C已经有一段时间了,我认为自己对这门语言相当流

今天早上我得知著名的视频游戏Super Mario 64已经完全反编译回C源代码。出于好奇,我决定翻阅一下,发现了一些我以前从未见过的东西

// 0x09000000
ALIGNED8 const u8 machine_09000000[] = {
#include "textures/machine/ttc_textures.00000.rgba16.inc.c"
};
看起来他们在数组中放入了include指令。这在整个计划中重复进行。
我学习C已经有一段时间了,我认为自己对这门语言相当流利,但这对我来说是非常新颖的,我有很多问题。 1) 这样做是合法的还是被建议的?
2) 你为什么要这样做?
3) 为什么包含引用*.c文件?
4) 为什么将类型设置为u8(如果我明白的话,它应该是无符号字符的标准别名)?
5) 那个对齐的8宏是什么?这是标准的吗?


我试着自己收集信息,但在这个话题上找不到太多。如果您想亲自查看源代码,这里有一个链接:

在我开始讨论之前,首先让我推荐使用该repo附带的Discord链接Discord.gg/27JtCWs。我会尽最大努力回答这个问题,但我绝对不是最了解一般编码标准和典型行为的人。我的经验只与反编译相关,因为我与一些参与反编译的人员密切合作

1和2。我不认为这是一个明智的做法,但重要的是要记住repo的要点-允许轻松修改代码库,同时保留其编译SM64的1:1 ROM的能力。将文件拆分可以更容易地找到相关的位置,尽管这个特定位置尚未命名

  • 因此inc.c文件是美化的头文件,只需将其代码插入该位置。它之所以被命名为.c文件,是因为它有点像c,只是它本身不是一个合法的c文件。这就是为什么它是.inc.c,因为它包含>

  • 这是一个标准的无符号字符,这是正确的。这可以在类型h中找到。之所以这样做,是因为它实际上只是导入了一组可以单独读取的数据。此特定文件不在回购协议中,但如果提取资产,您可以看到插入其中的图像。图像的数据被分割成u8并放在那里,这样既可以提取/插入数据,也可以更容易地编辑数据

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


  • 希望我没有犯任何错误,这会有所帮助。重要的是要记住,整个GitHub并不是一个典型的GitHub,因为它不太担心内部一致性,而更担心外部(ROM)一致性,这通常意味着有时必须将解决方案进行某种程度的黑客攻击才能实现功能。如果你还有其他问题,我会再次建议你在《不和谐》中提问,因为这些人比我更了解情况。

    来自一个比我聪明一点的人-

    1和2:我们正在将一个图像转换成C。除了.C代码中的数组之外,还有其他技术可以实现这一点,但sm64开发人员使用的就是这种技术,所以我们模仿它。我们没有复制粘贴C数组,而是让构建系统从图像中自动生成(部分)C,然后包括。它运行得很好,在这种情况下我们能做的最好。(假设我们希望将所有内容都保存在C中,而不是汇编中——在汇编中,我们将使用.incbin,这样会更干净,但它的可移植性会降低。)

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

  • 这是u8,因为我们所包含的文件只是一个二进制数据块,我们不想做endianness假设

  • ALIGNED8实际上在IDO上被忽略。它的作用是在GCC上对数组进行8字节对齐。原因是发送到RSP的地址必须是8字节对齐的,没有这样的指令就不能保证这一点。特别是,GCC乐于以非8字节对齐的方式重新排序变量。IDO并没有进行那种重新排序(它只是以源代码顺序发出数组),但变量恰好以8字节对齐结束。 它有助于了解include的作用,即只包含另一个文件的文本 根据这个定义,是的,在这种情况下使用它是绝对合法的;这是否明智是另一个问题


  • 谢谢你的回复!这真的很有趣,事实上也不像我想象的那么神秘。让我们看看我是否明白了这一点:基本上,一幅图像是在一个*.c文件(每个纹理或任何东西一个)中以8位的块进行解码的,该文件表示该图像。它是一个*.c,因为在头文件中不能执行类似的操作。然后初始化一个字节数组,在其中放入一个include指令。include引用的*.c仅包含表示映像的字节集,因此当预编译器执行其操作时,include将被这些元素替换,从而正确初始化数组。然后,该数组将在代码的其余部分中表示图像。这看起来是一个奇怪而复杂的解决方案,但它也相当巧妙。我弄错了吗?是的,你完全正确。很高兴这帮了你,如果你需要更多的帮助,请告诉我。再次感谢你!只要我有一点空闲时间,我可能会检查一下discord服务器,这东西真的很有趣。目前,我将确认您的回答:)