Привет, хабровчане! В прошлой теме я рассказывал, как мы с командой производили (и дальше производим) ромхакинг такой игры, как Xenoblade Chronicles на Nintendo Wii. Я бы хотел рассказать о менее простой, но интересной теме – устройство хранения файловой системы у Nintendo GameCube. Так уж вышло, что я полюбил данную консоль и никак не мог упустить шанс рассказать о её технической стороне, хоть и малой. Не будем затягивать, начнём!
Введение
Как понятно по названию темы, речь пойдёт о том, как устроена файловая система Nintendo GameCube, а если быть точнее, то как устроена файловая система дисков. Давайте поговорим о том, какие всё такие диски использовались на Nintendo GameCube. Прошу Вас выйти из дома в гараж, сесть в DeLorean и отправиться в начало нулевых. На дворе 2001 год, на рынке игровых консолей уже как год властвует Sony PlayStation 2 и выходит оно – Nintendo GameCube. Мощнее начинка, больше потенциал, но почему продажи не так высоки, как у PlayStation 2? Крикнем “Спасибо!” Nintendo и их политике от пиратства и тому чудовищу, которое они решили использовать в своей консоле в качестве носителя информации – собственно разработанный miniDVD диск. Что он из себя представлял и почему смог погубить такую потенциальную консоль, спросите Вы? А я отвечу, представлял он из себя по размеру половину DVD диска, а вот проблемой стал малый объем в размере 1,5ГБ (против 4,7ГБ у DVD диска на PlayStation 2). Это чисто моё личное мнение, но именно данный диск и погубил продажи данной консоли. Об этом можно говорить много, но всё же вернёмся к основной теме. Да, Nintendo изобрели для GameCube свой собственный диск объёмом в 1,5ГБ, что категорически не хватало крупным играм, из-за чего их разделяли на несколько дисков (привет 90-е). Приходилось использовать кучу разных алгоритмов сжатия, как-то сокращать игры, чтобы они влезли на диск. Ладно, хватит о грустном, пора вернуться к основной теме.
Техническая составляющая
Как я сказал выше, диск имел объем в 1,5ГБ. С таким объёмом использовать всем прижившуюся ISO9660 или её модификацию было явно нерентабельно. Nintendo пошли другим путем – они разработали свою технологию описывания файловой системы, её основой стал блок FST (FileStringTable). Данный блок компактный и хранит всю нужную информацию о файлах, о нём я ещё расскажу побольше, но об этом чуть позже.
Весь игровой образ можно разделить на 6 блоков:
- Основная информация (boot.bin)
- Дополнение к основной информации (bi2.bin)
- Apploader (apploader.img)
- FileStringTable (fst.bin)
- DOL (main.dol)
- Основные данные
Предлагаю рассмотреть каждый блок отдельно. Для примера использовался первый диск европейской версии Resident Evil Code Veronica X (GCDP08).
Основная информация, блок boot.bin
Данный блок находится в самом начале файла и содержит информацию, которая позволяет опознать, что это за диск и что с ним делать дальше. Он имеет фиксированный размер в 0x440 байт. Есть байты, значения которых мне до сих пор не понятны, но их трогать мы и не будем, я расскажу только о том, что более важно:
class gcmBoot
{
public uint gameCode;
public ushort makerCode;
public byte diskID;
public byte version;
//seek to 0x1C
public uint DVDMagicWord; //0xC2339F3D
public string gameName;
//seek to 0x420
public uint offsetMainDol;
public uint offsetFST;
public uint sizeFST;
}
Как видно по коду выше, данный блок содержит в себе код диска, его номер (используется, когда игра содержит несколько дисков), название игры, указатель на блок DOL, указатель и размер на блок FST. В данном блоке есть и другие данные, но они используются для debug режима, что в гражданском режиме вовсе не используется.
Дополнение к основной информации, блок bi2.bin
Данный блок, как и прошлый, имеет фиксированный размер, правда на этот раз его размер 0x2000 байт, а начинается он строго после boot.bin (0x440). Сказать о нём мне нечего, он содержит в себе информацию для debug режима.
Apploader
Данный блок, как понятно по название, отвечает за загрузку образа, парсинга FST, инициализацию модулей, запуска DOL файла. Рассказать о нём, как и о bi2.bin мне нечего, так что идём дальше.
FileStringTable, блок fst.bin
Вот мы и добрались до самого интересного, данный блок содержит в себе разметку всех файлов, находящихся в образе: имена файлов и папок, их смещение и размер. Начинается он с адреса gcmBoot>offsetFST и имеет размер gcmBoot>sizeFST.
Его структура такова:
class gcmFST
{
public byte flags; // 0: File; 1: Dir;
public uint offsetName;//Real size 3 byte
//if flags = 0
public uint fileOffset;
public uint fileSize;
//if flags = 1
public uint dirParent;
public uint dirNext;
}
Попробую разъяснить полегче:
1 байт предназначается для определения, идёт информация о файле или о папке. 3 остальных байта предназначаются для указателя на строку с именем файла или папки (указатель начинается с начало блока с именами файлов\папок, а не с начала блока FST).
Если первый байт равен 0 (файл), то следующие 8 байт значат:
- 4 байта – указатель на файл в образе
- 4 байта – размер файла
Если же первый байт равен 1 (папка), то следующие 8 байт значат:
- 4 байта – номер папки, в которой находится данная папка
- 4 байта – номер элемента, на котором заканчиваются элементы в данной папке
С файлами всё просто и понятно, а вот с папками не очень. Но, я здесь для того, чтобы вам всё объяснить. К примеру, папка находится в корне диска, имеет название habr, dirParent равен 0 (т.к. в корне диска), а вот dirNext имеет значение 6. Сама папка находится 3 элементом в блоке FST, следовательно, все последующие элементы ровно до 6 элемента будут находится в папке habr, то есть элемент 4 и 5.
Самое главное, о чём забыл сказать, так что 0 блок (то бишь первый) является ссылкой на корень диска, он не имеет имени в блоке с названиями элементов, хоть и имеет указатель. Это просто надо учитывать и ничего более.
Как видите, благодаря подобной структуре, она имеет очень малый размер (если сравнивать с ISO9660 и её модификациями).
DOL
Как говорится, сердце игры. Как у Windows – EXE, так и на GameCube – DOL. Блок с основным исполняемым файлом. Конечно, были и игры, где использовался иной исполняемый файл, хранимый с основными игровыми файлами, но, чаще, никто так не извращался, слава богу.
Ну что ж можно рассказать о нём? Простой исполняемый файл, разделённый на секции:
- Семь TEXT секций (код)
- Одиннадцать DATA секций (данные)
Основные данные
И последний блок, который свою суть рассказывает по названию. Это блок идёт до конца файла и содержит в себе все файлы, выровненные по 2048 байт. Ходит легенда, что для экономии места можно выровнять эти файлы не по 2048 байт, а по 4 байта. И даже работать будет, на эмуляторе так точно. А вот убить лазер таким способом Вам точно не составит труда.
Заключение
В данной теме я попытался раскрыть, как Nintendo послала всех куда подальше и разработала простую, но всё же интересную и компактную файловую систему. Конечно, она не подойдёт для использования на домашних ПК из-за её особенностей хранения файлов. Данная файловая система не хранит в себе никаких флагов, кроме как File\Dir, не хранит время создания файла, EDC\ECC каждого сектора и т.п информацию, которая имеется в ISO9660. Но, она здесь и не нужна. Nintendo разработали такую компактную файловую систему, чтобы предоставить больше места для игровых данных. Ведь зачем диску с игровой системы хранить время создания файла и т.п.?
Спасибо за внимание.
Поделиться с друзьями
Комментарии (5)
GeMir
25.07.2017 12:41Размер в 0x440 байт
«1088 байт» читаются в тексте заметно легче, неправда ли?
В прошлой теме […] Как понятно по названию темы […] В данной теме
Статье, статьи?
darakanoit
25.07.2017 15:23Спасибо! Довольно интересно, но зачем? -Ограничить пиратство? В итоге PS2 стала легендой.
nickkee
25.07.2017 19:08Всегда уважал вот таких вот хакеров стареньких консолей, сразу видно, что не за бабки работа сделана, а для души :)
freeart
А какой выигрыш в цифрах давала такая оптимизированная файловая система по сравнению с ISO9660? Мне кажется там разница на несколько десятков мегабайт.