Как достать графику из игры. Игровая палитра
Ни для кого не секрет, что практически все разработчики сознательно стараются скрыть от игроков все ресурсы игры, дабы потом не созерцать в чужом проекте свои текстуры, звуки и прочее. Для этого они изобретают множество собственных форматов хранения ресурсов, так появляются всевозможные *.scr , *.tex, *.vol и другие. Многие из них на самом деле просто стандартные звуковые, графические и текстовые файлы с измененным расширением (например, во всех играх на движке Q3 pk3-файлы — это обычные zip-архивы). Но есть и настоящие “поделки”, которые никакими универсальными просмотрщиками не откроешь.
Рис. 1. В глаза сразу же бросается первая строка в средней части экрана, последние 4 байта имеют вид BE 00 7C 00 (обозначена красным цветом). А ведь эти числа-то мы и смотрели в калькуляторе!
Если вы освоите нижеописанный материал, то с достаточной легкостью сможете добывать практически любые графические изображения из любимой игры. А дальше из полученной картинки вы сможете сделать wallpaper или оформить фан-сайт по игре. В общем, сделать с изображением все что угодно, кроме, естественно, использования в коммерческих целях. Теория Самое непростое — это раскопать графическую составляющую игры. Рассмотрим, каким именно образом ее от нас прячут. Допустим, вы интуитивно догадываетесь, в каких именно файлах в игре хранится графика (названия файлов очень часто говорят сами за себя). Дело за малым — определить тип данных. Если файлов немного (можно по пальцам перечесть), они большого размера, и если при просмотре их содержимого можно среди закорючек разглядеть имена каких-
Рис. 2. Первые 4 байта файла являются идентификатором “RIX3” (на рисунке он выделен зеленым), а следом за ним идут уже знакомые нам числа (выделены красным цветом), правда, написанные в обратном порядке: вместо 02 80 записано 80 02 и вместо 01 E0 написано E0 01. Так и должно быть, так записываются числа формата WORD. Далее идет FF 00 (это число в десятичном формате равно 256) — количество цветов в палитре. На все уходит ровно 10 байт, полная состыковка!
то файлов, то это игровой архив, и его необходимо разархивировать. Если файлов достаточно много и у них одинаковый размер (в килобайтах), то, скорее всего, это графические файлы с изображениями фиксированного размера, например 256х256 пикселей, и чаще всего без заголовка (Header), но об этом ниже. Если же файлы разных размеров, то это может означать две вещи: файлы содержат заголовки и делятся на два типа — с одним изображением внутри и с несколькими изображениями. Рассмотрим по порядку особенности всех трех типов.Фиксированный размер, без заголовка. Данный тип примечателен тем, что используется только в трехмерных играх. Все дело в том, что 3D-видеокарты имеют ограничение на размер графических изображений, и разработчикам приходится мириться с этим. Распознать такие файлы очень просто: их размер в байтах должен нацело делиться на 32. Этот тип использовался, например, в Warlords 4 , Warlords Battlecry 2.Изображение с заголовком. Этот тип может использоваться во всех без исключения игр. В заголовок обычно записывается версия формата, количество бит и размер изображения в пикселях (например, 640х480) . Иногда разработчики прибавляют еще несколько записей, иногда некоторые убирают — если вся игра сделана в одной цветовой палитре (например, 256 цветов), то зачем тогда указывать количество бит? За заголовком следуют данные изображения. Этот тип был использован в играх Will Rock , NOX.С несколькими изображениями и заголовком. Этот тип тоже используется довольно часто, от предыдущего он отличается тем, что файл имеет глобальный заголовок, в который записывается местонахождение (смещение до) каждой картинки в этом файле. У каждой картинки есть свой заголовок, он схож с предыдущим типом. Этот тип использовался в Half-Life , “ Битве Героев ”, Fallout.
Рис.3. Посмотрите, как текстура забора выглядит в игре.
ИнструментарийПереходим к трудоемкой, но весьма увлекательной практике. Если вы не владеете языками программирования или у вас нет денег для покупки программ-компиляторов, то “Игроманию” с CD или DVD вы приобрели не зря. На нашем диске вы найдете программу Image Hacker v1.1. Программа представляет собой абсолютно легальный текстовый редактор с возможностью запускать специальные скрипты. Скриптовый (читайте — текстовый) файл получается очень маленький, поэтому его намного легче отослать кому-то по почте. Язык скриптов данной программы заимствует многое у языка Паскаль (Pascal), но имеет намного меньше процедур, из-за чего становится очень простым, и в нем сложно запутаться. Команды языка вы можете прочитать на врезке. Еще я надеюсь, что у всех найдется старичок Windows Commander , в поздних версиях он называется Total Commander (далее ТС). Но если его нет, то сойдет любой HEX-viewer. А также обычный “ Калькулятор ”, входящий в стандартный пакет программ Windows. Чтобы активировать HEX-viewer в ТС, необходимо просмотреть нужный файл (клавиша F3 ) и выбрать шестнадцатеричный вид (клавиша 3 ). Желательно переключиться в ASCII, нажав кнопку S. Весь файл будет графически разбит на строки по 16 символов. Экран будет разделен на три части: первая указывает на номер первого элемента строки (в шестнадцатеричном коде), вторая (самая широкая) показывает HEX-код каждого символа, третья показывает сами 16 символов. Нам будет нужна только вторая часть. __ Структура файлов Структура всех файлов делится на две части: заголовок (его может и не быть, как в первом случае) и данные изображения , где хранятся цветовые значения всех точек (пикселей) изображения. Цветовое значение состоит из трех оттенков: красного (red) , зеленого (green) и синего (blue). Сокращенно RGB. Это цвет в формате 24 бита (под каждый оттенок отводится 8 бит), и он “вмещает” в себя около 16,5 миллионов цветов. В 32-битных изображениях к RGB добавляется уровень прозрачности (alpha) , показывая глазу уже 4 миллиарда цветов, но человек не способен увидеть десятой части этих цветов из-за своих скромных биологических возможностей. В 16-битных изображениях (это самый сложный для понимания формат) за счет понижения количества оттенков RGB в 256 раз удалось существенно снизить затраты процессорной мощи на обработку изображений, правда, цветов осталось всего 65535. Наконец, 256-цветные изображения. Их структура очень проста: в заголовок или в отдельный файл записывается палитра из 256 цветов в формате 24 бит, а в области данных каждой точке приписывается номер цвета в палитре от 0 до 255, этот номер умещается в размерность одного байта, поэтому этот формат также называют 8-битным (1 байт=8 бит).
Рис. 4. И как она же выглядит в графическом редакторе.
Анализ Создайте в любом графическом редакторе картинку, нарисуйте что-нибудь, запомните ее размер (например, 190х124, далее я буду рассматривать именно такой размер) и сохраните в формате tga с цветовой палитрой 24bit. Запустите калькулятор, в меню нажмите “ Вид” и выберите “ Инженерный”. Вводите размер картинки по горизонтали (в примере это 190) и выберите оператор HEX. Вместо 190 появится число в шестнадцатеричном коде, равное BE. Запомните это число, перейдите в оператор DEC — вместо BE снова появится 190. Введите высоту картинки 124 и повторите процедуру. Запомните получившийся результат, если вы все сделали правильно, то это будет 7С. Теперь открывайте вашу картинку HEX-viewer’ом в Total Commander, как описано выше. На рис. 1 показано, что мы нашли место в файле, где записаны ширина и высота изображения. Они начинаются в файле с тринадцатого байта и записаны в формате Word (2 байта), об этом говорят байты со значением 00, идущие после BE и 7С в количестве одной штуки (за каждым). Это может показаться сложным, поэтому давайте еще раз разберем: на запись ширины и высоты уходит 4 байта (см.рис. 1 , выделено красным цветом), логично подумать, что на запись одного параметра уходит 2 байта. Потом идет 2 байта какого-то мусора (выделено зеленым), а далее идут данные изображения, их видно в правой части экрана: если первая строка почти пуста, то все остальные наполнены разными закорючками._
_
Рис. 5. Много всего интересного можно найти в графических архивах игр. Например, в Call of Duty можно найти планы битв…
Процесс пошел Загружайте Image Hacker и начинайте считать, какое количество переменных нам необходимо. Ширина — раз, высота — два, Оттенки R,G,B — три, четыре, пять, и еще две возьмем для рисования изображения (координаты пикселей по осям x и y). Итого семь. Начинаем писать: “Showmessage(‘Это мой скрипт для чтения 24-битных tga-файлов’);” затем нажмите F9, и вы увидите окно с этим сообщением — начало положено. Давим кнопку ОК и пишем дальше: “Var width, height, r, g, b, x, y; {Объявляем 7 переменных} openfileas(‘*.tga’); {Просим указать нужный файл с маской *.tga} setpos(12); {Переходим на 12-й байт в выбранном файле} width:=read(3); {Читаем из файла ширину изображения} height:=read(3); {Читаем из файла высоту изображения} setpos(getpos+2); {Пропускаем 2 байта с мусором} setsize(width,height,24); _ {Создаем в памяти картинку в формате BMP с размерами TGA-файла} for y:=0 to height-1 do {Организовываем цикл для загрузки 3-х оттенков для каждого пикселя по Y, а следующая строка для каждого пикселя по X} for x:=0 to width-1 do {Так как цикл мы начинаем с 0, а не с 1, от максимального значения мы отнимаем 1, чтобы не вызвать сбой в программе} begin {Начало обработки каждого пикселя} r:=read(1); {Читаем Byte с оттенком красного} g:=read(1); {Зеленого} b:=read(1); {Голубого} setpixelcolor(x, y ,rgb(r,g,b)); {Пикселю по данным координатам указываем полученный тремя оттенками цвет} _ end; {Завершение обработки} savefileas; {Сохраняем получившееся изображение в файл} closefile; {Очищаем память от уже ненужных данных}”
Рис. 6 …и чертежи кораблей и другой техники.
__ Запускаем скрипт (F9), указываем картинку, программа запрашивает сохранение файла. Сохраняем. Смотрим, что получилось, и приходим в недоумение — картинка отражена по вертикали, и цвета какие-то странные. Ну, с тем, чтобы перевернуть изображение, проблем нет (даже Paint с этим справится), но вот что делать с цветами? Ответ прост: многие разработчики пренебрегают стандартным порядком оттенков RGB, зачастую просто меняя местами крайние из них (красный и голубой), то есть получая BGR. Меняем слегка код скрипта (меняем местами порядок чтения красного и голубого): “ b:=read(1); {Читаем Byte с оттенком голубого} g:=read(1); {Зеленого} r:=read(1); {Красного} “ Запускаем программу, повторяем открытие и сохранение файлов и — вуаля! — получаем правильные цвета, правда, изображение все еще перевернуто. Конечно, это не столь важно, но если заменить строчку “setpixelcolor(x, y ,rgb(r,g,b));” на “setpixelcolor(x, height-1-y,rgb(r,g,b));”, где исправлены координаты по вертикали, вы получите правильно отображенную картинку.
Рис. 7. В процессе вскрытия могут получаться непонятные или смещенные изображения. Рис. 8. Если слегка подкорректировать скрипт, все встает на свое место.
Боевое крещение Если tga — общедоступный формат и с ним более или менее все понятно, то вот с другими, заточенными под конкретные игры форматами, придется попотеть. И снова на операционный стол ложится старина Fallout 2. Распаковав архивы *.dat в каталоге с игрой, в папке Art\Splash вы найдете файлы в формате *.rix. Это картинки, появляющиеся при загрузке игры.
Рис. 9. Графика из Fallout.
Сначала прикинем, что мы знаем о графике в этой игре. Мы знаем, что в игре строго фиксированное разрешение экрана — 640х480, и всего 256 цветов. Так как эти картинки в самой игре не используются, предположим, что у них имеется собственная палитра (записанная в заголовок). Проверим. Размер всех файлов фиксирован — 307978 байт. Данные изображения, идущие после заголовка, должны занимать 6404801байт=307200 байт. Я умножал на 1 байт потому, что в 256-цветных файлах для каждого пикселя просто записывается номер цвета из палитры (0-255), который умещается в 1 байт. Теперь посмотрим, сколько данных у нас остается: 307978 (размер файла)-307200 (размер данных)=778 байт. Размер палитры у нас 256*3байта (RGB)=768 байт. Палитра вполне умещается, значит, оставшиеся 10 байт идут под остальные данные заголовка (ширина, высота, количество цветов в палитре и идентификатор файла). Проверим догадку — открываем любой rix-файл в HEX-viewer. В калькуляторе уже известным способом вычисляем HEX-значения чисел 640 и 480. Они будут соответственно равны 02 80 и 01 E0. Смотрим первую строчку на рис. 2. Теперь можно писать скрипт. “{Объявляем переменные x,y — часто используемые переменные
Рис. 10. В Fallout много “потерянных” изображений (неиспользованных в игре), наша цель — отыскать их.
width,height — ширина и высота картинки colcount — количество цветов в палитре r,g,b — три составляющие цвета (красный,зеленый,синий)} var x,y,width,height,colcount,r,g,b; {Открываем файл} openfileas(‘*.rix’); {Пропускаем идентификатор — “Rix3”} setpos(4); {Читаем ширину как Word} width:=read(3); {Читаем высоту как Word} height:=read(3); {Устанавливаем размер и количество бит будущей картинки} setsize(width,height,8); {Читаем количество цветов в палитре (максимум их 256)} colcount:=read(3); {Далее организуем цикл загрузки каждого из 256 цветов в палитру нашей BMP картинки} for x:=0 to colcount do begin r:=read(1);
Рис. 11. В некоторых играх можно найти весьма интересные композиции.
g:=read(1); b:=read(1); setcolortable(x,rgb(r,g,b)); end; {Далее идет цикл формирования BMP из данных изображения} for y:=0 to height-1 do for x:=0 to width-1 do setpixel(x,y,read(1)); {Сохраняем полученный результат} savefileas(); {Закрываем файл} _ closefile; “_ Запускаем скрипт, указываем файл, проверяем результат и видим: картинка есть, но почему-то очень темная. Вспомним, что картинка при загрузке игры как бы “появляется” из темноты, а потом так же исчезает. Значит, при загрузке игры каждый оттенок RGB-цвета в палитре умножается на какое-то число, и возникает эффект “осветления” картинки. Методом подбора я выявил, что нормальная по освещенности картинка получается при множителе, равном четырем (4). Смело меняем строку “setcolortable(x,rgb(r,g,b));” на “setcolortable(x,rgb(r4,g4,b*4));” и радуемся полученному результату. __ Список процедур _Процедуры для работы с файлами в игровом формате _ OpenFile(‘Имя файла в одинарных кавычках’) — загружает в память файл с картинкой в игровом формате. OpenFileAs(‘В кавычках — маска файла. Например .’) — открывает диалоговое окно для выбора файла для процедуры Open. SetPos(число) — устанавливает позицию в файле, с которой впоследствии мы будем читать данные. GetPos() — возвращает нынешнюю позицию в файле. GetSize() — возвращает размер открытого файла. read(число) — читает и возвращает скрипту данные из файла, где число: 0 — букву (1 байт) 1 — байт 2 — integer (4 байта) 3 — word (2 байта) 4 — дробное число (8 байт) CloseFile() — очищает память (обязательно выполняйте эту процедуру в конце скрипта). _Процедуры для работы с картинкой _ setsize(ширина, высота, количество бит) — устанавливает размер картинки. Количество бит может быть 8 (256 цветов) или 24. setpixel(x, y, номер цвета в палитре) — устанавливает цвет пикселя с координатами x и y. Эта процедура подходит только для 256-цветных картинок! setpixelcolor(x, y, цвет) — устанавливает цвет пикселя с координатами x и y. Эта процедура только для 24-битных картинок! setcolortable(номер ячейки палитры (0-255), цвет) — устанавливает цвет для соответствующего номера палитры. Save(‘имя файла в одинарных кавычках’) — сохраняет полученную картинку в bmp-файл. SaveFileAs() — открывает диалоговое окно для выбора файла для процедуры Save. _Прочие процедуры _ RGB(оттенки (числа от 0-255) красного, зеленого, синего) — возвращает полученный при смешении цвет. ShowMessage(любое значение) — выводит на экран значение (используйте эту процедуру для проверки прочитанных данных и для вывода указаний по дальнейшей работе). ToStr(любой параметр) — превращает любой параметр в строку (иногда требуется для нормальной работы предыдущей процедуры).
*** * *** Все рассмотренные выше примеры входят в комплект программы Picture Hack. В этот раз мы не рассмотрели форматы, где хранится по несколько изображений. О них мы поговорим в одном из ближайших выпусков “Мании”. Напоследок бы хотелось отметить, что процедура обнаружения и вынимания графики из игры все же довольно трудоемка и требует терпения. Надо отдать должное разработчикам, которые потратили столько времени и сил на разработку своих форматов. Не забывайте про это. И помните, что коммерческое использование изображений, “вынутых” описанным в статье способом, незаконно. Вы можете их использовать только в некоммерческих целях.