Заполнение массива директивами include - PullRequest
1 голос
/ 26 января 2020

Этим утром я узнал, что знаменитая видеоигра Super Mario 64 была полностью декомпилирована обратно в исходный код C. Просто из любопытства я решил просмотреть его и заметил кое-что, чего никогда раньше не видел.

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

Похоже, они помещают директиву включения в массив. Это делается неоднократно на протяжении всей программы.
Я уже некоторое время изучаю C, и я считаю себя достаточно свободно владеющим этим языком, но это что-то чрезвычайно новое для меня, и у меня так получилось много вопросов по этому поводу.

1) Это действительно законно или даже рекомендуется делать что-то подобное?
2) Зачем вы это делаете?
3) Почему включение относится к * . c file?
4) Почему для типа задано значение u8 (который должен быть стандартным псевдонимом для unsigned char, если я так понял)?
5) Что это за макрос ALIGNED8? Это что-то стандартное?

Я пытался собрать информацию самостоятельно, но не смог найти много по этой теме c. Если вы хотите посмотреть исходный код самостоятельно, вот ссылка: https://github.com/n64decomp/sm64

Ответы [ 2 ]

1 голос
/ 29 января 2020

От парня, который немного ярче меня -

1 & 2: мы включаем изображение, преобразованное в C. Для этого есть другие методы, кроме массивов в коде. c, но это метод, используемый разработчиками sm64, поэтому мы имитируем его c. И вместо массива C копирования-вставки у нас есть система сборки, которая автоматически генерирует (части) C из изображений, которые затем включаются #include. Это работает прилично хорошо, лучшее, что мы могли бы сделать в данных обстоятельствах. (Предполагая, что мы хотим сохранить все в C вместо сборки - в сборке мы бы .incbin были бы чище, но стали бы менее переносимыми.)

3: .h было бы неправильно, так как это не заголовочный файл, который объявляет функции, типы и т. д. c., а скорее данные (частичный C файл)

это u8, потому что файл, который мы включаем, является просто двоичным блоком данных, и мы не хотим делать предположения о порядке байтов

ALIGNED8 фактически игнорируется Я ДЕЛАЮ. Его эффект заключается в выравнивании массива по 8 байтов в G CC. Причина в том, что адреса, отправляемые в RSP, должны быть выровнены по 8 байтов, и без такой директивы это не гарантируется. В частности, G CC удачно переупорядочивает переменные таким образом, что они не выровнены по 8 байтов. IDO не выполняет такого рода переупорядочение (он просто генерирует массивы в исходном порядке), но в любом случае переменные в конечном итоге оказываются выровненными на 8 байтов. это помогает узнать, что делает #include, то есть просто включает текст другого файла из этого определения, из которого следует, что да, это абсолютно законно использовать в этом контексте; мудрый ли это другой вопрос.

1 голос
/ 28 января 2020

Прежде чем я go во что-либо, позвольте мне сначала порекомендовать использовать ссылку Discord, прикрепленную к этому репо, discord.gg/27JtCWs. Я сделаю все возможное, чтобы ответить на это, но я определенно не самый осведомленный о стандартах и ​​типичном поведении для общего кодирования. Мой опыт важен только потому, что я тесно сотрудничаю с некоторыми людьми, связанными с декомпиляцией.

1 & 2. Я не считаю, что это нормальное занятие, но важно помнить этот момент репозитория позволяет легко вносить изменения в кодовую базу, сохраняя при этом способность компилировать ПЗУ 1: 1 из SM64. Разделение файла облегчает поиск нужных мест, хотя этот конкретный еще не назван.

Таким образом, файлы c. c являются прославленными заголовочными файлами, просто вставляя их код в это место. Он называется. c файлом, потому что это своего рода C, просто не является допустимым C файлом. Вот почему это .in c. c, поскольку оно включено>

Это стандартный неподписанный символ, это правильно. Это можно найти в types.h. Это сделано потому, что на самом деле это просто импорт группы данных, которые можно прочитать отдельно. Этот конкретный файл отсутствует в репозитории, но если вы извлекаете ресурсы, вы можете видеть, что это вставляемое изображение. Данные изображения просто разделяются на u8 и помещаются туда, что позволяет одновременно извлекать / вставлять и более легко редактировать.

ALIGNED8 для компилятора. Компилятор IDO 5.7, который использует репозиторий, часто выравнивает вещи в выводе ПЗУ, а директива ALIGN8 говорит ему заполнить до 8 байтов. Если ALIGNED8 не было, он потенциально мог бы вставить эти данные слишком рано, что приведет к смещению ПЗУ.

Надеюсь, я не допустил ошибок, и это помогает. Просто важно помнить, что весь GitHub на самом деле не является типичным, так как он меньше беспокоится о внутренней согласованности и больше беспокоится о внешней (ROM) согласованности, что часто означает, что иногда решения нужно взламывать вместе, чтобы функциональность. Если у вас есть дополнительные вопросы, я снова рекомендую задавать их в Discord, поскольку эти парни гораздо более информированы, чем я.

...