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

Избранное

ИИ: умрёт ли профессия программиста

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

И дело не в наивном оптимизме. Дело в механике развития технологий.

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

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

В моём детстве я писал первые команды прямо в машинных кодах — шестнадцатеричными цифрами (!) — в тетрадке, отлаживая их в уме. Потом ждал, иногда целыми днями, когда смогу ввести их в компьютер, набирая прямо из тетрадки. Получив какую-нибудь ошибку, дома писал новую версию.

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

Потом пришли ассемблеры. Потом компиляторы. Потом высокоуровневые языки. Потом фреймворки. Потом облака. И всё заверте…

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

Мы больше не программируем в машинных кодах. Очень мало кто пишет даже на ассемблере и даже Си многие считают чем-то очень далёким, почти устаревшим. Теперь «компьютерная смерть с косой» пришла за Пайтоном, Гоу, Растом и всем остальным, что многим так дорого. Будем описывать, что надо сделать компьютеру, на естественном языке.

И что именно из этого следует?

Если нейросеть способна переводить текст в код, это значит, что исчезает этап механической трансляции. Но разработка программного обеспечения никогда не сводилась к набору текста.

Я специально нашёл слайд презентации, которая с моим участием готовилась для президента нашей республики в 2021 году. Схема упрощённая; сегодня я добавил бы туда ещё пару-тройку прямоугольников и несколько циклов. Но даже здесь видно, что собственно разработка — перевод требований в программный код — это только один из многих этапов разработки программного обеспечения.

Нейросеть может помочь почти на каждом этапе. Но помощь и замещение — разные вещи.

Разработчик высокого уровня даже сейчас способен закрыть большинство, а то и все (разве что насчёт ЮИкса у меня есть сомнения), этапы самостоятельно. Почитайте, например, историю известнейшей игры «Принц Перси» — её создал один разработчик, пройдя все без исключения этапы, включая дизайн.

Важно не то, что он был один. Важно то, что ему пришлось проявить себя во множестве ипостасей.

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

Автоматизация всегда убирает уровень ниже. Программисты просто поднимаются выше.

Когда-то основной ценностью было умение правильно жонглировать регистрами процессора. Потом — правильно написать алгоритм. Потом — построить архитектуру. Сегодня — понять, какую систему вообще нужно строить и как она впишется в бизнес и мир.

ИИ не отменяет сложность. Он лишь сдвигает её на другой уровень абстракции.

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

Локальные адреса в «Веб-архиве»

Я тут благодаря «Виоле» обнаружил кое-что интересное в «Веб-архиве».

В моей версии этого браузера я делал логику, согласно которой, если домен не открывается, то я пытаюсь найти и открыть его самую раннюю сохранённую копию в «Веб-архиве».

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

Я не учёл, что локальные адреса — localhost, 127.0.0.1 и прочие — не должны искаться в «Веб-архиве», ведь из интернета их не видно. Вчера случайно я запустил «Виолу» с URL http://localhost/, и вдруг у меня начал открываться какой-то сайт на японском.

Оказалось, «Веб-архив» хранит зеркала каких-то случайных сайтов, доступных по локальным адресам и портам бог знает каких сетей. Я навскидку посмотрел несколько адресов — 127.0.0.1:8080, 192.168.0.1 и так далее — и обнаружил около десятка разных сайтов. И это только вершина айсберга!

Поскольку снапшоты за разное время в «Веб-архив» попали из разных источников, по одному и тому же адресу в таймлайне «Веб-архива» лежат копии разных сайтов. Хорошо бы их найти все и выкачать — это, судя по всему, какой-то совершенно новый пласт информации, сохранённый там!

Попробовать что ли сканер написать, который составит список всего этого богатства…

«Виола»: предок VRML

Недавно завершил в «Виоле» большую работу: реализацию раннего черновика стандарта VRML. VRML когда-то широко использовался в вебе для создания трёхмерных игр, да и просто для того, чтобы рассматривать с разных сторон какие-либо объекты в объёме.

Началось всё с того, что я заметил в браузере едва начатую реализацию тегов, помеченную комментариями как /* vr exp */. В исходном коде нашлась целая группа таких тегов. Назначение некоторых из них, например OVAL или LINE, было вполне очевидным, тогда как то, что в точности могли бы делать некоторые другие теги, например ACTION или BUTTON, было не вполне ясно.

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

Шло время, и вдруг, копаясь в каталогах старого сайта, посвящённого «Виоле», я неожиданно нашёл черновик письма, в котором автор «Виолы» описывал своё видение того, как должен выглядеть VRML.

Готовая реализация графики, которая сейчас работает в браузере

Там раскрывалось значение всех ключевых тегов из вышеуказанной группы, их атрибутов, а также интерактивная часть — причём в двух вариантах: декларативном (через теги) и скриптовом (через язык «Виолы»).

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

Вот, например, как на этом языке рисуется синий квадрат с тёмно-синим бордюром на светло-сером фоне в координатах x=10, y=20, повёрнутый на 45°:

