Взлом цветного картриджа HP: превращаем его в ручной принтер

https://habr.com/ru/post/443582/
  • DIY или Сделай сам
  • Компьютерное железо
  • Производство и разработка электроники
  • Реверс-инжиниринг


image

Введение


Ещё с юности, когда у нас был старый DeskJet, меня интересовали картриджи струйных принтеров. Эти картриджи казались очень интересными и как только в них заканчивались чернила, я сразу забирал их себе. В то время я не мог сделать с ними ничего, кроме как разобрать и пачкать руки… Хоть я и знал, что там внутри есть какая-то сложная электроника, но при касании контактов батарейкой не происходило ничего интересного, а моих знаний по электронике на большее не хватало.

Чуть позже, когда я стал студентом, мне удалось раздобыть старый струйный принтер. В то время сам я пользовался лазерным принтером, поэтому он мне был не очень интересен, зато было любопытно исследовать картриджи и попытаться выполнить их реверс-инжиниринг. Я в самом деле написал статью об управлении этими картриджами, и хотя они работали достаточно хорошо, были и недостатки: мне так и не удалось выяснить точный порядок сопел, картридж был только монохромным (печатал маджентой), к тому же довольно старым, а потому разрешение оказалось довольно низким.

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

Мне наконец-то удалось получить управление трёхцветным картриджем и печатать в полном цвете!

Если вы хотите пройти со мной путь от кучи принтеров до полного контроля над картриджем принтера, то я делал доклад об этом на Hackaday Supercon 2018. Видеозапись выступления добавлена ниже. Если вам интересны подробности реверс-инжиниринга, то посмотрите его. В статье я расскажу о технических деталях созданной мной электроники, а также конкретные подробности управления картриджем, чтобы вы сами смогли нарисовать Nyancat при помощи ESP32 или другого микроконтроллера.

Приложение к презентации


Если вы не смотрели видео, то вот его содержание вкратце: я разобрал цветной картридж для принтера HP1112 (в Китае это картридж HP 803, но артикул зависит от региона), сделал снимки кристалла и пытался разобраться, как он работает. Когда мне не удалось выяснить многого, я начал считывать сигналы, передаваемые между принтером и картриджем, разобрался, какие сигналы нужно отправлять, чтобы картридж подчинялся моим приказам, а затем распечатал Nyancat и другие забавные штуки.

Часть исследования, посвящённая таймингам сигналов, в основном была процессом проб и ошибок. Я могу только догадываться, какая связь существует между сигналами, поэтому было довольно сложно разобраться в порядке между фронтами и в том, какие сигналы можно отложить, а какие нужно передавать вовремя. Для получения этой информации я изучил кремний картриджа. Оказалось, что мне и в самом деле удалось получить её, засунув картридж под микроскоп, но совсем не так, как я ожидал.

До выступления на Supercon я в изучал цветные картриджи, потому что они казались мне самыми интересными. После возвращения с Supercon мне захотелось выполнить обратную разработку и чёрного картриджа: его печатающая головка крупнее, чем у цветного картриджа, поэтому за раз я мог бы печатать больше. Вероятно, добавить поддержку и этого картриджа будет не так сложно: расположение контактов кажется таким же, и я знал, что протокол, скорее всего, будет похожим, потому что уже пробовал подключать чёрный картридж к своему «железу». Даже несмотря на то, что ПО передавало цветные изображения, ему всё равно удавалось что-то печатать.

Вот что я сделал с цветным картриджем: засунул его под микроскоп, убрал силиконовое покрытие с контактов, подготовился к соединению нескольких снимков в одно крупное изображение. Однако чёрный картридж отличался от цветного тем, что на его металлической пластине с соплами было больше надписей: под силиконовым покрытием скрывались названия сигналов для всех контактов!

image

(Кстати, если вы хотите посмотреть полные снимки с микроскопа во всём 40-мегапиксельном величии, то вот shield и кремний цветного картриджа! Полюбуйтесь на сложность сопел и снимка кристалла чёрного картриджа!)

