Ни для кого не секрет, что практически все разработчики сознательно стараются скрыть от игроков все ресурсы игры, дабы потом не созерцать в чужом проекте свои текстуры, звуки и прочее. Для этого они изобретают множество собственных форматов хранения ресурсов, так появляются всевозможные *.scr , *.tex, *.vol и другие. Многие из них на самом деле просто стандартные звуковые, графические и текстовые файлы с измененным расширением (например, во всех играх на движке Q3 pk3-файлы — это обычные zip-архивы). Но есть и настоящие “поделки”, которые никакими универсальными просмотрщиками не откроешь.
|
Теория
Самое непростое — это раскопать графическую составляющую игры. Рассмотрим, каким именно образом ее от нас прячут. Допустим, вы интуитивно догадываетесь, в каких именно файлах в игре хранится графика (названия файлов очень часто говорят сами за себя). Дело за малым — определить тип данных. Если файлов немного (можно по пальцам перечесть), они большого размера, и если при просмотре их содержимого можно среди закорючек разглядеть имена каких-
Рассмотрим по порядку особенности всех трех типов.
Фиксированный размер, без заголовка. Данный тип примечателен тем, что используется только в трехмерных играх. Все дело в том, что 3D-видеокарты имеют ограничение на размер графических изображений, и разработчикам приходится мириться с этим. Распознать такие файлы очень просто: их размер в байтах должен нацело делиться на 32.
Этот тип использовался, например, в Warlords 4, Warlords Battlecry 2.
Изображение с заголовком. Этот тип может использоваться во всех без исключения игр. В заголовок обычно записывается версия формата, количество бит и размер изображения в пикселях (например, 640х480). Иногда разработчики прибавляют еще несколько записей, иногда некоторые убирают — если вся игра сделана в одной цветовой палитре (например, 256 цветов), то зачем тогда указывать количество бит? За заголовком следуют данные изображения.
Этот тип был использован в играх Will Rock, NOX.
С несколькими изображениями и заголовком. Этот тип тоже используется довольно часто, от предыдущего он отличается тем, что файл имеет глобальный заголовок, в который записывается местонахождение (смещение до) каждой картинки в этом файле. У каждой картинки есть свой заголовок, он схож с предыдущим типом.
Этот тип использовался в Half-Life, “Битве Героев”, Fallout.
|
Переходим к трудоемкой, но весьма увлекательной практике. Если вы не владеете языками программирования или у вас нет денег для покупки программ-компиляторов, то “Игроманию” с 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 бит). |
|
Создайте в любом графическом редакторе картинку, нарисуйте что-нибудь, запомните ее размер (например, 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 байта какого-то мусора (выделено зеленым), а далее идут данные изображения, их видно в правой части экрана: если первая строка почти пуста, то все остальные наполнены разными закорючками.
|
Загружайте 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; {Очищаем память от уже ненужных данных}”
|
“
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));”, где исправлены координаты по вертикали, вы получите правильно отображенную картинку.
|
Боевое крещение
Если tga — общедоступный формат и с ним более или менее все понятно, то вот с другими, заточенными под конкретные игры форматами, придется попотеть. И снова на операционный стол ложится старина Fallout 2. Распаковав архивы *.dat в каталоге с игрой, в папке Art\Splash вы найдете файлы в формате *.rix. Это картинки, появляющиеся при загрузке игры.
|
В калькуляторе уже известным способом вычисляем HEX-значения чисел 640 и 480. Они будут соответственно равны 02 80 и 01 E0. Смотрим первую строчку на рис. 2.
Теперь можно писать скрипт.
“{Объявляем переменные
x,y — часто используемые переменные
|
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);
|
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(r*4,g*4,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. В этот раз мы не рассмотрели форматы, где хранится по несколько изображений. О них мы поговорим в одном из ближайших выпусков “Мании”. Напоследок бы хотелось отметить, что процедура обнаружения и вынимания графики из игры все же довольно трудоемка и требует терпения. Надо отдать должное разработчикам, которые потратили столько времени и сил на разработку своих форматов. Не забывайте про это. И помните, что коммерческое использование изображений, “вынутых” описанным в статье способом, незаконно. Вы можете их использовать только в некоммерческих целях.