<GRAPHICS WIDTH=400 HEIGHT=120>
<BGCOLOR NAME="lightgray"></BGCOLOR>
<RECT ID="rect1">
<POS X=10 Y=20></POS>
<SIZE X=70 Y=70></SIZE>
<FGCOLOR NAME="blue"></FGCOLOR>
<BDCOLOR NAME="navy"></BDCOLOR>
<ROT Z=45>
</RECT>

Особенно меня почему-то зацепил атрибут SC о роли которого я бы никогда самостоятельно не догадался. Автор описывал его так:

The SC attribute says that whenever the attributes in this object changes, relay the change to a server that broadcasts the change to all other browsers looking at this object... Have to think about this more...

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

В итоге эту часть я сначала пытался сделать через маковский сервис «Бонжур», но позже переделал на мультикастовый UDP — так работало гораздо быстрее и надёжнее.

Активные объекты, содержащие атрибут SC рассылают свои изменения по локальной сети

Поскольку я тестировал у себя на ноутбуке, запуская два экземпляра браузера, столкнулся и с другой проблемой — стоило убрать курсор с одного из окон, и оно переставало перерисовываться. Оказалось, это особенность оконного фреймворка, на котором построено приложение: так сделано для экономии процессорного времени.

Пришлось делать специальный таймер, который будит приложение, если ему адресованы интерактивные UDP-пакеты.

Работу я разбил на три части: реализацию графических примитивов, реализацию интерактивного взаимодействия и сетевое взаимодействие.

На всё ушло несколько дней интенсивной работы с нейросетью «Опус 4.5». Пришлось даже немного переделать парсер тегов внутри браузера. Несмотря на то, что работа двигалась трудно, отчаяния я не испытывал — было видно, что при работе в паре с «Опусом» эта задача вполне мне по силам.

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

Во-первых, она, при наличии скриптового языка, избыточна, во-вторых, в коде браузера видно, что автор её реализовывать и не собирался.

Пример с узорами, нарисованный при помощи реализованных графических примитивов

Обратная разработка GIFLITE.EXE

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

Когда-то давно, когда я активно верстал, формат GIF был одним из самых ходовых, для анимации так вообще альтернатив не было. И мы в то время в обязательном порядке занимались оптимизацией графики.

В случае GIF очень хорошо помогала известная утилита GIFLITE.EXE — коммерческая разработка компании «Вайт Ривер Софтвейр» (White River Software), которая, по всей видимости, давно исчезла, так как я про неё ни в какой другой связи никогда ничего не слышал.

Утилита была под DOS, но я тогда работал под «Виндой» и проблем это не создавало, но позже, когда я пересел на «Мак», пользоваться ей стало неудобно. Тем не менее я всё равно ей ещё долго пользовался через всякие эмуляторы.

Она всегда меня интриговала — было интересно что она вообще такое делает, как ей удаётся уменьшить размер гифа и чем отличаются её методы сжатия, которые задаются ключом -m.

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

Забегая вперёд, хочу сказать, что эксперимент удался — программа создаёт в точности такие же GIF-файлы во всех режимах и я, кстати, получил ответ на свой вопрос — бо́льшая часть методов в ней объединяет близкие цвета, уменьшая файл за счёт этого.

А теперь, немного подробностей.

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

Opus 4.5 показался смелым исследователем, который идёт к цели, не пасует перед проблемами. Если где-то что-то непонятно, выскажет несколько гипотез, сам их проверит, докопается до истины. Выше всяких похвал.

GPT-5.1 Codex Max показался немного медлительным и чуть туповатым парнем, таким неповоротливым увальнем сибирских размеров, старательным, но звёзд с неба не хватающим.

Grok Code — торопыга, который как будто считает себя чересчур способным, много фантазирует, принимая свои фантазии за реальность и вообще слишком некритично, без рассуждений всё воспринимающий.

Во-вторых, я хоть и написал на «Гитхабе», что делал обратную разработку методом «чёрного ящика», на деле пришлось активно смотреть в исходники.

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

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

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

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

В полным соответствии с принципом Парето, 20% кода отняло у меня 80% времени. Тут очень хорошо показал себя Opus 4.5, — поскольку в коде разобраться было сложно, там 40 тысяч строк на ассемблере, он ставил очень много эксприментов, сравнивая два набора файлов между собой — тот, который получался при запуске оригинального GIFLITE.EXE с нашим.

Мы долго не могли добиться бинарной точности результирующих файлов — очень много нюансов, которые влияли на то, что получалось. Вплоть до реализации алгоритма сортировки цветов, функции хеширования и прочих мелких деталей. Восстанавливать детали помог ассемблерный код — в Си некоторые подробности не перенеслись, отчасти из-за таблицы виртуальных функций, которую «Гидра» (r2ghidra) расщёлкать не смогла.

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

Я очень доволен тем, как прошёл эксперимент. Очень интересный опыт и результаты воодушевляющие. Код, как обычно, можно увидеть на «Гитхабе».

«Виола» и моя мечта: как ИИ снова мне помог

