Недавно решил пройти Vice City на Play Station 2. Многие эту игру любят за масштабный открытый мир, который можно очень долго изучать. Один из аспектов игры - это поиск "пакетов", спрятанных по всему городу. На некоторые из них можно случайно наткнуться в ходе игры, но чтобы собрать все 100, нужно приложить значительные усилия.
Я захотел собрать их все. Исследовать каждый сантиметр города мне не хотелось, а просто посмотреть в интернете, где находятся пакеты, было бы неинтересно. Поэтому я решил покопаться во внутреннем устройстве игры и попытаться найти координаты всех пакетов.
План был такой: надо найти несколько пакетов самостоятельно и узнать их координаты в игровом мире. Когда у меня будут координаты, я смогу запустить поиск этих значений по файлам игры. Если я найду, где хранятся координаты известных мне пакетов, то я смогу прочитать и координаты остальных.
На диске с игрой было несколько типов файлов, которые выглядели полезными:
• SLES_510.61 - главный скомпилированный бинарник
• Файлы с расширениями IDA и IPL и ZON. Эти файлы текстовые, в некоторых хранятся координаты.
• MAIN.SCM - бинарный файл неизвестного назначения. Как выяснилось далее, там хранятся все скрипты и миссии в игре.
Координаты известных пакетовIPL файлы выглядели интересно, так как в них хранятся названия и координаты объектов. Там описаны всякие фонарные столбы, пальмы и скамейки. Хоть пакетов я там и не нашёл, эти файлы помогли мне приблизительно узнать координаты некоторых из известных мне пакетов.
Я выбрал в качестве референса пакеты, которые находились возле особенных, выделяющихся объектов. Один был возле маяка, другой - в пиццерии и третий - возле бассейна с характерной формой. В IPL файлах они были записаны как nbt_pizzaplace, od_lighthouse и
cokpoolwater.
Читаем машинный кодСреди машинных инструкций и структур где-то должны лежать данные. Единственное, на что я мог полагаться в бинарниках - это числа. Я надеялся, что они хранятся в каком-нибудь нормальном формате, который я смогу прочитать. Число с плавающей точкой можно получить, читая любой набор байтов. Мне же подходят только те числа, которые похожи на координаты - в пределах от -2000 до 2000 и по модулю больше 0.1. Так я могу отсеять числа с большой экспонентой - такие числа встречаются среди данных чаще всего.
Я стал запускать линейный поиск блоков байтов, которые при раскодировании дадут мне хорошие числа. Путём перебора параметров выяснилось, что больше всего чисел получается, если искать 4-байтные float-ы, записанные в
little endian. Нашлось 246 525 чисел в основном бинарнике и 74 207 в MAIN.SCM.
Теперь можно начать искать координаты известных пакетов, которые я нашёл ранее. Я брал каждое из найденных чисел и проверял, есть ли ещё одно число, записанное с определённым отступом после него. Если есть, то первое число интерпретировалось как X и второе - как Y. Дальше считаем евклидово расстояние до известных пакетов и репортим, если это расстояние меньше 50 до любого из них. В MAIN.SCM нашёлся кластер из 6 чисел, которые подходили под все условия. Это и было то заветное место, где хранятся координаты всех пакетов!
Оказалось, что пакет возле маяка хранится самым первым в списке. А всего нашлась 101 точка. Получается, пакетов не 100, а 101?
Координаты почему-то хранятся с отступом в 1 байт между числами и 2 байта между пакетами. Получается, на одну координату отведено 5 байт, а на точку - 17 (3 координаты + отступ). Почему нет выравнивания и почему не записано просто одно число за другим - не знаю.
Наносим точки на картуВ файле NAVIG.ZON нашлись координаты районов города с названиями. Это помогло мне сопоставить точки со скриншотом карты. При помощи скрипта была сгенерирована прозрачная картинка с границами областей и точками на местах пакетов. Потом самая сложная часть - сопоставить сгенерированную карту с игровой с нанесёнными вручную точками.
Интересно, рассчитывали ли разработчики на такой вариант прохождения игры?