Хотя может показаться, что это не так уж и много, в море немаркированных печатных плат, чипов без справочных материалов и артикулов, которые никуда не ведут, названия нескольких сигналов — это настоящая находка. По наитию я вбил отдельные названия сигналов с названием «Hewlett Packard» в Google Patents и обнаружил конкретный патент (и другой, более старый, на который ссылается первый) с чётким описанием технологий и сигналов, используемых в картриджах. Это бы сэкономило мне так много времени, когда я боролся с таймингами картриджа… ну да ладно. Могу искренне сказать, что эту подсказку найти было очень сложно: сигналы были не только покрыты силиконовой плёнкой, но и оказались крошечными: буквы имеют размер всего 30 микрометров, а это меньше, чем толщина человеческого волоса.

Патент описывает внутреннюю работу картриджа и его стоит прочитать (если вам удастся разобраться в использованном там юридическом жаргоне) просто чтобы понимать, насколько странную логику иногда применяет HP для управления всеми соплами. Сам по себе патент полезен, но его недостаточно для управления картриджем; по крайней мере, основная часть предпринятых мной трудов по реверс-инжинирингу всё равно была бы необходима, даже если бы у меня был этот патент.

Здесь и ниже я буду использовать названия сигналов и контактов, применяемые в патенте. Учтите, что в коде всё равно могут встречаться мои собственные названия сигналов; таблицу переводов я включу вместе с документацией.

Кодирование данных



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


На боку есть 16 контактов, идущих снизу, где находится печатающая головка. Как можно было увидеть на снимках с микроскопа, в печатающей головке чёрного картриджа примерно 336 сопел, а в цветном картридже — 612 сопел. На печатающей головке сопла расположены вертикальными рядами, и каждым соплом можно управлять электроникой, чтобы оно выстреливало крошечной капелькой чернил вниз, в сторону вставленной в принтер бумаги. Перемещая головку по вертикали, принтер может печатать «полосу» или любое другое изображение; эта полоса в случае чёрного картриджа имеет длину примерно 15 мм, а для цветного картриджа — 8 мм.

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


Так как контактов всего 16, должна существовать какая-то схема мультиплексирования для управления всеми соплами. В патенте объясняется, как это работает: управление соплами разделено на 14 отдельных групп. Эти группы срабатывают последовательно: сначала получает свои данные и срабатывает группа 1, затем группа 2, и так далее. Каждая группа управляет максимум 24 соплами, а данные для них передаются по трём шинам передачи данных. В случае цветного картриджа данные в трёх шинах соответствуют цветам: D1 — это данные жёлтого цвета, D2 — данные мадженты, а D3 управляет соплами, печатающими цианом.

В патенте работа подробно описывается на примере одной шины данных. На этом рисунке из патента показаны используемые сигналы:


В шине данных содержится восемь байтов, 0-7. Чётные байты управляются задним фронтом DCLK, нечётные байты — задними фронтами S1-S4. Сопла, данные которых управляются первыми четырьмя байтами, можно включить подачей питания по шине питания F3; сопла, связанные с последними четырьмя битами, включаются шиной F5.

Я понятия не имею, почему HP решила использовать для управления данными в соплах такой сложной схемой. Можно сказать, что здесь бы вполне нормально сработало нечто очевидное, вроде регистра сдвига. Я понимаю, что HP использует свои патенты как оружие против компаний, занимающихся перезаправкой картриджей; возможно, кто-то уже запатентовал более простое решение, и им пришлось придумать это более сложное решение, чтобы быть уникальными.

На этом графике, сделанном мной на логическом анализаторе, несложно найти сигналы, описанные в патенте:


Кроме управления соплами, картриджу также требуется сигнал (csync) для перехода к следующей группе сопел или для сброса и возврата к первой группе. Его можно увидеть на изображении с логического анализатора: на нём показаны предпоследняя и последняя группы из 14, а сигнал csync имеет в последней группе узнаваемую форму; он выполняет «сброс» картриджа, чтобы следующей получала данные первая группа. Этот сигнал также можно использовать для обхода групп сопел в обратном порядке; это полезно, когда печатающая головка ходит и слева направо, и справа налево. Хотя во втором патенте описывается, как это работает, я решил просто закодировать переход к следующей группе и выполнять сброс сигналов, показанных на моих изображениях линией csync.

Заметьте, что всё это происходит с довольно большой скоростью; задержка между двумя передними фронтами сигнала DCLK примерно равна 0,4 мкс, а расстояние между группами примерно равно 4 мкс.

