Картридж из бумаги: можно ли вместить целую игру в QR-код

Эксперимент ради науки.

Благодаря QR-коду мы уже почти десятилетие можем быстро переходить по ссылкам, просто наведя камеру на рекламный баннер — ведь, по сути, это носитель информации.

Но если QR-код содержит данные, можно ли в него вместить целую игру? И речь не о ссылке на веб-приложение, а о полноценной программе, которую можно запустить и играть.

Блогер MattKC разработал игру — классическую «Змейку», — которая уместилась в QR-коде и может запускаться с веб-камеры. И всё бы ничего, если бы не ограничение в формате — всего несколько килобайт. Пересказываем его ролик о том, как ему это удалось.

Картридж из бумаги: можно ли вместить целую игру в QR-код

QR-коды бывают разного формата. Самый большой из них, «версия 40», содержит 177х177 пикселей — или 2953 байта. Это всего 2,88 килобайта.

Это ничтожно мало даже в сравнении с дискетами — которые в большинстве своём достигали 1,44 мегабайт (а позже — 2,88 мегабайт). Иначе говоря, типичная дискета может содержать почти пятьсот, а то и тысячу QR-кодов максимального размера.

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

К примеру, существуют игры, разработанные для загрузочного сектора дискеты — это всего 512 байта. О них рассказывал блогер The 8-Bit Guy.

А картриджи от легендарной Atari 2600 были размером всего 4 килобайта. Это, конечно, не 2,88 — но всё ещё хороший пример того, как людям удавалось умещать игры в таком крошечном носителе.

Так как эксперимент проводился «ради науки», MattKC выбрал всем знакомую «Змейку». В качестве основы для программы блогер остановился на Windows. Программу можно было бы написать и для телефонов, но, по словам MattKC, из-за закрытости мобильных платформ на них намного сложнее заставить работать код, считываемый с QR.

Поначалу блогер написал «Змейку» на HTML и CSS, чтобы она могла запускаться на современных браузерах — но он посчитал это «нечестным» подходом, так как «браузеры делают всю работу за вас». Поэтому MattKC решил использовать Windows Portable Executable (.exe).

На первый взгляд написание игры в таком формате может показаться нереальным — простейшая программа на языке C, выводящая надпись «Hello world!», уже весит сто килобайт. Но значительная часть этого веса — не сам код, а библиотеки языка, к которым обычно обращается компилятор.

Компилятор нужен для того, чтобы транслировать обиходные языки (C, C++ и так далее) в машинный код — который, грубо говоря, посылает нужные команды процессору напрямую.

Ненужные библиотеки можно отключить вручную — тогда вес программы снизится сразу до 3 килобайт.

MattKC пошёл ещё дальше — теперь он собрался в целом отказаться от стандартного компилятора C, написав код на низкоуровневом языке ассемблера х86 — ему компилятор не нужен.

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

MattKC

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

Впрочем, уже на первых этапах написания кода начались сложности. Программа, которая запускала простое пустое окно, уже весила 2,5 килобайта — а ведь предстояло написать ещё и код от самой игры.

Стоило добавить в «игру» простую белую точку, которая бы перемещалась по чёрному экрану, и размер кода подскочил ещё сильнее — до 3 килобайт. Когда MattKC увидел, что дополнительная оптимизация не помогает, он понял, что «откусил кусок больше, чем смог проглотить» — ведь ассемблер довольно сложен в использовании, и далеко не каждый программист сможет написать на нём эффективный код.

Поэтому блогер вернулся к более знакомому для него C, правильно настроив компилятор. MattKC переписал весь код заново, и вуаля — программа весила 2,46 килобайта. По мере написания игры он продолжал поглядывать за счётчиком, так как одна строчка кода может прибавить к весу от пары до сотни байт — приходилось постоянно искать пути для оптимизации.

В конце концов MattKC дописал полностью функционирующую «Змейку» со всеми полезными фичами, которые присутствовали ещё на старых «Нокиях». К примеру, игра распознаёт нажатие сразу двух стрелочек подряд, если пользователю нужно очень быстро сменить направление. Также у змейки, если она вот-вот упрётся в собственный хвост, появляется чуть больше времени для манёвра перед концом игры.

