Реверс-инжиниринг из детства - вытаскиваем данные из Carmageddon TDR2000
Оффтоп - у меня навязчивая идея сделать гонки, где можно было бы проехать на машинах из одной старой игры трассу из другой старой игры :) Уже поковырялся в NFS1-NFS5, Carmageddon1-2, и вот, дойдя до TDR2000 решил, что пора как-то уже делиться с людьми своими наработками :)
Итак, заходим в папку игры, что мы имеем? папку Assets и папку Saves. Очевидно, данные в первой :)
А там уже есть и папка Tracks (локации) и папка Cars (тачки)!
Ну, ввиду того, что цель стоит в том, чтобы разобраться как всё устроено - начнём с Cars, там обычно меньше данных :))
Ткнём, ну, в electric_blue
файл *.h - это описание каких то нод, пока запомним про его наличие :)
*descriptor.txt - а вот это, похоже, важный файл, есть упоминания файлов, входящих в описание модели. Думаю, обязательно к нему вернёмся :)
*texturedescriptor.txt - наверняка описание использования текстур. к нему если и вернёмся, то на стадии текстурирования модели :)
Вот что и правда интересно, и не поддается анализу через супер-утилиту Блокнот (ахахах) - так это файл dir и файл pak.
Логично предположить (исходя из размера и названия) - dir это индекс, pak - это сами упакованные данные.
Вообще обычно в старых играх индекс и сами данные лежат в одном файле. А тут - отдельно. Ну, мне же проще. Открываем DIR в Hex-редакторе...
ан нет, не проще :))
Глаз цепляется за то, что каждый нечётный байт как будто бы содержит контент, а чётный - видимо какие то флаги.
Вообще, при расшифровке таких архивов важно получить следующие данные:
- Название файла
- Смещение начала даннах
- Размер данных
Вернёмся же к индексу.
В чётных байтах как будто записаны названия файлов.
Но названия (String) должны либо иметь длину в начале, либо заканчиваться нулём.
Здесь ни то ни то, но в байте флагов в конце строчки - всегда 08h!
Запомним-с. а лучше - запишем-с
А что идёт после названия? наверняка нужные нам указатели смещения и размера.
C9 7F 16 00 - хм. какое то большое значение для смещения первого элемента.
B6 02 00 00 - а вот это для размера норм. Но, как бы там ни было, смещение укладывается в размер файла PAK (1474505 внутри файла 1 475 199 байт) - и даже тот факт, что так близко к верхней границе, говорит о том, что мы близко к истине :) просто первый элемент в индексе не является первым в самом архиве.
Пора писать скрипт чтения архива!
Вот здесь я реально немного задолбался писать свои копания в архиве, скажу кратко - в DIR файле не просто индекс, он еще и "заархивирован" так, чтобы повторяющиеся части путей не писать повторно. В итоге файл делится на блоки - ноды.
вся суть в байте флагов (про который я говорил ранее)
исследование привело к следующим выводам:
- 08h - завершение строки. после него сразу идут смещение и размер данных в файле PAK
- 40h - у текущего символа есть "вложения" - нужно дальше искать ноды и присобачить текущий преффикс к ним перед тем, как возвращать имя этих записей
- 80h - ничего не делаем, просто читаем дальше имя записи.
Итак, вот у нас есть список имён файлов, их смещения и размеры внутри PAK.
Пробуем читать.
На первый взгляд всё ок - смещения, а так же смещения+размер - все укладываются в размер файла PAK.
Но, что то не так.
Файлы, которые называются .txt ведут на данные, которые не очень то похожи на текстовые.
Запакованы?
В те времена часто использовался zlib для упаковки, который можно проверить по наличию байтов компрессии (с просторов интернета):
78 01 - No Compression/low
78 5E - Fast Compression
78 9C - Default Compression
78 DA - Best Compression
И да, 78 DA частенькой находится в файле PAK
Единственное, что смущает - он не в начале данных конкретной записи файла идёт... значит, пишем алгоритм, который пропускает всё, что идёт до этих данных. А остальное скармливаем ZLib'у (использую Ionic.zlib). Как результат - теперь получаем пачку файлов с данными машины. А вот об этом уже дальше, если вдруг это и правда интересно :)
Если есть желающие тоже в этом покопаться - черканите, оформлю в реп то, что уже накодил.
И, если есть ссылки на уже готовые решения - тоже пишите, мало ли, я провафлил этот момент и изобретаю велосипед :)