Теперь мы знаем, что каждый бит в этих трёх шинах данных из 14 байт содержит команду срабатывания для одного сопла. Если бит равен 0, то соответствующее ему сопло срабатывает; если равен 1, то сопло не срабатывает. Чего мы не знаем, так это соответствия между битами и соплами. Если вы смотрели презентацию, то знаете, как мне удалось в этом разобраться: я распечатал на работающем принтере известный мне паттерн, перехватывая сигналы с помощью логического анализатора, а затем разобрался, каким должен быть порядок сигналов, чтобы декодировать сигналы обратно исходное изображение
.
К сожалению, соответствие битов соплам кажется довольно постоянным, но не полностью логичным. Похоже, что в основном это вызвано необходимостью физического отдаления на достаточное расстояние одновременно срабатывающих сопел (чтобы избежать перегрева или возникновения локального вакуума в ёмкости с чернилами). Кроме того, я также выяснил, что простота маршрутизации сигналов в картридже может сделать сопоставление битов и сопел довольно запутанным. В своей прошивке я просто реализовал это сопоставление как набор таблиц поиска.

Электроника


Теперь, когда мы знаем, как работают сигналы, мы можем управлять картриджем принтера с помощью простого микроконтроллера, верно? Ну, не сразу. В картридже принтера не используется простая логика на 5 В или 3,3 В. Шины данных управляются шинами на 16 В или 9 В. Шины питания тоже управляются 16 В и на самом деле в зависимости от количества срабатывающих сопел их можно подтянуть до тока источника питания. Нам нужно выполнить преобразование уровней.

В качестве преобразователя уровней я выбрал MC14504. Это старый однонаправленный шестнадцатеричный чип преобразования уровней, который может повышать напряжение до 18 В. Хоть этот чип и работает, оглядываясь назад, могу сказать, что это был не лучший выбор: он может подавать на выход всего несколько мА и имеет довольно большую задержку распространения. Думаю, он обеспечивает задержку некоторых выходных сигналов в зависимости от картриджа и подаваемой на выводы чипа нагрузки. У меня есть по крайней мере один картридж, которому требуется для работы сигналов небольшая регулировка таймингов, и я думаю, что причина в этом. К сожалению, готовые преобразователи уровней на 16 В сегодня не так доступны, поэтому я не могу заменить его чем-то получше. Впрочем, этого классического чипа с небольшой регулировкой оказывается вполне достаточно.

С шинами питания всё немного сложнее. Кроме того, что эти контакты забирают большую долю тока, также они непосредственно подключены к резисторам включенных сопел: если по каким-то причинам питание будет подаваться слишком долго, то эти крошечные резисторы перегорят и сопло полностью выйдет из строя. К тому же, этого «слишком долго» достичь довольно просто: достаточно включить сопла всего на несколько микросекунд, а если подать питание всего на миллисекунду, то они просто испарятся, полностью сломав сопло. Чтобы этого не происходило из-за программного бага или плохого соединения, я добавил аппаратной логики, обеспечивающей ограничение импульса небольшой величиной, кратной 10 мкс.


В первом прототипе я оставил несколько преобразователей уровней и не знал, как проявит себя ПО, поэтому решил проблему настоящим однотактным мультивибратором. В этой схеме два использованы мультивибратора в 74HC123, генерирующие импульсы, ширина которых задаётся сочетанием R/C, подключённого к контакту RCExt. Получившийся импульс генерируется только при возрастающем входном сигнале, поэтому постоянно высокий сигнал не приведёт ни к чему, кроме точно заданного, но паразитного импульса на выходе. После этого канал MC14504 используется как преобразователь уровней для поднятия напряжения до +16 В, а P-канальный МОП-транзистор обеспечивает необходимый ток.