Но такой код весил 3,1 килобайта — что значительно больше предела в 2,88 килобайт. А так как MattKC не хотел урезать функции, чтобы его «Змейка» оставалась играбельной, ему пришлось прибегнуть к сжатию.

В случае с программами формата .exe используют такой приём, как Executable packing («Упаковка исполняемых файлов»). При его использовании оригинальная программа сжимается, но к ней прикрепляется небольшой код, который её распаковывает. С точки зрения обычного пользователя нет никакой разницы — он всё так же запускает .exe.

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

MattKC

Сначала MattKC использовал довольно распространённый упаковщик UPX, но он увеличил код «Змейки» до 4,5 килобайт. То есть, от сжатия программа стала лишь больше.

Затем блогер нашёл другой упаковщик — Crinkler, который устанавливается напрямую в компилятор. И благодаря ему размер «Змейки» упал аж до 1,4 килобайта — что в два раза меньше порога.

Чтобы перевести код игры в QR, MattKC задействовал утилиту qrencode. И вот, наконец, получился QR-код с работающей «Змейкой».

Но это ещё не всё
Но это ещё не всё

Теперь, чтобы игру можно было запустить в Windows, нужно сделать так, чтобы QR-код мог транслироваться в обратно в .exe. Для этого MattKC использовал утилиту ZBar.

Сначала блогер попробовал прогнать через утилиту изображение с QR. Всё сработало — единственное, что стоило указать в программе, так это то, что QR содержит не текст, а двоичные данные.

Но вся суть QR-кодов состоит в том, что их можно распечатать и оставить где-то в реальном времени. Поэтому теперь MattKC решил проверить, откроется ли «Змейка», если прочитать листок с QR с веб-камеры.

На этот раз задача оказалась сложнее. Раз за разом у блогера выскакивала ошибка сегментации — конечный .exe, созданный на основе снимка с веб-камеры, был повреждён.

Поэтому MattKC решил сравнить оригинальный и конечный .exe через hex-редактор — приложение, в котором данные представлены как последовательность байтов. И тут он заметил, что байт 0A во втором варианте программы превращался в два байта — 0D и 0A.

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

Исторически сложилось так, что в Unix-системах (Mac, Linux, iOS, Android) разрыв представляет собой один байт — 0х0A, а в Windows — два байта, 0x0D0A.

Большинство современного софта умеет различать разные виды разрывов и автоматически конвертирует их — но даже Windows Notepad до 2018 года признавал лишь собственную двухбайтовую интерпретацию.

И уже после того, как MattKC поправил код в ZBar, «Змейка» наконец начала открываться и через веб-камеру. Блогер также написал скрипт, который запускает .exe сразу после сканирования QR-кода.

Так что если вы меня спросите, это безумно круто. Само собой, в этом не особо много практической пользы, но сам факт того, что QR-код, используемый в основном для ссылок на сайты, может работать как небольшой игровой картридж — это классно.

MattKC

Единственная проблема, которая может возникнуть с такого рода экспериментами — ничто не мешает злоумышленникам использовать QR-код, чтобы запускать вредоносные приложения на системах.

Гайд по запуску «Змейки» от MattKC можно прочесть здесь.

250250
85 комментариев

Спасибо за наводку @Bourbon. Он успел пересказать видео раньше нас у себя в блоге — но у него акцент на технических подробностях, а у нас выжимка ролика чуть пошире и более общеобразовательная. Прочитайте его пост тоже, чтобы составить полную картину — https://dtf.ru/u/195154-bourbon/186196-mozhno-li-umestit-igru-v-qr-kod

57
Ответить

Ждите скоро челленджей "можно ли запустить DOOM на QR-коде".

37
Ответить

это уже не очень реально. Одна из самых маленьких игр, без текстур и прочего (процедурная геренация) весит 96кб. С учетом, что ее делал не профессионал, думаю легко можно ужать в 2-3 раза. Но это все равно намного больше 2.88кб

1
Ответить

Или димейк Skyrim

Ответить

Комментарий недоступен

16
Ответить

А я буду сканировать все игры

5
Ответить