Вступление

Я, как вы знаете, довольно давно уже реставрирую браузер «Виола» из недописанных исходников. И была у одна мечта, связанная с ним: увидеть как в нём работает вращение трёхмерной модели самолёта.

Узнал я об этом из статей о судебной тяжбе компаний «Микрософт» и «Иолас» (Eolas), начавшейся в 1999-м году.

Компания «Иолас» утверждала, что первой разработала и внедрила технологию «встроенных объектов и плагинов» для веб-браузеров, и «Микрософт», по их мнению, нарушала права, используя схожий механизм. В этой связи автора «Виолы» вызывали в суд, где рассказал, что придумал эту технологию ещё в начале 90-х годов, тогда как «Иолас» получила на неё патент только в 1998-м.

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

Скриншот того как это выглядело в первой половине 1990-х

Что мешало

Но оказалось, что исполнению моей мечты мешало несколько обстоятельств.

Во-первых, на самом деле модель вращала утилита V-Plot, написанная Скоттом Силви, который учился вместе с автором «Виолы». Её исходники не сохранились.

Во-вторых, судя по сохранившимся исходникам веб-страницы, вращались две модели, которые назывались TomCat и x29.geom, которые ещё нужно было найти.

В-третьих, как оказалось, часть, которая должна взаимодейстовать с V-Plot не работала.

Вопрос №1: где взять V-Plot?

По всей видимости, в открытых источниках его не найти — сколько не запускал я невод глубокого поиска нейросетями, ничего не вышло. Тогда я решил пойти от обратного — у нас есть скрипт на «Виоле», который должен слать этой программе какие-то команды, так может нейросеть, отталкиваясь от них, мне её просто напишет?

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

Оказалось, что специальный «объект» TTY «Виолы» для взаимодействия с программами, которые могут выводить графику в окно браузера, реализован только для «Линукса», а для «МакОСи» (в «Виоле» встречаются куски для очень старой версии этой операционной системы) код реализован не был.

Я как можно тщательнее, как зловредному джину, описал что именно хочу получить и опять переключился на свои дела. И вот тут, когда я без особой надежды вернулся через какое-то время посмотреть на то как нейросеть провалила задачу, меня ждало маленькое чудо: в окне, где должны выводиться модели, появилась жёлтая сетка — самодельный V-Plot делал что-то полезное!

Сетка — признак того, что взаимодействие с V-Plot работает!

Здо́рово! Но где же мои самолётики?

Настал момент узнать откуда же брались самолёты. Оказалось, что «Виола» передаёт на вход V-Plot одну из моделей, которые выберет пользователь — там на выбор несколько графиков и две модели в формате OFF (Object File Format). Моделей в комплекте с исходниками браузера не оказалось.

Ориентируясь на приметное имя x29.geom, я решил поискать эту модель, вдруг это что-то известное. А параллельно зарядил ChatGPT глубоким поиском.

Модель действительно оказалось известной — её когда-то изготовила компания «Эванс энд Сазерлэнд», а потом использовали на европейской выставке 1987 года, электронные материалы которой каким-то чудом уцелели и доступны для скачивания.

ChatGPT оказался полезен тем, что правильно идентифицировал модель и рассказал её историю, но сам файл нашёлся банальным поиском по интернету.

Дальше нейросети меня опять удивили — посмотрев на мой найденный файл, сеть для программирования «Опус 4.5», не моргнув глазом, написала мне за каких-то несколько десятков секунд код для парсинга и отображения этого формата. И вот я уже вращал свой первый самолёт!

Браузер «Виола», вращающий модель самолёта Grumman X-29 в трёх измерениях

Отлично! А что со второй моделью?

Со второй моделью так гладко не вышло — как я ни старался, ничего путного по слову TomCat на нашёл. Решил смириться и найти хоть какую-нибудь модель того же самолёта — ChatGPT определила, что на картинке нарисован Grumman F-14 Tomcat.

Тут наконец пригодился глубокий поиск — нашёлся архив внутри которого лежала модель самолёта F-14, но, вот неприятность, в формате IOB (Imagine object). Формат давно мёртвый и единственный конвертор, который я нашёл — бинарный файл под операционную систему «Амига».

Я, было загрустил, но тут решил попробовать уже совсем безумную штуку — натурально попросить нейросеть написать мне конвертор из формата IOB в OFF, причём без описания самих форматов. Самое смешное, что это сработало, причём с первого раза! Получившаяся модель сразу появилась в окне и заработала!

Модель Grumman F-14 Tomcat, сконвертированная из формата IOB

Выводы, или Что меня удивило

Лёгкость к которой нейросеть провела обратную разработку команд, написала интерпретатор команд для V-Plot и конвертор, просто поражает! Честно сказать, я на такое совсем не надеялся. Максимум, который я ожидал — полуживой прототип, который придётся отлаживать не один день.

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

Тем не менее, та работа, которую я проделал над браузером при помощи нейросетей, совершенно неподъёмна для человека в такие короткие сроки.