На второй печатной плате я понял, что если изменю логику контактов питания так, чтобы они не использовали два канала схемы сдвига уровня, то достаточно будет всего двух чипов MC14504. Теперь у меня есть достаточно хороший программный контроль над шириной импульса, но мне всё равно хочется иметь защиту от постоянно высокого сигнала входного контакта. Вот схема, к которой я пришёл. Она работает так: в нормальном состоянии при низком сигнале PWRB_IN конденсатор C28 пуст, потому что любое напряжение в нём медленно стекает по R20 и R21: затвор транзистора Q4 имеет высокий уровень, а PWRB_OUT отсоединён от шины питания 16 В. Как только в PWRB_IN появляется высокий сигнал, Q6 заземляет один из концов C28; так как напряжение по нему равно 0 В, изначально это также подтягивает вниз другую его сторону, которая соединена с затвором Q4. Подтягивание затвора Q4 вниз делает его проводимым, и это позволяет току течь от +16 В к PWRB_OUT. В обычном состоянии PWRB_IN достаточно быстро снова переходит в состояние с низким уровнем, закрывая затвор Q4 и прерывая ток. Однако пока PWRB_IN имеет состояние low, C28 медленно заряжается: одна его сторона заземлена Q6, а другая подключена к 16 В через R21 и R31. Когда конденсатор достаточно зарядится, Q4 «увидит» высокий уровень на своём затворе и перекроет ток в PWRB_OUT, даже если PWRB_IN по-прежнему находится в состоянии с высоким сигналом. Этот механизм гарантирует, что PWRB_OUT будет подавать питание только в ограниченный промежуток времени.

В схеме также имеется небольшой резистор, соединённый последовательно с шиной питания 16 В (R31), а также небольшой конденсатор, подключенный параллельно к выходному сигналу (C15). Они нужны для «снятия напряжения» сигнала питания: без них резкое включение и отключение Q4 будет индуцировать кучу электромагнитных помех, искажающих сигналы, передаваемые в картридж.

Кроме этой логики больше особо ничего не требуется. Очевидно, что необходимы преобразователи уровней на +9 В и +16 В. Источник питания +9 В должен быть довольно скромным: я не замечал, чтобы эти шины в целом использовали больше нескольких мА. Так как он питает резисторы сопел, источник 16 В должен чуть более сильным: я сделал так, чтобы мой мог обеспечивать непрерывно не менее 400 мА, а также добавил довольно много развязывающей ёмкости.

Наконец, самая важная нагрузка по обработке изображений и генерации сигналов ложится на плечи микроконтроллера. Для этой цели я выбрал ESP32, в основном потому, что взял несколько штук с работы, но ещё и потому, что в нём есть довольно мощный контроллер I2S, в котором используется очень удобный параллельный режим: по сути, мы можем просто задать тактовую частоту, указать контроллеру I2S область памяти, и он будет параллельно выводить эти байты. Благодаря этому он идеально подходит для генерации необходимых сигналов управления; то, что у него есть два мощных ядра на 240 МГц, также помогает в обработке изображений.

Прототип


Разумеется, несколько преобразователей и МОП-транзисторов сами по себе не могут стать работающим контроллером картриджа принтера. Поэтому я создал отдельное устройство, задуманное как платформа для экспериментов с картриджем и его возможностями. Оно имеет модуль ESP32, логику, необходимую для управления картриджем, а также несколько источников питания для работы от литий-ионной ячейки. Также оно оснащено несколькими датчиками, призванными компенсировать неидеальные движения рук человека, а также кнопками и дисплеем, обеспечивающим обратную связь о печатаемых изображениях. Давайте разберём компоненты, возможно, для кого-то это станет источником вдохновения для хакинга картриджей:



Давайте начнём с источника питания. Питание поступает от литий-ионной ячейки и преобразуется в 3,3 В, 16 В и 9 В. Напряжение 3,3 В необходимо для датчиков и ESP32; оно генерируется с помощью простого LDO-регулятора HT7833. Напряжения 9 В и 16 В генерируются двумя повышающими преобразователями, созданными на основе чипа повышающего преобразователя XR2203. Учтите, что источник питания 16 В должен трудиться намного усерднее, чем источник питания 9 В; картридж потребляет от 9 В всего несколько миллиампер. Два повышающих преобразователя созданы на одном чипе просто потому, что мне достаточно было купить для обоих один тип компонентов.

Так как всё устройство питается от литий-ионной ячейки, нам нужно как-то заряжать и её. У меня осталось немного места, поэтому я добавил зарядное устройство литий-ионных аккумуляторов на основе TP4056, чтобы можно было подзаряжать аккумулятор от любого USB-источника питания.


