【问题标题】:Populating an array with include directives使用包含指令填充数组
【发布时间】:2020-05-12 00:36:00
【问题描述】:

今天早上我得知著名的电子游戏《超级马里奥 64》已经完全反编译回 C 源代码。只是出于好奇,我决定看一看,我发现了一些我以前从未见过的东西。

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

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

1) 这样做真的合法,甚至被推荐吗?
2) 你为什么要这样做?
3) 为什么包含引用 *.c 文件?
4) 为什么将类型设置为 u8(如果我明白的话,这应该是 unsigned char 的标准别名)?
5) ALIGNED8 宏是什么?这是标准的东西吗?

我曾尝试自行收集信息,但在此主题上找不到太多信息。如果你想自己看源代码,这里是链接:https://github.com/n64decomp/sm64

【问题讨论】:

    标签: arrays include static-linking precompile


    【解决方案1】:

    来自比我聪明一点的人-

    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 的作用,它只是包含另一个文件的文本 从这个定义可以看出,是的,在这种情况下使用它是绝对合法的;是否明智是另一个问题。

    【讨论】:

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

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

    1 和 2。我不认为这通常是明智的做法,但重要的是要记住回购的要点 - 允许轻松修改代码库,同时保留其编译 1:1 的能力SM64的ROM。将文件拆分后可以更轻松地找到事物的相关位置,尽管这个特定的位置还没有很好地命名。

    1. 因此,inc.c 文件是美化的头文件,只需将其代码插入该位置即可。它被命名为 .c 文件,因为它是一种 C,而不是合法的 C 文件本身。这就是为什么它是 .inc.c,因为它包含在内>

    2. 这是一个标准的无符号字符,这是正确的。这可以在 types.h 中找到。这样做是因为它实际上只是导入了一堆可以单独读取的数据。这个特定的文件不在 repo 中,但是如果您提取资产,您可以看到这是一个插入其中的图像。图像的数据只是被拆分成 u8 并放在那里,这样既可以提取/插入,也可以更轻松地进行编辑。

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

    希望我没有犯任何错误,这会有所帮助。重要的是要记住整个 GitHub 并不是一个真正的典型,因为它较少担心内部一致性,而更多地担心外部(ROM)一致性,这通常意味着有时必须将解决方案组合在一起以允许功能。如果您还有其他问题,我会再次建议您在 Discord 中提问,因为这些人比我更了解情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-13
      • 2023-02-01
      • 2018-05-24
      • 2019-01-23
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多