Первая BBS в Казани

Около полугода назад я заинтересовался темой появления казанских BBS — это системы электронных доски объявлений, которые были распространены до эпохи интернета. В одном из источников, которые я использовал для исследования, всплыло указание на первое казанское объявление в газете «Вечерняя Казань», которое рекламировала первую казанскую BBS.

Доска объявлений называлась «ORPHAN’S BBS». Модерировали её Амир Шабашвили, с которым я когда-то был знаком, и Марат Якубов. Последний и дал объявление в газету за космические 130 рублей, переплатив за срочность и пятничный номер.

Поискав по казанским фидошникам фотографию, скан или вырезку из газеты с этим объявлением, я успеха не достиг — ни у кого искомого не обнаружилось. Поставив себе задачу в список «когда-нибудь» разыскать архивы «Вечерней Казани» и поискать в ней объявление, я занялся другими делами.

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

Недавно я выделил время и сходил-таки в библиотеку. Завёл читательский билет и засел за чтение подшивок. Из найденного источника мне было известно, что объявление опубликовано в весной или летом 1992 или 1993-го года в разделе частных объявлений.

Нашёл не без труда, объявление совсем крошечное. Латинского шрифта в газете в те времена ещё не было, поэтому BBS написали как ВВС:

Владельцы модемов! Информацию о первой в Казани ФИДО-ВВС Вы можете получить по тел. 76-85-59.

Объявление было опубликовано 7 августа 1992 года

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

Ненормальное программирование

Введение

Недавно разговорился с одним приятелем, тема разговора как-то мало-помалу сместилась в программирование. Оказалось, он давно читает мой блог и удивляется почему я, по его словам, «в последнее время увлёкся совершенно непрактичным программированием».

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

Более нормальным программированием я тоже занимаюсь, но чаще всего это работа или какая-то рутинная необходимость. В этом посте я хочу рассказать о нескольких моих проектах, которые, как я думаю, попадают под определение ненормального программирования. Проектах, которые создавались без цели как-то их напрямую использовать, так сказать, по зову души.

«Junix» (1999—2003)

Это самый старый из сохранившихся подобных проектов. И, наверное, самый монументальный. Дело было в конце 90-х, тогда ДжаваСкрипт мало кто воспринимал всерьёз. В основном его использовали для какого-нибудь простенького интерактива или, максимум, относительно несложных игр, типа «Тетриса».

Мне же было очевидно, что ДжаваСкрипт уже можно использовать для большего. Я так был уверен в своей идее, что был готов продемонстрировать её всему миру. Проект занял несколько лет — в начальной фазе я занимался им каждый вечер на протяжении нескольких месяцев, а потом изредка реализовывал какие-то идеи. Наверное это очень долго, но с документацией тогда было негусто, кроме того в каких-то вещах я был первопроходцем.

Так у меня получилось что-то вроде эмулятора командной строки «Линукса». Это был первый такой проект в мире и о нём написали все топовые интернетные издания того времени. Я реализовал интерпретатор, похожий на tcsh, несколько утилит и аналог терминала с доступом к файловой системе.

«JS-FTPd» (2001)

В то время, когда я делал этот проект, ДжаваСкрипт ещё не был монополистом в мире браузерных языков. Существовало несколько альтернативных технологий, так, например, в браузерах была технология «апплетов», позволявших писать небольшие встраиваемые в браузер приложения на языке Джава.

В то же время в браузере «Нетскейп» была нестандартная технология «LiveConnect», которая позволяла вызывать Джаву из ДжаваСкрипта, а так же запрашивать из браузера различные разрешения, например, на сетевое взаимодействие. Впервые я познакомился с этой технологией, когда писал «Junix», там я через неё работал с диском компьютера, а в этом проекте мне захотелось изучить работу с сокетами.

Используя «LiveConnect» я написал FTP-сервер — на ДжаваСкрипте, вызывая Джаву там, где ДжаваСкрипт что-то не умел. Заодно детально разобрался как устроен протокол FTP, что потом часто пригождалось.

«Крестики-нолики» на HTML и CSS (2011)

Тема игр для компьютера без программирования меня давно интересовала.Я написал их несколько. В основном, с использованием HTML и CSS. Ни тот ни другой языками программирования не считаются, тем не менее, развились настолько, что на них можно писать очень сложные интерактивные вещи.

«Крестики-нолики» один из таких проектов, где я экспериментировал с тем, что можно сделать, не прибегая к более традиционным методам создания игр в браузере.

«Арканоид» на bash (2011)

В рамках этой игры я хотел испытать две концепции.

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

Во-вторых, я задумал сделать игру со звуком. Для этого у меня использовался встроенный в «МакОС» синтез голоса через команду say. Манипулируя скоростью и подбирая разные смешные голоса, мне удалось сделать несколько уместных, как мне кажется, звуковых эффектов.

«Шахматы» на языке утилиты sed (2013)

