Автор Тема: Exe без Exe  (Прочитано 1777 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Февраль 12, 2012, 19:11:44 pm
Прочитано 1777 раз

Ru_lon

  • Активный участник

  • Оффлайн
  • ****

  • 390
  • Репутация:
    9
    • Просмотр профиля
Exe без Exe
Вы хотели уменьшить размер архива при публикации своей игры? А исходник выкладывать не хочется? Тогда у вас появился новый вариант.
Многие сейчас ведут борьбу за открытые исходные коды (Open Source) и делают они это, как мне кажется, только для того, чтобы можно было вырезать кусочек

оттуда, кусочек отсюда, и слепить из этого свою игру. Это я, конечно, утрирую, но суть не в этом. Эта статья не для таких людей. Дело в том, что у всего

коммьюнити GameMaker’а не очень широкий канал, поэтому каждый хочет сделать свою игру как можно меньшего размера и при этом не показывать «внутренности».

Здесь и сейчас мы с вами попробуем реализовать такую «мечту».

Идея
На одном из форумов я встретил человека, который создал некий архиватор, позволявший сжимать exe-файлы GameMaker’а. Он утверждал, что во всех этих файлах

есть одинаковая часть, которую можно «отрезать», а по надобности опять вернуть, то есть распаковать. Я тогда не придал этому значения, так как для того,

чтобы распаковывать игры, нужно было иметь эту самую программу, поэтому смысл в запаковке практически отпадал. Через некоторое время один человек, по имени

Stasundr, подал мне отличную идею. А что если распространять вместе с «отрезанной» частью игры небольшой файлик, сделанный на GameMaker, который бы соединял

часть откомпилированного самого себя с частью игры? Гениально!

Недолго думая, я составил небольшой алгоритм, который сравнил два файла, созданных при помощи GameMaker 7. Оказалось, что первые 1752060 байт являются

абсолютно идентичными! Осталось написать сами алгоритмы склеивания и разрезания файлов. Они будут написаны непосредственно на GameMaker с использованием

функций для работы с двоичными файлами.

Разрезание
Для начала нам нужно написать небольшой алгоритм, который отделит от основного файла игры уникальную ее часть (то есть ту, которая у всех игр разная).

Запускайте GameMaker 7. Для начала необходимо создать новый проект. Сохраните его под именем data_splitter.gmk. Создайте новый объект с любым именем. Чтобы

позже не забыть, добавьте комнату и поместите в нее новый объект. Само действие разделения будет происходить непосредственно после запуска программы, так что

добавьте события создания (Create event) для нашего единственного объекта и поместите в нее действие выполнения кода (Execute Code со вкладки control). Далее

будем работать только с открывшимся окном кода. Мы сразу позаботимся об универсальности нашего приложения и добавим переменные, которые будут отображать путь

к обрабатываемому и результирующему файлам.
source = 'game.exe'; //файл для обработки
dest = 'data.dat'; //результирующий файл
Обратите внимание, что пути у нас относительные, поэтому необходимо, чтобы наш файл находился в одной папке с файлом game.exe. Дальше идет непосредственно

копирование из одного файла в другой.
f1 = file_bin_open(source, 0); //открываем первый файл для чтения
f2 = file_bin_open(dest, 1); //а второй для записи
file_bin_rewrite(f2); //переписываем файл (или создаем, если его еще нет)
 
//перемещаем указатель чтения на то кол-во байт,
//содержимое которых у всех файлов одинаково.
//Нам ведь нужна уникальная часть?
file_bin_seek(f1, 1752060);
 
//считываем все те байты уникальной части первого файла
//и записываем их сразу во второй файл
repeat (file_bin_size(f1) - 1752060)
  file_bin_write_byte(f2, file_bin_read_byte(f1));
 
//освобождаем ресурсы
file_bin_close(f1);
file_bin_close(f2);


Запускайте программу. Если вы все сделали правильно, то по адресу dest у вас появится новый файл, который будет содержать уникальную часть вашей игры.

«Пусковая установка»
Файл данных создан, осталось сделать программку, которая будет склеивать два файла в один и запускать его. Причем, для оптимизации, мы сделаем так, что наша

«пусковая установка» будет проверять, существует ли конечный файл: если да, то она сразу и запустит его, а если нет, то пройдет алгоритм склеивания.

Как я уже сказал выше, мы будем склеивать часть откомпилированной программы с файлом данных. Но где же нам взять этот файл, если мы будем распространять

только его исходник? Некоторые читатели подумают, что сначала этот файл нужно будет откомпилировать, поместить в папку с игрой и уже тогда только

использовать его. А вот и нет! Дело в том, что когда вы запускаете исходный файл из GameMaker’а, то он также компилируется и помещается в папке временных

файлов и, у нас, слава богу, есть к ней доступ. program_directory указывает на текущую рабочую папку программы.

Теперь создайте заготовку по прошлому примеру и назовите ее launcher.gmk. Замените только код в создании нашего первого и единственного объекта на:
data = 'data.dat'; //файл данных игры
game = 'game.exe'; //имя игры
 
if (!file_exists(game))
{
  //открываем два файла для чтения
  //первый - это откомпилированная "пусковая установка"
  //второй - файл данных
  f1 = file_bin_open(program_directory + 'launcher.exe', 0);
  f2 = file_bin_open(data, 0);
  //в этот файл будет совмещать два
  f3 = file_bin_open(game, 1);
  file_bin_rewrite(f3); //переписываем файл (или создаем, если его еще нет)
 
  //сначала записываем ту часть, которую мы ранее "отрезали"
  repeat (1752060)
    file_bin_write_byte(f3, file_bin_read_byte(f1));
 
  //а затем ту часть, которая осталась, т.е. файл данных
  repeat (file_bin_size(f2))
    file_bin_write_byte(f3, file_bin_read_byte(f2));
 
  //освобождаем ресурсы
  file_bin_close(f1);
  file_bin_close(f2);
  file_bin_close(f3);
}
 
execute_program(game, '', false); 
game_end();
Все. Запускайте и радуйтесь! Кстати, данный код будет успешно работать также и в том случае, если вы перед запуском программы предварительно откомпилировали

ее. Хотя это совершенно не обязательно.

Заключение
Все это, конечно, хорошо, и вы сможете сэкономить порядка 700КБ (а для небольших игр это половина объема), но данный алгоритм работает слишком медленно.

Игру, в которой одно, всего лишь, действие, склеивается порядка 20 секунд на достаточно мощном процессоре. К сожалению, с этим ничего не поделаешь – это

ограничение GameMaker. Правда, можно написать библиотеку, например, на Delphi. Я так и сделал и получил скорость склеивания порядка полсекунды на том же

процессоре. Вот так вот. Вы тоже можете это сделать, если хотя бы немного знакомы с Pascal.

Прошу вас заметить, что данные примеры не будут работать с различными версиями GameMaker’а, так как количество одинаковых байт различается. То есть, игру,

откомпилированную на седьмой версии, нельзя будет запустить с помощью «пусковой установки», сделанной на шестой версии инструмента. Следуйте небольшому

правилу: сама игра и программа для ее запуска должны быть откомпилированы на одной версии GM. Скажу лишь, что для шестой версии инструмента, количество

одинаковых байт составляет 486712.

Автор статейки: CH@$ER
Сильное государство угнетает нас, при слабом государстве погибаем мы сами.

Февраль 12, 2012, 19:17:41 pm
Ответ #1

Alcatraz

  • Администратор
  • Старожил форума

  • Оффлайн
  • *****

  • 1851
  • Репутация:
    123
    • Просмотр профиля
    • Flight Dream Studio
хорошая статья!  :)

Февраль 17, 2013, 19:59:35 pm
Ответ #2

warrior2000

  • Пользователь

  • Оффлайн
  • **

  • 20
  • Репутация:
    0
    • Просмотр профиля
спасибо за статью