Интеллектуальность устройства обеспечивается модулем ESP-Wrover32. Я использовал вариант с 8 МиБ флеш-памяти и 8 МиБ ОЗУ SPI; вполне достаточно для выполнения сложной обработки изображений. Ещё у модуля есть 5-контактный разъём, позволяющий программировать и отлаживать прошивку, а также две кнопки, которые можно использовать для выбора опций и запуска отрисовки при работающей прошивке.


Выбранные опции отображаются на небольшом цветном ЖК-экране размером 160x80. Экран имеет соединение SPI и может напрямую управляться одним из периферийных SPI-разъёмов, имеющихся в ESP32.


Это интерфейс картриджа. Как сказано выше, он не особо сложен. Уровень всех сигналов преобразуется парой MC14504, один для сигналов 9 В и один для сигналов 16 В. Также на схеме видна схема сдвига уровня/защиты, управляющая двойными шинами питания.




Вот три использованных мной типа датчиков. Все они подключены с помощью одной шины I2C, то есть в ESP32 они занимают всего два GPIO. Это блок инерциальных датчиков MPU9250 (акселерометр, гироскоп и цифровой компас) для измерения движения, три лазерных датчика расстояния VL53L0X (показан только один), направленные вверх, влево и вправо. Идея заключается в том, что комбинируя эту информацию, теоретически можно определить абсолютное положение картриджа. Это полезно, например, при рисовании больших изображений свободным движением руки. Последний — это цветовой датчик TCS3472. Цветовой датчик расположен рядом с белым светодиодом; его можно использовать для «копирования» цвета с объекта или для компенсации цвета носителя, на котором мы печатаем.


Так как мне нужны были дополнительные GPIO, я подключил к шине расширитель GPIO. Он контролирует шины сброса для трёх датчиков расстояния, шину сброса для ЖК-экрана, включение повышающего преобразователя и два МОП-транзистора (не показаны), которые управляют белым светодиодом, используемым для освещения цели для цветового датчика, и подсветку ЖК-экрана. Датчикам расстояния нужна отдельная шина сброса, потому что они включатся по тому же I2C-адресу. Однако у них есть команда, изменяющая I2C-адрес после включения. Включая и перемещая их один за другим по разным I2C-адресам, я могу контролировать все три по одной I2C-шине.


Вот печатная плата, которую я спроектировал на основе схемы. Она имеет странную форму, потому что должна быть разделена на четыре отдельные платы и «окружить» картридж принтера. Они соединены электрически и физически; преимущество этого в том, что производители печатных плат не считают такую схему четырьмя отдельными платами и платить нужно только за одну.


Ещё одно преимущество в том, что я могу собирать плату как один элемент, а затем протестировать её, когда все компоненты находятся на одной плоскости. Это позволяет мне не заниматься тщательной балансировкой собранного устройства при отладке. Небольшое примечание: датчики VL53L0X используют инфракрасный лазерный луч; похоже, он достаточно силён, чтобы пробить фильтр защиты от ИК-излучения в моей «зеркалке» и проявляется в кадре как небольшие фиолетовые пятна света.


И вот каким будет конечный результат после сборки. Заметьте, что при разделении плат соединения между ними оказались разорванными. У плат есть небольшие площадки для пайки, к которым можно припаять небольшой кусок провода и загнуть его. Очевидно, что для производственного уровня нужно будет использовать технологии наподобие FPC PCB или flex-rigid PCB, но для дешёвого прототипа это вполне сойдёт.

Если вы хотите использовать этот прототип для справки или поэкспериментировать с ним, то можете скачать файлы проекта KiCad (там же лежат схема в pdf и gerber) и собрать его самостоятельно, или использовать его подсистемы.

Так как это прототип, ПО довольно… неоднородно. Я дам ссылку на репозиторий, в котором его разрабатывал, но учтите, что это слепок почти всего цикла разработки, поэтому в нём содержится всё по порядку, от записей сигналов логическим анализатором до распечатанных Nyancat и Моны Лизы. К сожалению, поэтому код представляет собой почти недокументированный хаос с наполовину завершёнными путями и остатками старого кода. Если вы всё ещё хотите изучить его, то можете склонировать в git этот этот URL.