Когда я решил написать шахматы на sed, знакомые, с которыми я поделился своей идеей, подумали, что я сошёл с ума. Ну а как иначе? sed — в их глазах не язык программирования, а текстовый редактор, который умеет менять «кота» на «собаку» в конфигах.

Но мне хотелось доказать, что даже в таком примитиве можно выжать больше, чем кажется. В итоге я провёл две недели в диалоге с регулярными выражениями: заставлял их считать, сравнивать числа в придуманном мной формате 111::11 (так в нём записывается число 302) и имитировать логику шахматного ИИ. Каждый день я порывался бросить: когда код превращался в лабиринт из меток и переходов, а функция вычитания занимала 59 строк, но упрямство перевешивало.

Как я уже сказал, большая часть логики сделана на регулярных выражениях, поверх которых я написал мета-язык, на котором уже и писал шахматы, благо в sed есть способ переиспользования кода. Было очень тяжело, но мне так нравилась идея, что я справился. Это был настолько сложный проект, что его выпуск породил волну публикаций по всему интернету. Информационный гул заметили даже «Гугле» и пригласили на собеседование, но я отказался.

«Тетрис» на языке AppleScript (2017)

Встроенный в «МакОс» язык автоматизации «ЭплСкрипт», кажется, никто никогда для написания игр использовать и не пытался. По крайней мере, я таких попыток не обнаружил. И немудрено — сходу неясно чем бы он мог таким оперировать, чтобы взаимодействовать с пользователем.

Я написал «Тетрис» на нём, когда понял, что графику можно выводить, манипулируя свёрнутыми в точку окнами приложений и опрашивая клавиши регулирования громкости.

«Морской бой» на клавише «Капслок» (2020)

Игру «Морской бой» я написал по двум причинам. Во-первых, у меня была идея написать какую-нибудь игру, для которой нужно было использовать только одну клавишу. Во-вторых, мне хотелось посмотреть в действии язык «Луа».

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

В итоге я написал игру, где всё взаимодействие с компьютером делается через азбуку Морзе — пользуясь одной клавишей, как ключом, мы вводим координаты для игры в «Морской бой», а ответы компьютера считываем через мигание светодиода на «Капслоке». Картинка ниже — это отладочный режим, его можно включить, но по-умолчанию на экран ничего не выводится.

«Вампус» для наручных часов в корпусе «Касио» (2024)

Я вообще очень люблю различные ретро-устройства, а так же всё, что их напоминает — постоянно читаю о ретро-консолях, подписан на каналы, где обозревают интересные устройства прошлого, и когда узнал про «The Sensor Watch», небольшую плату, превращающую классические «Касио» в программируемое устройство, влюбился в эту концепцию и добыл себе всё необходимое.

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

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

«Вампус» на командах командной строки (2024)

Была у меня ещё одна идея — сделать что-то такое, что превратило бы в игру саму оболочку командной строки (шелл). Тогда полем для игры была бы файловая система, а её командами были бы команды шелла. Для реализации выбрал тот же «Вампус», старые текстовые игрушки как нельзя лучше подходят для таких целей.

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

«PowerShoot» игра, управляемая подключением зарядки (2024)

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

На искомую идею меня натолкнул звук, который раздаётся, когда «Макбук» подключается к зарядке. Я задумался, что можно же программно узнать — заряжается ноутбук или нет, а потом уже, от скуки, развил эту мысль до небольшой игрушки. В ней игрок выпускает в сторону врагов бомбу, когда ноутбук подключается к зарядке.

«Дум» на языке калькулятора bc (2025)

Концепция вывода графики в текстовую консоль существует давно — в различных терминалах было последовательно придумано несколько способов как это сделать, что меня весьма интриговало. Хотя и понятно, что терминалы нынче никакие не текстовые, всё равно графика там поначалу как-то изумляет.

Во мне идея сделать что-то графическое в терминале зрела много лет и, когда я стал изучать язык утилиты bc, мне пришла в голову идея суточного хакатона — сделать на этом совершенно непригодном для написания игр языке, первую игру, да не простую, а трёхмерную, с выводом графики в консоль.

Хотя первые несколько часов хакатона я был в отчаянии от своей идеи и мне казалось, что я либо ничего не сделаю, либо не уложусь в срок, у меня всё получилось — за сутки я сделал порт игры «Wolf5k» на bc и придумал как на этом языке генерировать графику. А заодно доказал, что кодить сутки с раннего утра и до трёх ночи можно и в 47 лет.

«Throttling» игра, использующая для отображения мониторинг загрузки процессора (2025)

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

Недавно я этот код случайно нашёл и придумал небольшую игрушку. Её несложный сюжет, остающийся за рамками игрового процесса, таков: вы оператор блока реактора на АЭС, у вас отключается автоматика и вам нужно вручную удерживать температуру внутри блока, которая отображается как загрузка процессора.

Заключение

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

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

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

Батарейки CR2032

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

А тут недавно в одном из каналов попалась ссылка на тестрирование батарей CR2032. У меня на картинке лишь вершина айсберга, загляните сами — разница между лидером и аутсайдером в 11 раз! Что, кстати, неплохо укладывается в мои ощущения в год и месяц работы.

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

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

7000 и кафе

Формально эта заметка — семитысячная на этом сайте. Формально, потому что некоторые посты я пишу задним числом, копируя их из «Дневников жизни», которые я вёл с 1989 года по 2000-й. Там работа даже не близка к завершению, так что, очевидно, в будущем нумерация поменяется.

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

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

Честно говоря, я планировал выбрать первый вариант, но вчера случилось событие о котором невозможно молчать, — мы с ещё двумя друзьями подписали договор, условия которого обсуждали почти месяц. В скором времени мы будем открывать кафе, даже два — одну точку в виде киоска недалеко от одной из центральных улиц Казани и ещё одну на фудкорте строящегося торгового центра.

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

Прошлое: Дни Интернета в Казани

Вчера встретил в кафе нашего офисного центра своего друга А. Х., который общался о чём-то за столиком с тремя молоденькими девушками. Он махнул мне рукой, я подошёл поздороваться и оказалось, что эти трое — журналистки, собирающие воспоминания о том как развивалась отрасль айти в девяностых и двухтысячных.

А. Х. попросил меня помочь, но сначала мне пришлось отказаться — меня ждали на встрече. Позже выяснилось, что встречу передвинули и у меня есть минут 15—20, чтобы спринтом пробежаться по памяти и чем-нибудь поделиться.

События очень давние, поэтому вспомнить удалось не так много как хотелось бы, но зато в памяти всплыл один забавный случай, про который я нигде не писал. Журналисткам он не подошёл по тематике, поделюсь здесь.

В конце девяностых—начале двухтысячных в Казани проводились Дни Интернета. Событие, насколько я помню, должно было стать ежегодным, но не стало. Его провели не менее двух раз и в какой-то момент оно благополучно загнулось.

В интернете об этом упоминаний не сохранилось, но кое-что можно наковырять в веб-архиве, в частности на сайте передачи «Система 104».

Я был на двух «Днях». Один из них проводил на свои деньги известный тогда в казанском интернете деятель Daddy Hab, а второй, если мне не изменяет память, провайдер «Сантел-интернет», ныне несуществующий. Но может и не он.

Кажется оба раза это было в зале НКЦ «Казань», но что там конкретно было, я уже и не помню. Вероятно, просто тусовка с алкоголем. Но что я помню хорошо, что перед одним из этих событий в качестве приглашённого гостя был анонсирован Артемий Лебедев, в те годы — абсолютная суперзвезда в интернете.

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

Как пошутил А. Х., я делился файлами через облако до того как это стало модным.

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

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

К сожалению, чуда не случилось. В итоге в какой-то момент объявили, что он не приедет — якобы очень извиняется, застрял в метро и не успел на самолёт.

cmd.sh

Я тут случайно в спор ввязался — можно ли переписать бат-файл так, чтобы он запускался и выводил примерно одинаковый результат на трёх основных операционных системах — Виндоузе, Линуксе и МакОСи.

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

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

Что ж. Основная моя идея была в том, чтобы заменить команды батника на вызовы баш-функций, которые я спрячу в специальных конструкциях. В Виндоузе файл обработает обычный cmd.exe, на остальных операционках — bash.

То, что мне предстояло адаптировать начиналось вполне стандартно:

@ECHO off
CHCP 1251
CLS

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

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

:; @ECHO() { :;}; CLS() { clear; }; CHCP() { ENC="$1"; }

Следующее, чему надо научиться — выводить текст в указанной в батнике кодировке. Это просто:

:; ECHO.() { echo $@ | iconv -f "CP$ENC"; }

Если теперь сделать файл запускаемым и добавить впереди #!/bin/bash (и пренебречь тем, что cmd.exe успевает ругнуться на эту строку до очистки экрана), у нас получится следующий файл, работающий во всех трёх операционках (кодировка должна быть Windows-1251):

#!/bin/bash
:; @ECHO() { :;}; CLS() { clear; }; CHCP() { ENC="$1"; }
@ECHO off
CHCP 1251
CLS
:; ECHO.() { echo $@ | iconv -f "CP$ENC"; }
ECHO. Всем привет

А вот дальше сложнее. Само меню организовано в оригинале так:

SET /p opt=Введите цифру:

IF %opt%==1 GOTO dns_auto
IF %opt%==2 GOTO dnschange
IF %opt%==3 GOTO exit

В «баше» goto (переход к метке) отсутствует и это проблема. Аналогов тоже нет. Единственное, что тут можно сделать — использовать вызов функций, но синтаксис в «бате» и «баше» сильно различается.

Как быть? Во-первых, сэмулировать функцией команду SET, во-вторвых, упростить это место, чтобы меньше было писать кода на «баше»:

:; SET() { shift; ECHO. -n "${@#*=}"; read -n1 "${1%%=*}"; echo; }
:; CALL() { eval "$(sed 's/%\(.*\)%/$\1/g' <<< "$1")" 2>&-; }

SET /p opt=Введите цифру:
CALL :menu_%opt%