Однако если вас больше интересует ПО, способное с лёгкостью управлять картриджем принтера с помощью ESP32 (и содержащее полезные процедуры для управления им через другой микроконтроллер), то продолжайте чтение.

Минимальная работающая версия


Чтобы упростить для других умельцев использование принтерных картриджей в их собственных проектах, я также создал минимальную работающую версию драйвера. В нём отсутствует поддержка всей периферии и хаки из кода прототипа, но архитектура подчищена и поэтому может стать прочным фундаментом для дальнейшего развития. В драйвере есть простой пример программы, печатающей при нажатии кнопки «HELLO!» цветным или чёрным картриджем.

Я не создал для него специализированного оборудования, но по сути вы можете заново использовать «железо» из предыдущего раздела: просто возьмите источник питания, ESP32
и преобразователи уровней и примените их в собственной схеме. Также можно полностью использовать описанный в предыдущем разделе прототип: достаточно просто обеспечить постоянный высокий сигнал BOOST_EN, чтобы повышающие преобразователи 9 В/16 В были всегда включены. (Таким образом я отлаживал код.)

Сам код можно найти на Github, он структурирован стандартно для проекта ESP-IDF. Основной код драйвера находится в components/printcart; код, считывающий кнопку и решающий, когда включать сопло, а также код инициализации содержится в main/main.c. В примере данные сопел считываются из встроенного rgb-изображения.

Система имеет следующую архитектуру: printcart_i2s.c содержит простой драйвер для параллельного режима периферийных разъёмов I2S контроллера ESP32. Он выделяет два буфера и передаёт из буферов 16-битные слова с частотой 3,3 МГц контактам GPIO (максимум 16 контактам). (Здесь эти контакты GPIO соединены с преобразователями уровней, управляющими картриджем.) При каждом опустошении буфера драйвер выполняет обработчик события для заполнения буфера.

Обработчик события находится в printcart_buffer_filler.c. Он получает данные сопел из очереди данных сопел и передаёт их в функцию в printcart_genwaveform.c, которая по шаблону преобразует эти данные сопел в сигналы. Шаблон зависит от типа картриджа (цветной или чёрный), и его можно изменять, загружая в браузер tools/waveform_editor.html.

С другой стороны очереди данных сопел находится процедура цикла в main.c. Она ожидает нажатия кнопки, и при нажатии генерирует данные сопел парсингом простого файла изображения, преобразованного в сырые данные rgb и встроенного в прошитый двоичный файл, сканируя данные слева направо. Благодаря этому можно нажать кнопку, проводя картриджем над бумагой, и распечатать содержимое изображения в виде полосы чернил.

Конечный результат выглядит примерно так:


Тут сильно заметно, что чёрный картридж печатает примерно в два раза больше по высоте, чем цветной (0,7 см и 1,5 см), поэтому если вам не нужен цвет и требуется хорошая видимость, то лучше выбирать чёрный картридж. Также стоит заметить, что в main.c есть define, переключающийся между двумя картриджами; код может работать с обоими. Не совсем понятно, почему на чёрном изображении есть смазанные линии: возможно, в моём сигнале есть ошибка, а может быть, картридж немного устал от тестирования. Как бы то ни было, распечатанные данные красивы и хорошо узнаваемы.

В заключение


Реверс-инжиниринг этих картриджей принтера был долгим приключением, но в конце концов моя работа оказалась плодотворной; хоть и осталось несколько загадок (например: что делает контакт ID?), я считаю, что хорошо разобрался с загадками сигналов, используемых в картридже. Надеюсь, что опубликовав код и схемы этого проекта, я добавлю в инструментарий умельцев, хакеров и творцов использование принтерных картриджей. Не могу дождаться, когда увижу интересные примеры использования, которые придумает сообщество. Если вам удастся сделать что-то интересное с моей работой, то обязательно пришлите мне сообщение.

Что же касается моего намерения творить искусство… эммм… вот это можно так назвать?

Currently unrated

Recent Posts

Archive

2019
2018
2017
2016
2015
2014

Categories

Authors

Feeds

RSS / Atom

Powered by Mezzanine and Django | Theme by Bootstrap | Яндекс.Метрика