Первая функция парсит команду SET выводит строку после равно, ждёт ввода и записывает значение в имя переменной, указанной слева от равно.

Вторая — заменяет CALL. В ней %variable% заменяется на $variable, выполняется подстановка переменной и получившееся имя выполняется как команда или функция «баша». Конструкция 2>&- нужна, чтобы избежать вывода ошибки в ситуации, если пользователь введёт что-нибудь не то.

Теперь надо как-то научиться определять функции так, чтобы их нормально «видел» и cmd.exe, и «баш». В батнике функции — просто любое место программы, начинающееся с метки и заканчивающееся вызовом GOTO :EOF:

:function_1
ECHO это якобы функция
GOTO :EOF

В «баше» то же самое могло бы выглядеть, например, так:

function_1() {
    echo это функция
}

Как это объединить? Я придумал следующий подход:

:; GOTO() { :; };

GOTO ;#start
:function_1 (){
ECHO. это [якобы] функция
GOTO :EOF
:; }

:;#start

В первой строке определяется пустая функция для «баша», потому что эта часть синтаксиса бат-файла нам не нужна.

Ниже идёт строка GOTO ;#start. С точки зрения «баша» тут две конструкции — GOTO, которая вызывает определённую выше пустую функцию и #start — строка комментария, так как в«баше» с «решётки» начинаются комментарии.

В «батнике» же эта же строка будет означать переход к метке с именем ;#start. Этот переход нужен нам, чтобы «обогнуть» строки, которые определены ниже, иначе cmd.exe начнёт сразу их выполнять, а нам этого не нужно. Их нельзя «спрятать» ниже основной программы, так как в «баше» функции должны определены раньше их вызова.

Что происходит дальше? С точки зрения cmd.exe ниже расположена метка :function_1 (как показывают мои эксперименты, часть после пробела просто отбрасывается), потом тело функции, команда её завершения GOTO :EOF и метка с именем :;}.

С точки зрения «баша» там определяется функция с именем :function_1, ниже идут вызовы уже определённых мною функций ECHO. и GOTO, а ещё ниже — уже знакомая нам пустая команда : и фигурная скобка, завершающая тело функции.

Соединяем всё вместе и получается следующая программа:

#!/bin/bash
:; @ECHO() { :;}; CLS() { clear; }; CHCP() { ENC="$1"; }
@ECHO off
CHCP 1251
CLS

:; GOTO() { :; };
:; ECHO.() { echo $@ | iconv -f "CP$ENC"; }; PAUSE() { read; }; 
:; SET() { shift; ECHO. -n "${@#*=}"; read "${1%%=*}"; }
:; CALL() { eval "$(sed 's/%\(.*\)%/$\1/g' <<< "$1")" 2>&-; }

GOTO ;#start

:menu_1 (){
ECHO. Пункт первый
GOTO :EOF
:; }

:menu_2 (){
ECHO. Пункт второй
GOTO :EOF
:; }

:;#start

SET /p opt=Введите цифру:
CALL :menu_%opt%

Мой оппонент признал, что в споре я победил.

Пишем на «Флиппере Зеро» по-русски

Вкратце: в русским текстом работать можно, но сложно, код лежит на «Гитхабе».

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

Flipper Zero

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

Вывод русских букв (трансляция с экрана через оболочку qFlipper)

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

Внутри «Флиппера» довольно много всякого АПИ для вывода текста, от незатейливого, выводящего строку в заданные координаты, до довольно навороченного, умеющего переносить и выравнивать текст. К сожалению, с русскими буквами оно работать не умеет.

Под капотом у этого АПИ — очень известная в своей нише библиотека U∞g2, у которой по историческим, видимо, причинам есть два набора функций для работы со строками. Одни принимают только однобайтовую кодировку ASCII, другие работают в Юникоде.

АПИ «Флиппера», к сожалению, использует функции, которые с Юникодом работать не умеют. К счастью, по какой-то случайности, упомянутое АПИ содержит два вызова, которые помогают решить эту проблему, правда придётся помучаться.

Первый из них — canvas_set_custom_u8g2_font.

Чтобы что-то написать русскими буквами, нужен шрифт, который их содержит. Стандартный вывод canvas_set_font позволяет выбрать один из нескольких шрифтов, ни одни из которых кириллицу не поддерживает. Тут и приходит на помощь canvas_set_custom_u8g2_font. Он позволяет выбрать произвольный шрифт пакета U∞g2, — внутри их целая куча и некоторые в названии содержат слово «cyrillic».

Вот как я это делаю:

#include <u8g2/u8g2_fonts.c>
// …
canvas_set_custom_u8g2_font(canvas, u8g2_font_haxrcorp4089_t_cyrillic);

Файл u8g2/u8g2_fonts.c внутри себя содержит шрифты в особом формате, можно открыть его прямо в текстовом виде и посмотреть как всё устроено.

Шрифт мы выбрали, теперь надо что-нибудь вывести. Тут на помощь приходит canvas_draw_glyph. «Под капотом» у него лежит u8g2_DrawGlyph, которая понимает символы Юникода почти без танцев с бубном. Думаю, это чистое везение — наверняка эта функция появилась сильно позднее, поэтому у неё нет двух вариантов для работы с разными кодировками.

Плохая новость в том, что строки в коде мы обычно пишем в кодировке UTF-8, а canvas_draw_glyph ожидает их в UCS-2. Но есть и хорошая новость — в прошивке доступно АПИ для перекодирования, как обычно, великолепно документированное на языке Си.

Но canvas_draw_glyph, как можно понять из названия, выводит только один символ. Как же вывести строку? Достаточно просто — надо вывести её посимвольно, сдвигая координату на ширину символа. Звучит просто, но как это сделать?

Тут нас ждёт очередная засада. Дело в том, что canvas_glyph_width, которая должна бы это делать, принимает на вход только char, при том, что нижележащая u8g2_GetGlyphWidth преспокойно работает с Юникодом.

Поэтому я сделал просто — выдрал реализацию u8g2_GetGlyphWidth себе в исходники. В итоге мякотка моего решения выглядит вот так:

void unicode_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, char* str) {
    FuriStringUTF8State state = FuriStringUTF8StateStarting;
    FuriStringUnicodeValue value = 0;

    for(; *str; str++) {
        furi_string_utf8_decode(*str, &state, &value);
        if(state == FuriStringUTF8StateError) furi_crash(NULL);

        if(state == FuriStringUTF8StateStarting) {
            canvas_draw_glyph(canvas, x, y, value);
            x += unicode_GetGlyphWidth(&canvas->fb, value);
        }
    }
}

Тут unicode_GetGlyphWidth — скопированная реализация u8g2_GetGlyphWidth, а furi_string_utf8_decode используется для кодирования UTF-8-строки в последовательные символы UCS-2.

Надпись в «Гитхабе»

С тех пор как в первый раз увидел панель активности «Гитхаба», хочу на ней что-нибудь написать. Я даже всерьёз как-то порывался составить себе карту на год, чтобы по ней коммитить, пока не получится рисунок, но поленился. А позже сообразил, что можно сдвигать дату коммита в прошлое.

Моя панель активности за год на «Гитхабе»

И вот, годы спустя, я наконец сподобился сделать скрипт, чтобы автоматизировать процесс и написать себе там слово «ПРИВЕТ».

Скрипт переводит подготовленную картинку размером 52×7 пискелей в нужную интенсивность коммитов и распределяет их по датам. Для надписи я использовал шрифт silkscreen, русифицированный когда-то Димой Смирновым и чуть-чуть его размыл в графическом редакторе.

Если захотите себе такую же, вам понадобится так же bash, git и утилиты из набора ImageMagick. Создаёте пустой репозиторий на «Гитхабе», привязываете его к локальному, запускаете мою утилиту с картинкой и любуетесь изображением на панели активности.

GBox для Huwaei

Три года назад, пройдя от любви до ненависти к «Самсунгу» один шаг, я перешёл на «Хуавей», рискнув попытаться обойтись без гугловых сервисов. Честно сказать, продержался недолго — пришлось взламывать смартфон и почти сорокаминутным шаманством возвращаться в зону комфорта.

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

Приложение GBox, установленное на моём телефоне; приложения не знают, что они внутри Huawei

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

Я уже давно хотел побаловать себя апгрейдом смартфона, и консультант в магазине, почуяв мои колебания рядом со стендом «Хуавея», мастерски разбил каждый пункт моих сомнений. В том числе показал мне способ как не страдать от отсутствия сервисов «Гугла».

Оказывается существует панацея — приложение GBox. Оно ставится прямо из собственного магазина «Хуавея» и запускает внутри себя любое гугловое приложение (включая «Гугл Плей»), притворяясь для него смартфоном, свободным от санкций. В моём случае это какой-то «Сяоми», но в интернетах пишут, что модель и производитель выбираются случайным образом.

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

Мне такой способ понравился значительно больше — не засоряется система, и приложения, типа «Мир пэя», не сходят с ума от противоестественного симбиоза сервисов «Гугла» и «Хуавея».

О хранении пластинок

У нас дома есть настоящий патефон в хорошем состоянии. Эта вещь когда-то принадлежала дедушке жены и мы регулярно ею пользуемся — ставим пластинки по велению души или по просьбе друзей.

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

Отпечаток одной пластинки на другой — видно отзеркаленную надпись «RUSSIA» и след вокруг «яблока»

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

Некоторые из них меня заинтересовали (там была даже парочка дореволюционных), поэтому я взял их послушать и только дома обнаружил, что за годы хранения стопкой одна из односторонних пластинок испортила дорожки на рабочей стороне другой — там отпечатался рельеф вокруг «яблока» и часть надписи «REPRODUCED IN RUSSIA».

Вывод простой: хранение стопкой портит пластинки, так как под весом стопки одна пластинка может повредить дорожки на другой.

Ранее Ctrl + ↓