Я все таки запилил первый видос, экранизацию одной из прошлых своих статей
Да, где-то запорол звук и видеоряд, но я старался! Пожалуйста, зацените ;)
Да, где-то запорол звук и видеоряд, но я старался! Пожалуйста, зацените ;)
Отвал флэш-памяти типа eMMC - весьма частая болячка смартфонов и планшетов, которая массово преследует современные девайсы на протяжении вот уже более 10 лет. Симптомы проблемы знакомы многим читателям: смартфон виснет на заставке, системные приложения регулярно вылетают, или настройки системы внезапно перестают сохраняться. Сам процесс замены флэш-памяти требует навыков перекатки и пайки BGA-чипов, оборудования (трафареты для реболла, программатор с колодками, опционально подогрев) и понимания того, как работает загрузчик той или иной аппаратной платформы, поэтому в СЦ за эту процедуру могут взять достаточно большую сумму. На некоторых девайсах менять память уже совсем невыгодно, особенно когда другой такой-же аппарат стоит полторы тысячи рублей на барахолке, но воспоминания о любимом девайсе порой гораздо дороже, чем сумма за ремонт смартфона. Год назад я уже писал материал о загрузке Android с MicroSD при условии того, что eMMC ещё подает хоть какие-то признаки жизни, а сегодня я вам расскажу о способе загрузить систему с флэшки уже после того, как чип флэш-памяти отказал и ушёл в read-only. Сегодня мы с вами: узнаем о том, какие типы флэш-памяти существуют и причины их отказа, разметим MicroSD-флэшку и запишем на неё образ системы, пропатчим пути монтирования в boot.img, а также узнаем, как теперь запускать наш смартфон и посмотрим, сможет ли он работать достаточно шустро с MicroSD флэшки! Интересно узнать, как вернуть жизнь таким легендам, как Google Nexus? Тогда добро пожаловать под кат!
Как я уже говорил в вводном абзаце, проблема внезапно отваливающейся флэш-памяти существует вот уже более 10 лет. Ещё с выходом iPhone 3Gs/4, мастера познакомились с такой болячкой, как внезапное падение устройства в режим DFU и отказ прошиваться через iTunes. Ближе к выходу Galaxy S III, HTC Desire и Wildfire, LG Nexus возникла потребность в программаторах, поскольку чипы eMMC в этих смартфонах очень часто помирали «сами по себе» из-за косяков производителя флэш-памяти. Более опытная часть моих пользователей может вспомнить такие проблемы, как отказ входа в HSPL (загрузчик HTC), бесконечная загрузка с отказом прошиваться в режиме Odin на самсунгах, падение смартфонов на базе чипсетов Qualcomm в режим 9008 (QHSUSB_BULK), а также внезапное прекращение работоспособности девайса даже при наличии адекватного потребления и реакции на кнопку включения.
В относительно современных смартфонах используется два типа чипов флэш-памяти с разными протоколами: NAND и eMMC (в современных чаще используется UFS — наследник eMMC с дифференциальным протоколом, вместо MMC). Устройства конца 2000х годов чаще использовали флэш-память типа NAND с Legacy-протоколом, который требовал ручного управления SPARE-страницами и расчета кода коррекции ошибок (ECC), чем занималось отдельное периферийное ядро в процессоре, называемое NAND-контроллером. Момент, когда нужно «приговорить» флэш-память и перевести её в режим read-only решал не сам контроллер, а драйвер NAND в прошивке устройства — и обычно он был весьма лоялен даже к «сыпящейся» памяти. Кроме того, NAND-контроллер позволял практически напрямую взаимодействовать с чипом флэш-памяти, благодаря чему в загрузчиках типа U-boot есть команда для очистки таблицы Bad-блоков и низкоуровневого форматирования флэш-памяти, дабы в дальнейшем контроллер попробовал пересчитать бэды и, потенциально, вернул некоторое число блоков обратно в строй. Такой тип «флэшек» помирал значительно реже, в основном из-за того, что софт (на моём опыте) практически никогда не уводил флэшку в read-only, «добивая» её до последнего. Из минусов такого подхода — если флэш помирала совсем, то данные из нее можно было достать только с помощью программатора, да и то не факт.
В моей довольно большой коллекции нет ни одного смартфона с Legacy NAND, где флэш бы действительно «приехала», хотя на форумах мастеров иногда встречаются старые сообщения о замене флэши на телефонах Nokia.
Второй тип памяти появился примерно в начале 2010х годов и имя ему — eMMC. Фактически, eMMC — это адаптация интерфейса MMC для использования в виде обычных чипов памяти, а не карточек, совместимая с спецификацией ~SDHC. Если выпаять чип с телефона и припаять сигнальные линии к обычному SD-кардридеру на ПК — он будет работать и определяться как полноценный диск! Таким образом, на некоторых смартфонах можно заменить eMMC на MicroSD напрямую припаяв флэшку на место чипа к соответствующим сигнальным линиям. Однако работать такое будет только если у вашего смартфона «бутербродная» компоновка, где ОЗУ припаяна поверх процессора (MTK и Spreadtrum в пролете). В eMMC используется память типа NAND, которой управляет не чипсет, а встроенный в сам чип памяти контроллер, работающий с протоколом MMC и имеющий собственную прошивку и карту бэд-блоков. Такая флэш-память может самостоятельно уходить в режим read-only когда это посчитает нужным контроллер, зачастую не давая смартфону загрузится, но при этом потенциально сохраняет данные пользователя и позволяет их прочитать дома (сделав дамп памяти устройства и смонтировав раздел userdata в Linux). Однако всё равно иногда данные теряются безвозвратно. Нюанс в том, что состояние eMMC определяет сам контроллер в чипе — поэтому «оживить» его дома и вывести из read-only невозможно. Однако я слышал, что на некоторых «бракованных» чипах памяти (в основном Samsung 2012-2013 годов), которые ушли в read-only слишком рано, можно подпаяться к тест-поинтам программатором и прошить чуть более свежую прошивку с другой ревизии этого же чипа памяти. Флэшка, бывало, оживала.
В некоторых случаях, eMMC были бракованными с завода и помирали сами по себе (!) через короткое время (около года) после покупки устройства. Я знаю как минимум два примера массового брака флэш-памяти: смартфоны HTC 2011-2012 годов, которые время от времени страдали от валящихся чипов Hynix (это касается не всех устройств, многие дожили), хотя я лично видел не так много HTC'шек с дохлой памятью, так что здесь читатели-сервисники с опытом работы в те годы могут только подтвердить или опровергнуть мои слова. А вот подтвержденный пример — смартфоны и планшеты Samsung 2012-2014 годов. Galaxy S3 с артефактами на дисплее при включении, S4 Mini в 9008 или повисшие на заставке, S4 с теми же симптомами, S4 Zoom, которые практически все померли «сами по себе» после обновления до 4.4 KitKat, N8000… Добавьте к этому слабые NC-пятаки, которые срывает при попытке снять чип феном, близко расположенный «бутербродный» процессор, который легко «убить», если орудовать феном, компаунд… и по итогу многие мастера просто спиливали чип дремелем. А что ещё делать!?
По итогу, нам остаётся искать софтварные способы загрузить систему с внешней MicroSD флэшки. И я нашел два таких способа! Первый — предварительно подготовить образ boot.img и прошить его в смартфон вместо recovery, дабы если память ушла в read-only, мы могли просто «дуалбутнутся» во второй образ с пропатченными точками монтирования системных разделов на MicroSD. А о втором, к сожалению, знают лишь единицы, хотя это просто замечательный способ, который позволяет загрузить систему уже «пост-фактум» после ухода флэшки в read-only и требует некоторых манипуляций с fastboot! Давайте же рассмотрим его подробнее.
Нашим подопытным будет рабочий смартфон Alcatel OT-5020D 2013 года выпуска, который пока не подает признаков помирающей eMMC: к сожалению, смартфонов с полудохлой памятью и разлоченным бутом у меня не оказалось, дохлые флэшки я иногда меняю и сам :) Но тем не менее, грузиться мы в любом случае будем с флэшки и вы сможете повторить все шаги в статье, дабы загрузить систему с MicroSD самому!
Друзья! Для следующих действий, вам понадобится разблокированный загрузчик или устройство, на котором с завода загрузчик не заблокирован. Главный критерий — наличие режима fastboot.
Какие устройства не подойдут: многие смартфоны на базе чипов Spreadtrum, а также часть смартфонов Samsung на Exynos. Ни те, ни другие частенько не имеют режима fastboot от слова совсем. У Samsung есть режим загрузки с MicroSD (т. н. T-Flash Mode), но ядро он не грузит.
Какие устройства подойдут, но требуется подготовка: все смартфоны от Sony (исключение — Xperia Tipo, забагованный fastboot), Google Nexus (некоторые модели страдали из-за отвалов флэши), современные китайские новодельные noname-смартфоны (с вот таким патчем), Xiaomi, Meizu. Чипсеты: MediaTek 67xx/Qualcomm Snapdragon, возможно Kirin. Таким устройствам требуется предварительная разблокировка загрузчика.
Какие устройства подойдут даже при условии уже мертвой флэш-памяти: большинство девайсов на базе чипсетов MediaTek прошлого десятилетия, особенно бюджетных: MT6572, MT6582, MT6592, MT6580, MT6570, MT6575, MT83xx, некоторые Spreadtrum. Это касается Fly, Explay, ZTE и многих других ультрабюджетных смартфонов тех лет. Загрузчик там разблокирован с завода, никакого секьюрбута и верификации загружаемых образов нет. Но не везде можно загрузится в fastboot напрямую (попробуйте громкость вверх и громкость вниз при включении — если сразу грузится в рекавери, то нужно до отказа eMMC включить ADB, если показывает менюшку fastboot, recovery, normal boot — значит все ок).
Не подойдут: MT6573, MT6571 — там U-Boot (но его тоже можно попробовать заставить грузиться с SD).
Список устройств для потенциальной возможности загрузки с SD весьма большой! Как понять, что eMMC «всё»?
Смартфон не реагирует на зарядку и кнопку включения при заряженной АКБ: это не 100% показатель, но если поднимаются питальники с КП и потребление от кнопки есть ~0.1-0.3А — значит процессор вероятно пытается стартовать. Но не откуда. В таком случае, девайс поднять не получится — доступа к fastboot нет, флэшка полностью посыпалась. Исключение — некоторые Qualcomm'ы при наличии прожженного фьюза с завода, разрешающего загрузку с MicroSD могут стартовать ядро, но всё зависит от конфигурации aboot.
Смартфон загружается и сразу вылетают приложения, настройки не сохраняются: явный показатель того, что флэша ушла в read-only потенциально не повредив данные. Если смартфон грузится в fastboot — его ещё можно оживить, но не факт что получится вытащить данные (из-за шифрования). Если после сброса до заводских настроек эффект остается тот-же — eMMC приехала 100%.
Смартфон висит на заставке, сброс и прошивка не помогает: тоже явная причина: eMMC в read-only. В таком случае, не рекомендуется еще раз шить смартфон в надежде что все заработает, есть шанс что флэша посыпеться окончательно и вы потеряете доступ к fastboot.
Весьма всё просто, согласитесь? Как я уже сказал выше, на некоторых устройствах нужно сначала разблокировать загрузчик. Кое-где это, вероятно, получится сделать и при том что флэша ушла в read-only. Например, на устройствах Sony можно без проблем зайти в fastboot и разлочить устройство с помощью кода, полученного на сайте Sony (используйте VPN, если вы в РФ):
Как зайти в fastboot — вам придётся погуглить для конкретно своего устройства. Не нашли? Поищите как это делается на других смартфонах, которые работают на том же чипсете. Почти всегда можно зайти, если у вас включена отладка по USB с помощью команды:
adb reboot bootloader
Краткая справка: на устройствах Sony, в Fastboot можно зайти подключив устройство к ПК с зажатой громкостью вниз, на MTK громкость вверх или вниз, на HTC в HSPL, на Nexus'ах в фирменном загрузчике сразу режим Fastboot, на устройствах Tegra — включение с зажатой громкостью вверх, на смартфонах с чипсетом Intel есть fastboot, насколько помню зайти в него можно с помощью громкости вниз.
Команда для разблокировки загрузчика почти везде одна:
fastboot oem unlock
Вас могут запросить код разлочки или просто предупредить о последствиях такого действия. Как узнать, что бут разлочен?
fastboot getvar all
secure, locking и т. п. — отвечают за статус разлочки. Но даже если таких переменных нет, это не всегда значит, что загрузчик заблокирован. Возможно он разблокирован с завода :)
Теперь нам нужен образ раздела boot — boot.img. Его можно найти в файлах родной прошивки устройства, или, иногда, в zip-файлах кастомов. boot.img содержит в себе ядро Linux и небольшой раздел с файловой системой initrd (рамдиск), которая загружается в оперативную память и содержит в себе программы init, adbd, recovery, а также скрипты инициализации, которые управляют загрузкой Android и процессом зарядки (показывают анимацию, когда вы подключаете устройство выключенным к ЗУ. Да, в таком случае Linux тоже грузится!).
Если у вас есть доступ к fastboot, то попробуйте запустить его с помощью команды:
fastboot boot boot.img
Работать она будет не везде, на MTK её поддержка отключена в загрузчиках некоторых устройств. Если вы увидели на экране устройства USB Transferring — половину дела сделана! Если устройство показало лого и анимацию загрузки или ушло в ребут — потенциально, вы сможете загрузить Android с MicroSD. Если ошибка secure-boot — нужно сначала разблокировать загрузчик. Если unknown command — команда не поддерживается :(
Теперь у нас есть возможность загрузить ядро и пропатчить скрипты конфигурации, дабы изменить точки монтирования раздела /system/, /data/ и /cache/ на MicroSD-флэшку, вместо встроенной памяти.
Обратите внимание: Android очень интенсивно использует ресурс флэшки и постоянно перезаписывает сектора памяти, поэтому не поскупитесь купить нормальную MicroSD флэшку от, например, Transcend, Kingston или Samsung. Дешевые MicroSD флэшки очень-очень быстро (вероятно, за пару дней — это не шутка) выйдут из строя и придется делать всё заново!
Сначала, нам придется разбить флэшку на три раздела: /system/, /cache/, и /data/. Раздел system будет первым, cache — вторым, data — третьим. При этом раздел /sdcard/ не нужен — он автоматически маппится в /data/media/ на современных версиях Android. Сделать это можно как с ПК с помощью MicroSD-адаптера и fdisk/diskpart/gparted, так и с самого смартфона с помощью того же fdisk в busybox. Я решил это сделать с помощью другого вспомогательного смартфона с TWRP, где изначально был root-доступ через adb! Размеры выбирайте следующие: для системного диска чуть больше или по размерам с system.img (раздел read-only и не «растет» со временем), cache — 100-200Мб, userdata — всё оставшееся место на флэшке.
Разметили MicroSD? Теперь нам нужно записать на неё образ системы. Тут три пути: если у вас есть Linux-машина, то можете подмонтировать образ system.img из оригинальной прошивки и скопировать все файлы с сохранением прав, закинуть system.img в внутреннюю память другого смартфона с root-доступом и проделать все тоже самое, либо записать с помощью dd образ system.img напрямую в нужный нам раздел флэш-памяти. Я выбрал третий способ:
dd if=/sdcard/system.img of=/dev/mmcblk1p1
Разделы cache и userdata можно просто форматировать в ext4:
mke2fs -t ext4 /dev/mmcblk1p2
mke2fs -t ext4 /dev/mmcblk1p3
Готово! Необходимые для базовой работы разделы перенесены на MicroSD. Теперь, когда, у нас есть образ системы, нам нужно распаковать родной boot.img устройства и поменять точки монтирования. Я использую кухню MTKImgTools. Идём в Boot -> Unpack -> boot.img. В Unpack/boot/ появятся файлы нашего раздела boot:
Открываем файл init.rc (в случае MediaTek). Ищем строки с монтированием разделов вида emmc@system, emmc@cache, emmc@userdata и меняем их на /dev/block/mmcblk1p1, /dev/block/mmcblk1p2 и /dev/mmcblk1p3. На некоторых чипсетах, править нужно сразу fstab, или init.<чипсет>.rc:
Готово! Собираем образ обратно с помощью Boot -> Pack -> boot.img и получаем образ, который нам и надо будет загрузить с помощью fastboot. Копируем boot.img в папку с adb и пробуем загрузить систему. Это будет основная команда для старта загрузки смартфона в будущем:
fastboot boot boot.img
Увидели бутанимацию? Значит система пошла загружаться, нужно лишь подождать первой загрузки 5-10 минут! Система висит на лого или уходит в ребут? Значит, возможно, вы неверно прописали точки монтирования, записали образ system или форматировали раздел userdata. Если система 4.4 и ниже, то можно изменить default.prop, заменив ro.secure на 0 и debuggable на 1. Если вы на Android 5+ — то заменить adbd (не требующий ключи авторизации) в /system/bin на вариант из TWRP и посмотреть logcat и dmesg. Монтируется ли /system/? Загружается ли app_process? На каком этапе стопорится? Всё это пригодится при дальнейшей отладке!
Например, такая ошибка при запуске adb shell означает то, что раздел /system/ не монтирован.
Ну а на моем девайсе система уже загрузилась и работает. Но насколько шустро? В комментариях читатели часто говорили, что из-за скорости MicroSD система будет не юзабельной. Насколько это правда? Давайте посмотрим!
Вывод mount:
Как мы и видим, /system/, /data/ и /cache/ на MicroSD. custpack и mobile_info, а также nvram трогать не нужно — если в родной флэше они не повреждены, то у девайса без проблем будет работать и сеть, и Wi-Fi.
Наш девайс работает на базе Android 4.2 — казалось бы, совсем старенький дроид, но тем не менее ещё кое-что, да может. Alcatel OT — это бюджетный девайс из 2013 года, но работает он, на удивление, весьма шустро и приятно!
Начинаем с самых необходимых приложений — звонилка, контакты и галерея. Все эти приложения стартуют практически моментально, лишь иногда с небольшими лагами. Однако если поставить в браузере что-то скачиваться на фоне — конечно-же, система начнет лагать.
Как насчет браузера? Ставить последний хром, поддерживающий 4.2 смысла нет — уже и он открывает далеко не все сайты. Но те сайты, что пока ещё открывает стандартный браузер почитать ещё можно: например, opennet. На смартфонах с более свежим Android, браузер будет работать относительно адекватно. Зато с соц. сетями проблем особых нет. Telegram, конечно, может конкретно подвесить смартфон в процессе подгрузки картинок с каналов, но потом все будет нормально. Решение одно: отключить автоматическое кэширование картинок и видео!
С записью видео ситуация сложная. Даже в профессиональных камерах для 1080p рекомендуются карточки не ниже 10-класса (10Мб/с) и UHS-класса для 2+K видео. На нексусе, это скорее всего превратит девайс в лагодром даже при записе 720p видео: система в фоне так или иначе регулярно читает и записывает данные и рано или поздно мы упираемся в дисковой кэш.
Об играх с динамическим стримингом ресурсов можно забыть, если флэшка достаточно медленная — будут лаги.
А в динамике это всё выглядит так:
Достаточно шустро, для смартфона 2013 года за 4 тыщи рублей?
Сегодня мы с вами узнали, каким же образом можно перенести систему на MicroSD! Да, сработает далеко не на всех девайсах, однако сам способ может помочь поднять сотни устройств обратно в строй и сделать их полезными! Это всяко лучше, чем распаивать потенциально рабочие девайсы на «доноров» или, тем-более, отправлять их на мусорку или в чермет. С современными версиями Android ситуация сложнее: и не только из-за большего числа необходимых для загрузки разделов, но и из-за возросших требований к скорости флэш-памяти (упомянутые выше UFS работают на скорости ~500Мб/с), а также, внезапно, стремительно исчезающего слота для MicroSD :(
Надеюсь, материал вам был полезен! Сегодняшняя статья подготавливалась специально в «классическом», более коротком стиле с максимумом конкретики. Если вам больше нравится такой формат, нежели подробный на 15-20+ минут на чтения — напишите в комментариях!
Кстати, если у кого-то из читателей есть ненужные устройства (в том числе с косяками) или дешевые китайские подделки на айфоны/айпады/макбуки и другие брендовые девайсы будучи нерабочими, тормозящими, или окирпиченными и вам не хотелось бы выкидывать их на свалку, а наоборот, отдать их в хорошие руки и увидеть про них статью — пишите мне в Telegram или в комментах! Готов в том числе и купить их. Особенно ищу донора дисплея на китайскую реплику iPhone 11 Pro Max: мой ударник, контроллер дисплея калится и изображения нет :(
А ещё у меня есть Telegram-канал, куда я публикую различные заметки по ремонту, программированию и моддингу девайсов, свои мысли и вовремя публикую ссылки на новый материал!
Статья подготовлена при поддержке TimeWeb.Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи каждую неделю!
Пожалуй, многие из вас помнят, какими были мобильные игры до и после выхода первого iPhone. В начале 2000-х годов, ещё до появления яблочного смартфона, игры для телефонов в основном были весьма интересными, но тем не менее, достаточно простенькими с точки зрения графики и реализации в целом. После запуска AppStore в 2008 году, на iPhone начали выходить самые разные красочные, невиданные раннее по уровню детализации и проработке 2D и 3D игры. Но появление таких игр — отнюдь не заслуга Apple, а относительной малоизвестной компании PowerVR (подразделение Imagination Tech), которая смогла разработать на базе видеочипа Dreamcast и внедрить один из первых действительно массовых мобильных 3D-ускорителей, имя которому — PowerVR MBX! Сейчас мы с вами привыкли, что почти любой дешевый смартфон может отрисовывать графику уровня PS3 в 1080p, а то и выше, но когда-то даже уровень PS2 был роскошью… Сегодня мы с вами: узнаем предысторию появления аппаратно-ускоренной 3D-графики на телефонах, рассмотрим такую фирменную фишку PowerVR, как тайловый рендеринг, а в практической части статьи нам поможет легендарный КПК Dell Axim X51v с MBX на борту, под который мы напишем 3D-игру «про жигули» с нуля! Интересно? Тогда добро пожаловать под кат!
Пожалуй, 3D-графика на мобильных устройствах начала развиваться ещё с самого начала 2000-х годов. К тому моменту, как мобильные телефоны научились запускать сторонние Java-приложения, практически сразу же появился прибыльный рынок мобильных игр. Ещё до появления поддержки jar-приложений, люди ставили рекорды в «Змейке» на телефонах Nokia, таскали ящики в «Строителе» на Siemens и играли в другие предустановленные игры на девайсах других брендов, поэтому было очевидно, что игры на мобильных телефонах рано или поздно смогут занять немалую часть сегмента портативных игровых устройств.
Именно появление J2ME дало тот самый толчок для развития мобильного гейминга. Производители телефонов активно развивали и дорабатывали мобильную платформу, добавляя в неё различные API-расширения — например, активацию приложений через СМС и доступ в WAP-интернет. Сама платформа J2ME была достаточно простой для изучения и имела низкий порог вхождения не только для людей, имевших какой-то опыт программирования, но даже для совсем новичков, которые никогда не писали код и тем более игр! Благодаря этому, появились сотни игр, многие из которых до сих пор помнят и любят: это и легендарный «мячик» Bounce, и «зайчик с морковками» Bobby Carrot, и весьма крутой Gish, а также множество различных платформеров по известным фильмам и «большим» играм!
В 2003 году появился Nokia N-Gage — первый массовый телефон, ориентированный именно на мобильный гейминг, который поддерживал не только Java-игры, но и собственные Symbian-игры с достаточно крутой 3D-графикой! Примерно в том же 2003 году, для платформы Java вышло сразу два API-расширения, которые добавляли поддержку симпатичной 3D-графики даже в самые простенькие и бюджетные телефоны: Mobile 3D Graphics (M3G, была почти везде) и Mascot Capsule (эта платформа была только на Sony Ericsson и Motorola). Именно благодаря этим API, мы с вами увидели такие легендарные игры, как V-Rally, Galaxy on Fire, Deep3D и многие другие! Но тем не менее, эти API были относительно медленными из-за программной растеризации на процессоре без отдельного 3D-ускорителя и весьма ограниченными в функционале. Ближайший пример по функционалу — уровень софтрендера первой кваки на первом Pentium! Кстати, про 3D на мобильных телефонах я писал отдельную статью, там в практической части мы пишем 3D-бродилку для Sony Ericsson!
Но помимо кнопочных телефонов, существовал сегмент High-end мультимедийных устройств, которые предоставляли гораздо больший функционал и производительность за немалые деньги. И речь, конечно же, о КПК! Девайсы, работавшие на базе шустрых процессоров Intel PXA и Samsung S3C с Windows Mobile на борту были заметно более перспективными для игр… но как-то не задалось из-за отсутствия нормальных каналов для распространения. Но тем не менее, Intel (иронично, но один из самых больших производителей ARM-чипсетов для КПК в те годы), которая уже занималась развитием десктопной графики GMA и PowerVR активно работали в этой сфере и результатом стало появление видеоускорителя 2700G, который представлял из себя не только 3D GPU PowerVR MBX Lite, но и аппаратный декодер видео, позволявший смотреть видео в высоком качестве! MBX Lite позволял запустить даже Quake 3 в 640x480 (!), пусть и в 10-15 FPS… Ещё за 5 лет до этого, далеко не все десктопные видеокарты могли выдать больше 30 FPS в 800x600!
Конечно в 2004 году уже вышел PSP, выставивший новую планку уровня 3D-графики для портативного гейминга, однако для смартфонов и КПК, уровень графики, разрешение и производительность 3D-игр на MBX Lite был просто немыслимым! Одним из самых легендарных и популярных устройств с 2700G, которое вы можете приобрести достаточно дешево и сейчас, был КПК Dell Axim X51v, флагманская модель с VGA-дисплеем тех лет. Но нельзя сказать, что только PowerVR работала в этом направлении. Параллельно NVidia выпустили GoForce, крайне редко попадающийся в «полноценном» виде (NVidia предлагала дешевле лицензировать только видео-декодер с отключением 3D-части, как это было в Toshiba Portege G900) и ATI Imageon, который чаще всего можно встретить в виде Adreno на ранних Android-чипсетах Qualcomm (Adreno — анаграмма Radeon :)).
Тем не менее, решение PowerVR было действительно массовым: компания не предлагала отдельный чип (что обычно было дороже), как конкуренты, а лицензировала другим компаниям уже готовые IP-ядра, которые производители чипов могли синтезировать и использовать в своих собственных чипсетах, или, сопроцессорах, как в случае с 2700G. Благодаря этому, MBX появился в чипсете TI OMAP 2430, использовавшийся в легендарных Nokia N93i и Nokia N95, Samsung INNOV8, Asus Lamborghini, Nokia E90 и некоторых других. Кроме того, PowerVR MBX использовался в процессоре Samsung S5L8900, судя по всему, разработанный для iPhone 2G и 3G! Благодаря этому, его можно считать одним из первых массовых 3D GPU в телефонах!
Одна из игр для iPhone 2G и N95 — Assasins Creed
И Asphalt 5!
Весьма симпатично, согласитесь?
Но MBX, конечно же, не появился «из ниоткуда» и был основан на более ранних разработках компании Imagination Tech, а именно GPU из полноценной домашней консоли SEGA Dreamcast — PowerVR CLX2, который в свою очередь был основан на ранних десктопных GPU PowerVR из середины-конца 90-х годов. Основная фишка PowerVR была в использовании так называемой техники отложного тайлового рендеринга (TBDR), которая, в отличии от классической растеризации и сортировки с помощью Z-буфера (или ручной сортировки треугольников) всех примитивов «в лоб» (методика, используемая в PSP, PS2 и большинстве видеокарт 2000-х годов), сначала ждёт от программы списка всех рисуемых треугольников в кадре, разбивает весь экран на тайлы (небольшие прямоугольные области), которые содержат в себе информацию о пересекающихся треугольниках, а затем процессом, несколько схожим с рейтрейсингом, определяет, какой из пикселей треугольника ближе всего находится к камере наблюдателя. Таким образом, мы избавляемся от необходимости сортировки геометрии с помощью Z-буфера (который сам по себе занимает достаточно много, по меркам тех лет, памяти и страдает от проблем точности и Z-fighting'а), а также такой метод позволяет реализовать более дешевый альфа-блендинг без ручной сортировки полупрозрачных примитивов и имеет ещё одну приятную фишку — «бесплатный» Occlusion Query, который можно использовать для реализации продвинутых техник отсечения невидимой глазу геометрии.
Производительность PowerVR MBX была весьма достойной для своих лет: при частоте работы в 200МГц, видеочип обеспечивал филлрейт в 100Мп, обрабатывал до 1млн треугольников в секунду. Нативным графическим API MBX был OpenGL ES 1.1 — специальная урезанная версия OpenGL для встраиваемых устройств, из которой выбросили все ненужное и которая заточена не только под floating-point, но и под fixed-point арифметику. В остальном, особо никаких отличий для программиста по сравнению с обычными GPU не было, можно было без проблем портировать уже существующие приложения для десктопого OpenGL для мобильные девайсы, чем и пользовались энтузиасты при портировании Quake 3 на Nokia E90, КПК и другие девайсы. Также, PowerVR MBX поддерживал D3DM — графический API Windows Mobile, о котором мы поговорим позднее.
Однако PowerVR MBX был GPU с фиксированным конвейером (FFP), а не программируемым, как принято в современных 3D-ускорителях. Что-же такое программируемый и фиксированный конвейер? Давайте разберемся:
Фиксированный конвейер: для того, чтобы задать визуальную составляющую рисуемой геометрии, программист оперирует набором заранее определенных при проектировании видеочипа параметров, которые позволяют управлять внешним видом растеризуемых примитивов. Например, для реализации света, программист задает параметры каждого из 8 источников света влияющих на рисуемый объект. Если программисту необходимо наложить несколько текстур за один проход (например, для реализации плавных переходов текстур на ландшафте или нанесения карты отражений на модель), он оперировал комбайнерами, которые позволяли задавать для каждого сэмплера параметры наложения. Такой подход использовался на десктопных GPU эпохи до GeForce 3 (т. е. примерно до 2000 года), до PS3 на Sony PlayStation (Xbox сразу вышел с GeForce 3) и до PSP включительно на портативках. Очевидно, что такой подход сильно ограничивает программиста в том, как будет выглядеть его игра на той или иной видеокарте.
Программируемый конвейер: в программируемом подходе, для управления визуальной составляющей программист пишет небольшие программы для видеокарты, называемые шейдерами. Всего есть два базовых (в современных GPU их больше) этапа программируемого конвейера: первый из них — вершинный шейдер, отвечающий за трансформацию геометрии (перевод из мировой системы координат в экранную) и, например, анимацию. Трансформированные вершины отправляются в следующий этап конвейера — растеризацию, где выполняется уже пиксельный шейдер, который определяет цвет пикселя (или более корректно — фрагмента в терминологии 3D графики) — т.е например, окрас объекта в определенной цвет, текстуру (или несколько текстур), рассчитывает попиксельное освещение, накладывает тени и т. д. Кроме того, такой подход позволяет реализовать сложные техники типа Ambient Occlusion, SSR, а также пост-эффекты (например блюр/блум, правда эти два можно «сэмулировать» и на FFP при определенной сноровке).
К 2007 году, Khronos выпустили спецификацию второй версии OpenGL ES, которая добавляла в мобильные устройства поддержку программируемого конвейера и шейдеров. Таким образом, мобильные GPU всё ближе приближались к уровню консолей и могли выдавать вполне годную графику, близкую к консолям. Даже была когда-то такая консоль, как Zeebo, которая работала на базе смартфонного чипсета Qualcomm с графикой ATI Imageon (!). PowerVR уже в 2009 выпустила серию SGX, которая также использовалась в iPhone, iPad, многих Android-смартфонах и планшетах, а также PS Vita!
Modern Combat 3 на iPad
Но статья с пересказом фишек PowerVR MBX была бы не особо интересной без практической части с написанием 3D-игры под этот GPU с нуля! Поэтому предлагаю посмотреть на нашего сегодняшнего гостя, легендарный флагманский КПК Dell Axim X51v из далекого 2005 года! Для тех лет, это настоящий «жир»:
Его мне подарил мой читатель Сергей с Хабра, за что ему огромное спасибо! Девайс был в полной комплектации, даже с флэшкой и усиленной АКБ, которая до сих пор неплохо держит заряд, однако у него не работал тачскрин. Если вам интересен только процесс программирования игры, а не аппаратного ремонта, то листайте ниже сразу до следующего абзаца :)
По факту, девайс полностью работал, однако в некоторые моменты времени не откликался на кнопки и тачскрин, и по всем симптомам это напоминало дребезг кнопок. При этом тачскрин сам по себе реагировал нормально во всех местах, что, фактически, исключало вероятность его поломки (хотя резистивные тач-панели сами по себе не особо надежные, в отличии от емкостных тачскринов). Дело было вот в чём: во многих КПК тех лет был отдельный аппаратный переключатель блокировки клавиатуры и тачскрина, который можно было использовать при просмотре фильмов. Однако на моем девайсе он был слишком разболтанным…
Разбирается КПК несложно: выкручиваем 4 винта и снимаем переднюю часть корпуса. На всякий случай я прочистил грязь между тачем и верхней частью корпуса — она тоже бывает влияет на ложные нажатия и чувствительность тачскрина:
А вот и виновник наших проблем: рычажок переключателя был отломан, но все еще находится в положении «разблокирован». Даже если в выжать в упор — он все равно не работал. Ну что ж, фен в руки, сдуваем переключатель и ставим вот такую перемычку (на фото флюс ещё не отмыт):
Включаем девайс и смотрим — теперь всё работает! Вот такой простой и быстрый ремонт Axim'а. КПК мне сразу очень понравился, я и ранее знал о его легендарности, но теперь узнал и о том, что он очень круто спроектирован и собран! Кстати, есть смысл сразу сдуть концевой выключатель, который прижимает задняя крышка и заменить на перемычку.
GPU не очень хорошо работает на кастомных прошивок, на которую прошиты многие Axim X51v. Поэтому есть смысл прошить сток: качаем прошивку (Файл отката), закидываем на SD-карту и ребутим девайс нажатием клавиш Wi-Fi + включение + Reset. После этого, девайс пойдет прошиваться.
Теперь девайс чистый, как с завода! Можно приступить к написанию небольшой демки-игрушки, которая сможет продемонстрировать нам перспективы нашего КПК в 3D!
Изначально, в практической части статьи должна была участвовать не менее легендарная Nokia N95. Однако вот незадача: несмотря на то, что под Symbian сохранился SDK (который работает нормально только под Windows XP), на устройствах с системой старше 9.x необходимо взламывать installserver, дабы иметь возможность ставить хоумбрю программы (к которым относится и наша игра) и отладчик TRK.
И хотя свой девайс я пропатчил, дебаггер нормально поднять мне так и не удалось. Я смог проинициализировать контекст GLES, запилить примитивный рендерер с загрузкой ассетов из памяти устройства но потом решил перевести проект на WinMobile… Проблем с разработкой под Symbian много: если приложение крашится — то оно просто закрывается, без сообщений и логов. Добавьте к этому то, что в Symbian вообще нет исключений и не всегда можно записать ошибки в лог и отладка превращается в ужас. Ситуацию исправляет Qt, который работает на N95, но в котором нет поддержки GLES (по крайней мере, в виде обычного QOpenGL, хотя возможность юзать API системы из Qt есть и дебаггер там работает нормально, так что не всё потеряно). Если вы когда-то что-то пилили под Symbian, особенно в Carbide — пишите свой опыт в комментариях, интересно почитать :)
WinMobile не менее интересен тем, что в нём поддерживается сразу два графических API: классический OpenGLES в профиле Common Lite (только fixed-point арифметика) и мобильная версия Direct3D — D3DM.dll, которая предоставляет API очень похожее на DX9, но без поддержки шейдеров. Что не менее приятно — есть официальные биндинги от Microsoft к D3DM в .NET Compact Framework, что позволяет легко писать 3D-игры под WM на C#/VB.NET.
Поскольку WinMobile — достаточно открытая для пользователя система, хватит лишь накатить VS2005/2008 на машину с WinXP/WinVista/Win7/Win8 и сразу начать разрабатывать под неё приложения, никаких проблем с отладкой и запуском приложений тут нет. На Win10/Win11 совместимость с WM5 поломали :(
Создаём приложение для смарт-устройств, выбираем в качестве целевой платформы WM5-устройство (эмулятор будет слишком медленным для наших целей, он даже для 2D-игр не подойдет) и, наконец-то, приступаем к написанию игры!
Что же за игра у нас будет? Я решил сделать эдакое 3D-переосмысление популярного в прошлом бесконечного раннера из «тетриса», где мы едем на машинке F1 и обгоняем другие машины, стараясь в них не врезаться. Основной целью является набрать как можно больше очков. Подобные игры достаточно популярны на мобильных девайсах и сейчас: вспомнить хотя-бы Highway Traffic, однако мой вариант будет весьма колоритным: ведь в моей демке мы будем кататься на ТАЗе 21099 и уворачиваться от гнилых «вторых гольфов». Ну а почему бы и нет, я просто очень люблю старые гнилые жигули и это не первый мой проект про машины этого производителя :)
Как и у настоящей машины, у каждой игры должен быть собственный движок! Однако в случае конкретно нашей игры, это скорее небольшой фреймворк, который предоставляет ровно тот функционал, который нужен игре без каких либо излишеств. Необходимо изначально распланировать требования для будущего фреймворка, дабы написание игры не скатилось в процесс, известный в узких кругах как «движкописание» :)
Рендерер: с графической точки зрения, фреймворк должен реализовывать весьма небольшой функционал. Загружать геометрию и текстуры из файлов в специально-подготовленном формате, реализовывать концепцию камеры, отрисовывать статическую геометрию, а также спрайты и текст, реализовывать примитивную систему материалов, которая позволяет наносить на геометрию текстуры, красить их в определенный цвет и управлять повершинным освещением, а также наносить на геометрию отражения с помощью специально подготовленных enviornment-текстур. Кроме того, рендерер должен уметь рисовать симпатичное анимированное небо в виде полусферы.
Звук: воспроизведение wav-звуков и музыки из файлов. Да и всё пожалуй — что ещё нужно от звуковой подсистемы? :) Стерео ведь нет, поэтому и 3D-звук не нужен.
Ввод: обработка нажатий на тачскрин и аппаратные кнопки устройства, маппинг кейкодов в виртуальный «геймпад». GUI-подсистему тоже частично можно отнести именно сюда!
Физика: AABB и Sphere vs Sphere столкновения. Никакого полноценного солвера тут и не нужно :)
Начинаем, пожалуй, с реализации рендерера. Сначала нам необходимо создать окно и контекст D3DM. Процесс практически идентичен D3D8 и D3D9: передаём информацию о нужном адаптере (видеочипе) и заполняем структуру PresentationParameters, однако есть важные нюансы: аппаратный FSAA лучше всего отключить (MultisampleQuality), а также передавайте точный размер окна, в которое собираетесь рендерить изображение, иначе система начнёт софтварно (!) скейлить рендертаргет до размера окна каждый кадр, что, как сами понимаете, крайне медленно.
Из форматов Depth-Stencil форматов поддерживается D16, D24S8 и D32. Желательно использовать D16 (несмотря на тайловую архитектуру, насколько мне известно, в MBX все равно есть fallback до классического рендеринга при некоторых условиях). Практически на всех КПК и коммуникаторах использовался 16-битный цвет, т.е RGB565, но можно указать Unknown — тогда GAPI подцепит тот формат пикселя, что используется в остальной системе.
PresentParameters pp = new PresentParameters();
pp.AutoDepthStencilFormat = DepthFormat.D16;
pp.BackBufferCount = 1;
pp.BackBufferFormat = Format.Unknown;
pp.BackBufferWidth = parentForm.ClientSize.Width;
pp.BackBufferHeight = parentForm.ClientSize.Height;
pp.EnableAutoDepthStencil = true;
pp.FullScreenPresentationInterval = PresentInterval.One;
pp.MultiSample = MultiSampleType.None;
pp.PresentFlag = PresentFlag.None;
pp.SwapEffect = SwapEffect.CopyVSync;
pp.Windowed = true;
device = new Device(0, DeviceType.Default, parentForm.Handle, CreateFlags.None, pp);
device.RenderState.Lighting = false;
aspectRatio = (float)parentForm.ClientSize.Width / (float)parentForm.ClientSize.Height;
Переходим сразу же к рисованию геометрии! Для начала рендеринга, нам необходимо подготовить состояние контекста: посчитать и установить матрицы вида (т. е. камеры) и проекции для трансформации геометрии, задать рендерстейты (список состояний, например нужно ли рисовать модельку с освещением, или нет), очистить экран и Z-буфер и установить параметры фильтрации текстур. Перспективная коррекция текстур — достаточно тяжелая операция и использовать её стоит лишь при необходимости:
public void BeginScene()
{
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.SkyBlue, 1.0f, 0);
device.BeginScene();
device.TextureState[0].MinFilter = TextureFilter.Point;
device.TextureState[0].MagFilter = TextureFilter.Point;
device.RenderState.TexturePerspective = true;
// Prepare projection
Matrix matrix = Matrix.PerspectiveFovLH(60.0f * MathUtils.DegToRad, aspectRatio, 0.1f, 350.0f);
device.SetTransform(TransformType.Projection, matrix);
}
public void EndScene()
{
device.EndScene();
device.Present();
System.Threading.Thread.Sleep(16);
}
Чтобы какую-то модельку нарисовать, нам нужно сначала её загрузить! Для возможности напрямую прочитать треугольники из файла и сразу записать их в вершинный буфер, я написал небольшой конвертер из формата SMD (GoldSrc) в собственный, очень простой и легковесный формат, который состоит из позиции вершины и её текстурных координат:
public struct BoundingBox
{
public float MinX, MinY, MinZ;
public float MaxX, MaxY, MaxZ;
}
public sealed class ModelConverter
{
public const int Header = 0x1234;
static BoundingBox CalculateBBox(SmdMesh mesh)
{
BoundingBox ret = new BoundingBox();
ret.MinX = float.PositiveInfinity;
ret.MinY = float.PositiveInfinity;
ret.MinZ = float.PositiveInfinity;
ret.MaxX = float.NegativeInfinity;
ret.MaxY = float.NegativeInfinity;
ret.MaxZ = float.NegativeInfinity;
foreach (SmdTriangle triangle in mesh.Triangles)
{
for (int i = 0; i < 3; i++)
{
ret.MinX = Math.Min(ret.MinX, triangle.Verts[i].Position.X);
ret.MinY = Math.Min(ret.MinY, triangle.Verts[i].Position.Y);
ret.MinZ = Math.Min(ret.MinZ, triangle.Verts[i].Position.Z);
ret.MaxX = Math.Max(ret.MaxX, triangle.Verts[i].Position.X);
ret.MaxY = Math.Max(ret.MaxY, triangle.Verts[i].Position.Y);
ret.MaxZ = Math.Max(ret.MaxZ, triangle.Verts[i].Position.Z);
}
}
return ret;
}
private static int FloatToFixedPoint(float x)
{
return ((int)((x) * 65536.0f));
}
public static void Convert(string fileName, Stream stream)
{
Console.WriteLine("Converting mesh " + fileName);
Smd2Bmd.SmdMesh mesh = new Smd2Bmd.SmdMesh(stream);
BoundingBox bb = CalculateBBox(mesh);
using(Stream outStrm = File.Create(Path.GetFileNameWithoutExtension(fileName) + ".mdl"))
{
BinaryWriter writer = new BinaryWriter(outStrm);
writer.Write(Header);
writer.Write(mesh.Triangles.Count * 3); // Verts count
// BBox
writer.Write(bb.MinX);
writer.Write(bb.MinY);
writer.Write(bb.MinZ);
writer.Write(bb.MaxX);
writer.Write(bb.MaxY);
writer.Write(bb.MaxZ);
foreach (SmdTriangle triangle in mesh.Triangles)
{
for (int i = 0; i < 3; i++)
{
writer.Write(FloatToFixedPoint(triangle.Verts[i].Position.X));
writer.Write(FloatToFixedPoint(triangle.Verts[i].Position.Y));
writer.Write(FloatToFixedPoint(triangle.Verts[i].Position.Z));
writer.Write(triangle.Verts[i].UV.X);
writer.Write(triangle.Verts[i].UV.Y);
}
}
}
}
}
Обратите внимание, PowerVR MBX оперирует fixed-point арифметикой! D3DM, конечно, может автоматически преобразовывать float-координаты вершин в числа с фиксированной точкой, вот только реализовано это криво и косо: драйвер будет конвертировать все вершины в fixed-point каждый вызов отрисовки, вместо того, чтобы один раз преобразовать их после Unlock'а вершинного буфера. Теперь представьте, насколько это тормозно для хоть сколь-либо комплексной модели :)
При этом загрузчик модели при таком подходе будет очень простым и будет работать шустро даже на таком слабеньком железе:
public Model(string debugName, Stream strm)
{
BinaryReader reader = new BinaryReader(strm);
int hdr = reader.ReadInt32();
int numVerts = reader.ReadInt32();
int vertSize = 20;
Bounds = new BoundingBox(reader.ReadSingle() * 2, reader.ReadSingle() * 2, reader.ReadSingle() * 2,
reader.ReadSingle() * 2, reader.ReadSingle() * 2, reader.ReadSingle() * 2);
PrimitiveCount = numVerts / 3;
byte[] data = new byte[numVerts * vertSize];
strm.Read(data, 0, (int)(strm.Length - strm.Position));
Buffer = new VertexBuffer(Engine.Current.Graphics.device, vertSize * numVerts, Usage.None, VertexFormats.PositionFixed | VertexFormats.Texture1, Pool.SystemMemory);
GraphicsStream gs = Buffer.Lock(0, Buffer.SizeInBytes, LockFlags.None);
gs.Write(data, 0, data.Length);
Buffer.Unlock();
DebugName = debugName;
}
Переходим к текстурам. Грузить напрямую png/jpg на КПК слишком долго, поэтому их я тоже перегоняю в собственный примитивный формат, который состоит из описания ширины/высоты, а также формата текстуры и собственно, самих пикселей. На данный момент поддерживаются только RGB565 текстуры — с ними MBX работает лучше всего:
public sealed class TextureConverter
{
public const int Header = 0x1234;
public static unsafe void Convert(string fileName, Stream stream)
{
Console.WriteLine("Converting texture " + fileName);
Bitmap bitmap = (Bitmap)Image.FromStream(stream);
byte[] pixels = new byte[bitmap.Width * bitmap.Height * 2];
System.Drawing.Imaging.BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format16bppRgb565);
Marshal.Copy(data.Scan0, pixels, 0, pixels.Length);
bitmap.UnlockBits(data);
using (Stream outStrm = File.Create(Path.GetFileNameWithoutExtension(fileName) + ".tex"))
{
BinaryWriter writer = new BinaryWriter(outStrm);
writer.Write(Header);
writer.Write(0); // 0 - 565, 1 - RGBA
writer.Write(bitmap.Width);
writer.Write(bitmap.Height);
writer.Write(pixels);
}
}
}
Загрузчик тоже получился примитивным и шустрым донельзя, пусть и без какой либо компрессии. PowerVR MBX поддерживает собственный формат компрессии — PVRTC:
BinaryReader reader = new BinaryReader(strm);
int hdr = reader.ReadInt32();
int fmt = reader.ReadInt32();
Width = reader.ReadInt32();
Height = reader.ReadInt32();
byte[] data = new byte[Width * Height * 2];
strm.Read(data, 0, data.Length);
Handle = new Texture(Engine.Current.Graphics.device, Width, Height, 1, Usage.Lockable, Format.R5G6B5, Pool.VideoMemory);
int pitch;
GraphicsStream gs = Handle.LockRectangle(0, LockFlags.None, out pitch);
gs.Write(data, 0, data.Length);
Handle.UnlockRectangle(0);
strm.Close();
Переходим, наконец, к фактическому рисованию модели! Для этого мы строим мировую матрицу для трансформации нашей модели, а также задаем вершинный буфер для, собственно, вершинного конвейера и посылаем видеочипу команду отрисовки. ZBufferWriteEnable нужен для отрисовки геометрии без записи в Z-буфер, что можно использовать, например, для реализации скайбоксов:
public void DrawModel(Model model, Transform transform, Material material)
{
Matrix matrix = Matrix.RotationY(transform.Rotation.Y * MathUtils.DegToRad)
* Matrix.Translation(transform.Position);
device.SetTransform(TransformType.World, matrix);
// Setup renderstate
device.RenderState.ZBufferWriteEnable = !material.DepthWrite;
device.SetTexture(0, material.Diffuse.Handle);
device.SetStreamSource(0, model.Buffer, 0);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, model.PrimitiveCount);
}
И рисуем модельку:
Model model;
Material mat;
Transform t;
void Start()
{
model = Model.FromFile("model.mdl");
mat = new Material();
mat.Diffuse = Texture2D.FromFile("test.tex");
}
void Update()
{
t = new Transform();
t.Position.Z = 150;
t.Rotation.Y += 0.1f;
graphics.DrawModel(model, t, mat);
}
Результат: у нас есть крутящийся кубик или любая другая произвольная 3D-модель!
Переходим к обработке ввода. Тут ничего сложного нет, ловим события KeyUp/KeyDown формы и назначаем виртуальным кнопкам их состояние.
public Input(Form parentForm)
{
keyState = new bool[(int)GamepadKey.Count];
parentForm.KeyPreview = true;
parentForm.KeyDown += new KeyEventHandler(OnKeyDown);
parentForm.KeyUp += new KeyEventHandler(OnKeyUp);
}
private GamepadKey ResolveKeyCode(Keys key)
{
GamepadKey k = GamepadKey.Count;
switch (key)
{
case Keys.Left:
k = GamepadKey.Left;
break;
case Keys.Right:
k = GamepadKey.Right;
break;
case Keys.Up:
k = GamepadKey.Up;
break;
case Keys.Down:
k = GamepadKey.Down;
break;
case Keys.Return:
k = GamepadKey.OK;
break;
}
return k;
}
void OnKeyUp(object sender, KeyEventArgs e)
{
GamepadKey key = ResolveKeyCode(e.KeyCode);
if (key != GamepadKey.Count)
SetKeyState(key, false);
}
void OnKeyDown(object sender, KeyEventArgs e)
{
GamepadKey key = ResolveKeyCode(e.KeyCode);
if (key != GamepadKey.Count)
SetKeyState(key, true);
}
public bool GetKeyState(GamepadKey key)
{
return keyState[(int)key];
}
private void SetKeyState(GamepadKey key, bool state)
{
keyState[(int)key] = state;
}
Теперь мы сможем управлять нашей машинкой в игре (которой пока ещё нет). Самая-самая основа для реализации игры подобного плана у нас есть, пора переходить к геймплею!
Выспаться, провести генеральную уборку, посмотреть все новые сериалы и позаниматься спортом. Потом расстроиться, что время прошло зря. Есть альтернатива: сесть за руль и махнуть в путешествие. Как минимум, его вы всегда будете вспоминать с улыбкой. Собрали несколько нестандартных маршрутов.
Этого красавца подарил мне читатель с Пикабу, за что ему большое спасибо! Девайс сдали в утиль, после неудачной попытки ремонта в СЦ в середине нулевых. Последний раз телефон использовался до поломки, ещё в 2006 году - 18 лет назад!
Считайте, что это своеобразный анонс подробного длиннопоста об аппаратном оживлении этого красавца, на манер статьи о N-Gage! Помимо ремонта, мы посмотрим на этот девайс подробнее, посчитаем ключи загрузчика, накатим патчи и эльфлоадер - эдакий ретро-моддинг из нулевых! И это будет не единственная статья про Siemens...
Многим пользователям смартфонов знакомо такие понятия как «привязка к аккаунту». У различных вендоров смартфонах есть свои механизмы защиты смартфонов от кражи: у Apple — FMI, у Xiaomi — Mi Cloud, а у Google — FRP. Однако у Android есть давняя уязвимость, которая позволяет обходить практически любые смартфоны на «чистой» системе, даже с привязкой к Google-аккаунту. Недавно мне написал известный YouTube-блогер MaddyMurk и предложил задарить смартфон-броневичок AGM H3 на гугл-аккаунте, который он не смог сбросить. Я решил подготовить подробный материал о дырах в защите Android и на практике обойти FRP на смартфоне, который «повис» на активации. Сегодня мы с вами узнаем: почему смартфоны на Android так легко обходить, какие существуют методики и почему подобная практика невозможна на устройствах Apple. Интересно? Жду вас под катом!
Ещё в нулевых, никакой привязки к аккаунтам у телефонов не существовало. Девайсы крали направо и налево: не уверен насчёт других стран, но в СНГ, к сожалению, эта практика была развита очень хорошо. Девайсы защищались максимум пин-кодом, который телефон мог запросить при смене SIM-карты, но даже его можно было обойти с помощью т.н «мастер-кодов», которые рассчитывались на специальных сайтах в различных СЦ. На некоторых телефонах помогала обычная перепрошивка — и вот, девайс снова отправлялся на БУ рынок для продажи своему новому владельцу, абсолютно чистенький и вероятно, пересобранный в новый китайский корпус. И пофиг, что IMEI-устройства уже давно числится как краденый!
Иногда, своеобразную защиту обеспечивала редкость аппаратной платформы телефона. Например, французские Sagem, которые были довольно популярны в РФ в середине нулевых, практически никто не обслуживал, несмотря на наличие программаторов на рынке. Смена IMEI же зачастую была невозможна — на телефонах Nokia, например, в внутренней памяти хранятся т.н сертификаты для активации радиомодуля и загрузки телефона. Если в процессе кривой прошивки они были повреждены или кто-то пытался их подделать, то телефон больше не включался без генерации нового сертификата за деньги на специальном сайте. Совсем.
Единственное известное мне исключение — китайские телефоны на платформе MediaTek (кнопочники Fly, Explay и.т.п) — там IMEI вполне можно поменять на какой-нибудь левый. Хоть из семерок себе сделать :)
Одну из первых и эталонных реализаций привязки смартфона к аккаунту представила Apple с выходом iPhone 4. Помимо входа в обычный аккаунт iCloud, пользователь мог включить функцию Find My iPhone, которая позволяла найти смартфон в случае кражи. Помимо поиска утерянного девайса, включенный FMI запрашивает логин и пароль пользователя при сбросе смартфона до заводских настроек (или перепрошивке). И вот здесь кроется главная фишка реализации «яблочников»: все устройства Apple, вышедшие с конвейера и прошедшие контроль качества, заносятся в некую базу данных, где хранится связка из нескольких аппаратных идентификаторов: уникальный ID процессора, который «прожигается» на заводе и остаётся
неизменяемым навсегда, уникальный ID модема (вот здесь я точно не скажу, что является идентификатором — скорее всего IMEI) и вероятно что-то ещё. Если идентификатор хотя-бы одного модуля не соответствует тому, что хранится в базе данных Apple — устройство повиснет на ошибке активации!
С этим даже связана одна занимательная история: iPhone 4/4s страдали отвалами модема, от чего в мастерских приловчились менять их с донорских аппаратов, при этом не перекатывая всю сборку вместе с процессором и памятью. С прилётом какого-то апдейта iOS, Apple ужесточили правила активации и многие полностью исправные айфоны повисли на ошибке активации.
Несмотря на эталонную реализацию, FMI обойти можно, если для устройства есть джейлбрейк, который можно сделать до доступа на главный экран (например checkra1n). Однако мобильная сеть и звонки работать не будут — для активации модема нужен уникальный токен, который генерирует сервер активации Apple Albert. Однако, кто-то всё-де смог отреверсить механизм работы сервера активации и завести модем на «байпаснутых» устройствах…
На Android-устройствах ситуация совсем иная: здесь долгое время балом правила открытость смартфонов, которая позволяла модифицировать устройства как угодно — портировать свежие версии Android, делать кастомные прошивки с различными плюшечками и оптимизациями. Долгое время люди знать не знали, что такое секьюрбут (заблокированный загрузчик) и с чем его едят…
По причинам тотальной открытости Android-смартфонов, никто особо не замарачивался с серьёзной привязкой к облачным сервисам: устройства с пин-кодом или графическим ключом без проблем обходились сбросом до заводских настроек через рекавери… до выхода Android Lolipop!
В «пятерке», Google предприняли попытку защитить устройства от сброса через рекавери с помощью механизма FRP — Factory Reset Protection, который запрашивает Google-аккаунт, если устройство не было сброшено с помощьюсоответствующего пункта в настройках. Реализована функция была крайне просто, без каких-либо аппаратных привязок: на устройствах MediaTek и Spreadtrum достаточно было забить нулями определенный раздел памяти фирменным прошивальщиком, а иногда вход в аккаунт можно было обойти различными багами операционной системы. На более старых версиях Android, можно было с помощью adb или терминала просто установить свойство, которое отвечает за показ окна активации:
content insert --uri content://settings/secure --bind name:s:user_setup_complete --bind value:s:1
Суть была в том, что Android на этапе активации просто делает шторку неактивной и прячет виртуальные кнопки домой/меню. По факту, приложения могут отсылать любые Intent («действия» в терминологии Android) системе и открывать любые приложения поверх окна активации, без каких либо ограничений. Если перезапустить приложение активации, то появлялась и полноценная кнопка «домой» и «многозадачность». Таким образом, нехитрыми манипуляциями, на смартфонах Samsung (вся A и J серия, до 2017 года) можно было зайти в браузер и затем в настройки с помощью голосового помощника, на смартфонах Asus с помощью умной клавиатуры TouchPal можно было открыть настройки и сбросить устройство до заводских в пару кликов, а в смартфонах Xiaomi была возможность написать в каком-нибудь текстовом поле youtube.com, зажать на нем палец и открыть соответствующее приложение, откуда можно снова попасть в настройки… Вариантов действительно много!
Недавно мне написал известный блогер с YouTube — MaddyMurk и рассказал занимательную историю: он нашёл «броневичок» AGM H3, который валялся в снегу и грязи несколько месяцев, абсолютно никому не нужный. Несмотря на тяжёлые условия, девайс полностью оправдал свой статус бронированного и остался полностью живым и целым! Однако, аппарат висел на графическом ключе и Миша по старой памяти решил скинуть его до заводских настроек, в надежде что владелец не входил в Google-аккаунт. После сброса, девайс повиснул на активации и Миша спросил у меня, что с ним можно сделать. По итогу, он предложил заслать девайс мне: «авось ты сможешь его оживить». Помимо AGM, Михаил прислал мне ещё кучу ништяков: несколько «сименсов» и «сонериков», кучу запчастей на iPhone 4-5, камеру и свою фирменную кассету с музыкой — за что ему спасибо :))
Однако материал был бы неполным, если бы я не показал на практике, как можно обойти абсолютно неизвестный девайс, для которого нет гайдов по обходу активации — и тем самым не показал бы вам, насколько «дырявая» защита от кражи у Android с Google-сервисами… Переходим к практике!
После включения, система встречает нас с предложением пройти первичную настройку. После подключения к Wi-Fi, нас встречает окно с предложением войти в аккаунт или ввести графических ключ прошлого владельца.
Наша задача: выйти из экрана авторизации в какое-нибудь приложение, откуда можно открыть встроенный в систему браузер. Вариантов масса: на некоторых устройствах, как уже было сказано, можно открывать ссылки, просто выделив их (таким образом, нужно открывать youtube или иной сайт с ассоциированным приложением в системе). Из тех, что я подметил: приложение «Google Фото» и YouTube подходят лучше всего. У моего смартфона нашлась аппаратная кнопка камеры слева, которая сразу же открывала соответствующее приложение. Хоба: фотографируем что-нибудь, нажимаем на превьюшку фотографии и попадаем в Google Фото!
Аппарат активно эксплуатировали до меня и хорошо затерли защитное стекло для камер — поэтому фото такое мутное.
Теперь нам нужно нажать «поделится объектом» и нажать «искать фотографию в Google». Лучше фотографировать что-то конкретное: например, другой смартфон или телевизор. Я снимал коробку от видеокарты и с помощью объектива нашёл обзор на неё на YouTube. Само собой, Google Поиск предложил мне открыть приложение YouTube для его просмотра!
После этого, нам нужно открыть боковое меню, тапнуть на «Настройки» и попытаться открыть какую-нибудь ссылку: например, лицензия на открытый софт. Делать это нужно быстро — иначе YouTube начнёт жаловаться на то, что версия устарела и смартфон придётся обходить по новой! После этого, смартфон предлагает нам открыть полноценный браузер.
Уже бежите качать какой-нибудь лаунчер и открывать настройки? Не тут то было — Google предусмотрели этот нюанс. Вы не сможете ничего установить из скачанного — менеджер пакетов без активации не работает. Совсем. Поэтому, мы заходим в настройки Chrome -> Уведомления и тапаем по значку логотипа приложения. Мы уже в настройках!
Сейчас сбрасывать устройство смысла нет: смартфон снова повиснет на активации (сброс сработает на устройствах с Android до 7 включительно). Однако есть забавный нюанс: если вовремя отключить Google-сервисы, то приложение активации просто начнёт считать, что мы активируем НОВОЕ устройство без СИМ-карты и предложит… пропустить шаг! Как забавно :)
Находим приложения с названиями а-ля «настройка системы» (кроме самого приложения Настройки) и всех их отключаем и снова включаем: у нас появятся все три кнопки навигации снизу и будет доступен диспетчер задач для более удобного процесса активации. Если у вашего устройства есть некое подобие Assistive Touch — оно тоже подойдет.
Теперь отключаем Google-сервисы и переключаемся на настройку системы. Жмём «Далее» и ждём пару секунд, но не дожидаемся ошибки Google-сервисов. Сразу же идём в настройки и включаем гуглосервисы обратно: по итогу, в один момент сервисы будут считать, что мы «оффлайн» и появится заветная кнопка «пропустить вход». Может получится не с первого раза. После этого, аппарат полностью «забудет» данные прошлого владельца и мы сможем без проблем войти в свой аккаунт :)
Если после этого у вас не устанавливаются приложения из обычных APK-пакетов, то тут два варианта решений: еще раз сбросить аппарат до заводских, либо устанавливать приложения с помощью adb — такой вариант тоже вполне работает:
Можно спокойно войти в свой гуглоакк.
Теперь аппарат полностью рабочий! Ретроспективу о нём не сделаешь: девайс относительно свеженький, работает на актуальной версии Android и имеет под капотом весьма неплохое железо:
Чипсет: Helio P22 с GPU PowerVR GE8320, с 8-ядрами Cortex-A53, 4 из которых работают на частоте до 2ГГц, а остальные 4 до 1.5ГГц.
ОЗУ: 4Гб
Память: 64Гб
Дисплей: 5.7 IPS-матрица. Не самая шустрая, конечно, но вполне ничего.
Аккумулятор: 5400мАч. Весьма бодро.
ОС: Android 11
В целом, весьма неплохие характеристики для современного бюджетника с приятным бонусом в виде бронированности. Уж что-что, а «бронежилет» аппарата выдержал явно многое :)
Авось кто-то из моих читателей когда-то его потерял?
Сегодня мы с вами рассмотрели некоторые базовые принципы защиты различных смартфонов от кражи и угона, а также на практике обошли плохонькую «гуглозащиту». Однако это отнюдь не призыв к действию: обходите таким образом только свои собственные смартфоны, аккаунты от которых вы когда-либо потеряли :)
Это не универсальный гайд и конкретный порядок действий может отличаться от версии Android и даже от версий оболочки. Но я рассказал, почему багами ОС можно обойти активацию и в общих принципах расписал то, почему гугловская защита такая плохая. А вы что думаете на этот счёт?
Материал подготовлен при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи каждую неделю!
А ещё я завёл собственный Tg-канал, куда публикую различный бэкстейдж статей, анонсы новых материалов, опросы и ссылки на статьи в минуту выхода.
Размер экрана — краеугольный камень мира современных смартфонов. Кто-то считает, что дисплеи должны становиться только больше, а рамки — меньше, кто-то любит «средние» дисплеи диагональю в 5+", ну а кто-то остаётся ярым поклонником и приверженцем компактных смартфонов с крошечными дисплейчиками. В наше время, купить новый смартфон с относительно небольшим дисплеем за приемлемые деньги почти нереально — самые бюджетные модели будут слишком тормозными для современного пользователя. Некоторое время назад, я купил себе бюджетный крошечный смартфон 2012 года выпуска — Samsung Galaxy Pocket, причём всего за 100 рублей. Конечно же мне захотелось довести его до ума — а доводить пришлось руками и навыками прожженного программера! Какой смартфон можно получить за 100 рублей? Читаем в статье!
Минутка предыстории
С самого появления смартфонов на рынке, весь мир шагал к тотальному увеличению дисплеев и уменьшению рамок. В какой-то момент, большие смартфоны даже получили отдельное название — падфоны или смартпэды. Такой ход событий было не трудно предугадать: ведь производители дисплейных матриц осваивали всё более и более высокие разрешения и предлагали больше вариантов производителям смартфонов.
Однако несмотря на всеобщее засилие больших «лопат», в мире всё ещё оставались поклонники маленьких и компактных телефонов, которыми очень удобно пользоваться одной рукой. Сейчас подобные устройства представляют только небольшие бренды, известные достаточно в узких кругах — в основном, их можно купить на маркетплейсах, в обычных салонах связи их не найти. Мне известно о нескольких подобных устройствах, которые сейчас присутствуют на рынке. Первый из них «закос» под iPhone — Soyes XS11:
Но тут уж, если честно, хочется назвать такой смартфон не просто компактным, а совсем малюсеньким. На нём вполне удобно выполнять задачи звонилки, но совсем неудобно набирать текст — поэтому под наши задачи, он не особо подходит. Кроме того, эти девайсы работают на базе бюджетного смартфонного железа 6-7 летней давности, поэтому их производительность будет достаточно невысокой по меркам современного пользователя. Конечно же есть и более серьёзные варианты — например, компания Unihertz (да, тот самый продолжатель идей BlackBerry) делает смартфоны Jelly 2: дисплей с диагональю 3", Helio P61 под капотом и Android 11 на борту. Вот только цена, мягко говоря, кусачая — 18 тысяч рублей на момент написания статьи. Это слишком дорого!
Но если душа прямо таки лежит к компактным смартфонам, почему бы не обратиться к рынку Б/У устройств и не присмотреть что-то из… прошлого десятилетия? А вариантов ведь реально много — тут и LG Optimus L3 (3.2"), и Samsung Galaxy Pocket Neo (2.8"), Samsung Galaxy Star (3"), Samsung Galaxy Fame (3.5"), Samsung Galaxy Young. Все перечисленные девайсы стоят реально копейки — можно купить живой вариант до 400-500 рублей!
Я решил взять себе целых два смартфона: Samsung Galaxy Mini и Samsung Galaxy Pocket первого поколения. Оба достались мне в одном лоте за 2.000 рублей (с 20 телефонами) и обошлись мне по сто рублей, причём оба смартфона были рабочими! Чуть позже я докупил отдельно Galaxy Star (250 рублей), Galaxy Fame (250 рублей) и Galaxy Pocket Neo (~400 рублей) для полноты коллекции — вышло совсем недорого. Итак, что за характеристики мы получаем в смартфоне за 100 рублей:
Android: 2.3 Gingerbread.
Чипсет: Broadcom BCM21553 с одним ядром Cortex-A5 на частоте 832мгц. Видеочип: VideoCore IV, он же использовался в Raspberry Pi.
ОЗУ: 256 мегабайт (предположительно — DDR1).
Встроенная память: 3 гигабайта + слот для SD.
Дисплей: 2.8", 240x320, емкостной тачскрин.
Сеть: Поддержка 2G/3G. Об LTE и речи не идёт.
Выглядит не особо густо, да? И разрешение весьма низкое — большинство софта не запустится, а о клиентах современных сервисов и мечтать не приходится… или приходится?
Конечно же шаловливым ручкам захотелось вернуть жизнь этому миниатюрному красавцу и я решил использовать его как второй смартфон — при этом с клиентом ВК и музыкой, которые я запилил сам.
Разработка под старые версии Android
На самом деле, разработка под старые версии Android не особо отличается от современных версий системы. Кое-где приходится костылить, велосипедить и юзать AppCompat для реализации современных фишек на старых версий системы, но, будем честным, подобного и в последних версиях Android достаточно.
Даже сейчас нет никакой проблемы скачать последнюю версию Android Studio, подключить смартфон с включенной отладкой и отлаживать приложение прямо на девайсе — logcat тоже есть. Единственный нюанс — поиск драйверов и ручное закрытие приложений в таскменеджере, если вы деплоите под Android 2.x (Android Studio не умеет сам закрывать приложение, чтобы переустановить пакет).
В целом, за всё время разработки под старые устройства, я пришёл к следующим выводам:
Поскольку большинство устройств имеет одно ядро, для плавности интерфейса нужно минимизировать любую работу в фоне.
Взаимодействие с современными веб-сервисами может быть осложнено из-за отсутствия поддержки TLS1.2 и устаревших сертификатов (проверка сертификатов легко обходится специальным костылем, а вот TLS — нет).
У Android до 3.0 вся отрисовка интерфейса программная и она опять же, будет сказываться на скорости работы фоновых служб. Чем менее интерфейс комплексный, тем лучше.
Пушей нет — да, вообще. Однако это ничуть не помешает нам сделать уведомления практически в реальном времени с помощью… очередного костыля!
Допиливаем ВК
Я уже писал клиент ВК в рамках одной из прошлых статей. Теперь нам нужно довести его до ума — подогнать под разрешение экрана и переработать интерфейс для большей удобности, а также добавить недостающие разделы — я тот ещё любитель полистать мемчики, сидя в автобусе.
Честно сказать, вся концепция интерфейса требовала полной переработки — боковое меню банально очень неудобно использовать на подобных устройствах из-за малых размеров каждой строчки. Поэтому я решил не изобретать велосипед, а обратился к дизайнерам Apple и первоисточнику: официальному клиенту ВК для iOS 6, родом из 2012 года!
Приложение для Android выглядело +- также в те годы. Видите вкладки с разделами снизу? Они то нам и нужны — это самый удобный способ навигации на таких смартфонах! Накидав макет в layout'е, я приступил к реализации:
Изначально мне хотелось, чтобы всё приложение было плавным и анимированным: для этого я обратился к фреймворку анимаций Android. Суть очень простая — это обычный интерполятор значений от a до b за определенный промежуток времени. При этом мы не можем анимировать произвольное свойство — только те, который уже реализованы в системе (переход, поворот, масштабирование, альфа-канал). Более наглядно это можно представить вот так:
Да, это всё анимация :) Получаем примерно такой результат:
Обратите внимание, что запуск большого количества анимаций будет вызывать перерисовку даже в том случае, если элемент не видно на экране — от чего у нас будут дикие тормоза! Осторожнее с этим.
После этого, я решил доработать раздел с музыкой: я все еще пользуюсь грязными хаками для получения доступа к API музыки, поскольку «левым» клиентам такой возможности не дают. Публично его расписывать не буду, поскольку это скорее всего нелегально, да и сами ребята из ВК об этом знают (но не думаю, что будут применять какие-то санкции по отношению к «маленьким» разработчикам) — но если нужно, пишите в личку, расскажу всю концепцию.
Во первых, мне хотелось добавить возможность скачивать треки на внутреннюю память/флэшку. А во вторых, мне хотелось добавить фоновое воспроизведение — до этого возможность свернуть приложение и послушать музыку уже была, однако Android мог в любой момент прибить окно с музыкой и оставить нас с носом, остаётся только реализация в виде foreground-сервиса:
В Android есть два типа служб: background (фоновые) и foreground (видимые пользователю). Первый тип служб система может прибить когда угодно — например мало памяти или экономия заряда АКБ. А вот второй тип служб система не прибивает практически никогда, поскольку они обозначают выполнение важной операции в фоне — например скачивание файла или обновление системы. Однако у них есть одно ограничение — они должны быть привязаны к собственному уведомлению, которое нельзя закрыть. В процессе реализации возникло еще пару проблем — Wakelock'и (механизм, предотвращающий уход девайса в «сон») и WiFiLock'и (тоже самое, но для WiFi).
Точно таким же способом я реализовал механизм уведомлений — как я уже говорил раньше, пушей на старых смартфонах нет вообще ни в каком виде, поэтому пришлось реализовывать свой механизм «обновления»: каждые 3-5 секунд запрашиваем список последних 5 диалогов с сервера и сравниваем с предыдущим результатом, если есть новые сообщения — создаём нотификацию (листинг слишком длинный - пришлось перезалить на pastebin):
После этого, я начал рутинную работу по реализации интерфейса для данных с сервера — паблики, друзья, профили, лента и.т.п. В некотором смысле, реализация лента весьма занимательна: вообще, для очень больших списков существуют т.н виртуализация ListView — это когда ListView отображает только видимый пользователю кусок датасета (набора данных — например, список записей на стене) и на старых версиях Android она доступна. Однако мне было интересно реализовать вариант, который потреблял бы минимальное количество ОЗУ и где я точно знал бы, когда пользователь видит тот или иной фрагмент приложения. Поэтому я реализовал… пагинацию свайпами! Вот так привет из нулевых!
Для этого я использовал GestureDetector — встроенный в систему класс для обнаружения простых жестов — свайпов и.т.п. ВК при запросе ленты отдаёт специальную метку для получения следующей страницы новостей (поскольку она может динамически меняться и нужно хранить её стейт), мы эти метки просто сохраняем и переключаемся по странницам новостей с помощью обычных свайпов вправо-влево:
Выглядит весьма забавно.
Юзабельно ли всё это на деле?
Давайте смотреть, может ли юзать такой смартфон в наши дни. Берём наш девайс в руки, логинимся и оцениваем его производительность «вхолостую».
Работает весьма шустренько, учитывая что это бюджетник 2012 года. Как насчет нашего самопального клиента ВК? Смотрим:
Работает весьма бодро. Не сказать что также плавно, как последний айфон, но и совсем плохим результат явно не назвать!
Смартфонный функционал у девайса тоже вполне ничего: 1-2 SIM (в зависимости от версии), нормальная синхронизация контактов с ПК (однако Kies вроде-бы не работает на Windows 10, но есть vcf):
Встроенный почтовый клиент продолжает работать без каких либо проблем. Однако настраивать некоторые почтовые сервисы нужно вручную и с помощью «паролей приложений» — напрямую залогинится возможности нет. В случае «покета», придется поставить стоковый клиент из Android 2.3 вручную.
Мультимедийные возможности тоже радуют: встроенный плеер тачвиза мне всегда очень нравился. Есть и настройки эквалайзера.
Единственное, что откровенно подводит — браузер. Последним вариантом осталась Opera Mini 7 — она позволяет смотреть сайты, но не поддерживает динамический контент, только статику. Ну, зайти на википедию или почитать статью на Хабре хватит. Родной браузер уже не в состоянии что либо загрузить :(
Ну а в общем, производителньость смартфона весьма радует, согласитесь? Нельзя сказать, что он уж слишком тормозной — по крайней мере, современные ультрабюджетные смартфоны (до 4-5 тысяч рублей) зачастую показывают себя гораздо хуже чем и флагманы прошлых лет, и даже бюджетники!
Заключение
И всё таки, я считаю что мне удалось в каком-то смысле вдохнуть новую жизнь в старенький девайс. Если использовать подобный девайс как второй — на случай, если сел основной смартфон, то такой миниатюрный красаввчик может неождианно выручить даже в довольно сложной ситуации. Кроме того, эти смартфоны всеядны к аккумуляторам — достаточно подпаять + и — и они будут работать хоть от BL-4C.
Главная ценность Galaxy Pocket — в его компактных размерах. А поскольку по настоящему дешевых, маленьких и шустрых смартфонов становится всё меньше и меньше, то нам остаётся лишь продлять жизнь моделям прошлых лет! Есть ли в этом смысл и получил ли смартфон новую жизнь? Пишите в комментариях!
Клиент ВК можно сказать на 4pda. Там лежит самая последняя версия (для скачивания нужна регистрация на форуме). Если по каким-то причинам не хотите регистрироваться на форуме — я выложил актуальную версию в комментариях.
Эта статья поддерживается командой ITGLOBAL.COM
Мы — первый облачный провайдер в России, а также интегратор, поставщик ИТ-услуг, продуктов, сервисов и разработчик собственного ПО.
• Наш сайт
• Наш блог про виртуализацию и Enterprise IT
• Истории успеха наших клиентов
Это все конечно здорово, энтузиазм дело хорошее.
Может с точки зрения разработчика эта система супер-пупер крутая.
Но с точки зрения пользователя - это редкостное говнище. Хуже только, наверное, виста на пк (в целом под нее и подгонялось).
Судя по интерфейсу и дизайну - система делалась как раз для разработчиков, мол как у нас классно, можно вот это написать, это запрограммировать, это сделать». Но для обычных пользователей это все нахер не надо. Человек хочет достать телефон из кармана, позвонить, отправить пару сообщений, посмотреть видосики и всё. И он хочет, что бы его глазам это было приятно. Виндафон этого не давал даже на 1%. В нем было хреново абсолютно всё от интерфейса до реализации структуры.
Это раз.
Второе:
А вы посмотрите на свой Android-смартфон сейчас. Сколько в нём ОЗУ? 4гб? 8гб? 12гб? Смущает ли вас то, что Android умудряется неприятно подтормаживать даже с такими ресурсами? А теперь вспомните Lumia 520: Snapdragon 200, 512 мегабайт оперативной памяти. Вот так она работает из коробки.
С точки зрения разработчика это полнейшая чушь и ложь. И либо ты не понимаешь как работают системы, либо пытаешься обмануть нас. С каждым годом приложения становятся сложнее и им требуется больше ресурсов. Да может где то это не оптимально. Да, может что то можно было бы лучше. Но общая тенденция это увеличение ресурсопотребления приложений из-за улучшения графики, увеличения вычислительных процессов, усложнения логики приложений.
И это все равно что сравнивать первую денди и PS5. На ПСке сколько оперативки? 32? 64? 128? И все равно некоторые игры тормозят. А вот на денди Марио не тормозил! Ну это же полнейшая чушь.
Это же фактический обман.
Плюс сама по себе система wp это максимально сырое тесто. Хочешь хорошо - бери напильник.
А людям надо что бы ты достал из коробки и сразу стало хорошо.
Вот простое объяснение того, что это система говно и к нее нет и никогда не было будущего.
Друг, это мертвая система которая никогда не будет воскрешена. Она убогая и неприятная (имхо).
И яблоки снискали такую популярность всего лишь по одной причине - они дали людям то, что им нужно - красоту и простоту. К счастью они нашли ровно тот ключик который был нужен.
А все вот эти архаизмы типа wp давно уже умерли и никогда не воскреснут.
А ты сейчас занимаешься некрофилией. Без обид, но по фактам.
А еще получит ачивку в профиль. Рискнете?
Windows Phone… услышав название этой мобильной системы, поневоле начинаешь с теплотой вспоминать своего недавнего, такого необычного мобильного друга, как будто прошло всего пару месяцев с момента смены смартфона на iPhone/Android. А ведь с момента фактической смерти Windows Phone прошло уже почти 10 лет! Увы, время вспять уже не повернуть, а мобильное подразделение Nokia не спасти, однако при наличии навыков разработки мобильных приложений, большом энтузиазме и фанатизме, есть шанс вернуть жизнь своему старому другу! Недавно я снова загорелся диким энтузиазмом и смог вернуть жизнь старенькой «люмии», написав собственные клиенты нужных мне сервисов с нуля — и готов поделиться этим с вами во всех подробностях!
Сегодня вы узнаете о моей мотивации привносить жизнь старым смартфонам, о тонкостях разработки мобильных приложений, чем Windiows Phone был на голову выше Android в техническом плане и о том, почему провал Windows Phone — одна из самых больших потерь мобильного рынка. Интересно? Тогда добро пожаловать в статью!
Пожалуй, довольно большой процент моих читателей и подписчиков когда-либо владел и пользовался смартфонами на Windows Phone. Мнение пользователей этой мобильной платформы во многом разнится — кто-то восхваляет по настоящему продуманный и плавный интерфейс, кто-то ругает Microsoft за «кидалово» с обновлениями, но большинство людей сходится во мнении, что Windows Phone — была действительно необычной и имела собственную изюминку.
Конечно же, Windows Phone была далеко не первым опытом Microsoft на мобильном рынке. До этого, Редмондская компания поддерживала очень крутую платформу для коммуникаторов и КПК под названием Windows Mobile. Фактически, это был полноценный компьютер в кармане — большинство кнопочных телефонов могли максимум запускать простенькие J2ME-приложения, в то время как WM позволял запускать множество самых разных программ — как написанных на C++/Pascal, так и написанных на C#/VB.Net. Мобильная платформа во всём пыталась подражать своему старшему брату — API системы было очень похоже на то, что мы видим в обычной Windows — тут и полноценная оконная система, и waveout для вывода звука, и GDI для вывода графики.
Windows Mobile прочно занимал свою нишу на мобильном рынке: HTC постоянно представляла новые модели коммуникаторов, которые довольно хорошо продавались. Но тут пришёл первый iPhone, который перевернул всё с ног на голову. Оказывается смартфоном можно управлять полностью пальцами, нажимая на красивые, анимированные элементы интерфейса! Это перевернуло всю индустрию — даже Nokia с её Symbian было тяжело конкурировать с продуктом от Apple. Microsoft видела, что пользователи хотят не столько свободы и кастомизации в системе, сколько плавности интерфейса, стабильности и простоты использования.
Плеер Zune HD стал дебютом свежего подхода к созданию интерфейсов — Metro UI. И хотя сам девайс не сыскал особой популярности, став в некоторой степени провальным, Microsoft взяла на вооружение концепцию этого интерфейса, дабы реализовать её уже в полноценной мобильной ОС. В октябре 2010 года выходит первая версия новой мобильной платформы Microsoft — Windows Phone 7, заложившая фундамент той самой системы, которую мы с вами до сих пор вспоминаем с теплотой!
На WP7 вышло весьма много устройств: тут и девайсы от HTC, и смартфоны Lumia от Nokia, и даже продолжение линейки Omnia от Samsung! Но были у этой платформы и серьезные минусы: она базировалась на ядре обычной Windows CE (оно же использовалось в Windows Mobile) и из-за желания повысить безопасность системы, Microsoft отключила возможность использовать код на нативных языках в своих приложениях. Кроме того, во многих аспектах WP7 была достаточно сырая — хотя для неё регулярно выходили обновления.
Конечно же параллельно с доработкой WP7, Microsoft разрабатывала новую версию ОС, которая должна была объединить мобильные и десктопные приложения в одну общую концепцию. Кроме того, разработчики решили отказаться от лёгкого ядра Windows CE в пользу более тяжелого и продвинутого ядра Windows NT, которое используется в полноценных версиях Windows.
К сожалению, апгрейда с WP7 на WP8 предусмотрено не было, что многие пользователи считают «кидаловом» со стороны Microsoft. Отчасти это так, но проблема была в том, что даже флагманские устройства на WP7 имели 512мб ОЗУ, чего было недостаточно для первой версии WP8. Думаю, в какой-то степени Microsoft просто не хотели портить имидж максимально плавных смартфонов тормозами обновленной системы, хотя примеры шустрой работы на 512мб ОЗУ есть — например, Lumia 520.
Но вот где WP8 была передовой, так это «под капотом». Microsoft смогли сделать что-то невообразимое для мира ARM-устройств: они реализовали нормальный слой абстракции от «железа» и ввели концепцию ACPI, знакомую нам из обычных десктопных ПК. Вкратце, ACPI — это что-то типа списка железа в устройстве, под которое ОС должна найти и загрузить драйверы, не забыв под это всё выделить ресурсы (devicetree в Linux реализует похожую концепцию). Кроме того, Microsoft реализовала полноценный UEFI в своих смартфонах, что позволяло, например, сделать дуалбут в будущем. На практике это всё означает то, что даже неподдерживаемые No-Name смартфоны можно было обновить до Windows 10, банально поменяв пару ключей в реестре: на Android-устройствах такое невообразимо. Фактически, это стандартизация ARM-железа.
На этом технические фишки Windows Phone не заканчиваются. Переходя к пользовательской части, стоит упомянуть фреймворк для построения интерфейса (WPF/Silverlight), который из коробки работает очень шустро, отлично масштабируется под разные размер экрана и предлагает мощные возможности по анимации и кастомизации интерфейса под стиль приложения. Да и само SDK навязывало изначально правильную концепцию программирования, заставляя выделять все задачи в отдельные потоки, не только задействуя дополнительные ядра процессора, но и улучшая пользовательский опыт от приложения (неправильно написанные Android-приложения легко могут подвисать при выполнении какой-то работы).
И третья классная фишка, про которую почему-то все забыли — это поддержка DirectX 11. Конечно в WP7 уже была поддержка Xna (именно на его базе написана Terraria), что позволяло писать игры одновременно для Windows, Xbox 360 и собственно мобилок, но он имел некоторые ограничения и был прослойкой между графическим API (как Direct3D или OpenGL) и самой игрой. Windows Phone 8 же давал настоящий, полноценный DirectX 11 — хотя и поддерживал максимум вторые шейдеры, но при этом умел те фишки, которые не умел Android — инстансинг для оптимальной отрисовки геометрии, установка стейтов «пачками» и эффективное «bindless» управление ресурсами шейдеров. Теоретически, это давало возможность портировать полноценные игры с ПК/Xbox на Windows Phone, хотя на практике не так много кто этим пользовался.
Ну и вспоминая аргумент про кидалово Microsoft с обновлениями, нужно помнить, что обратная совместимость с приложениями для более ранних версий системы была: на Windows Phone 8 можно было играть в годноту с Windows Phone 7 (NFS Undercover, NFS Hot Pursuit, Mirrors Edge и ещё некоторые классные мобильные игры), а на Windows 10 Mobile можно было запускать почти любое приложение для Windows Phone 8.
Так в чём же потеря WP — трагедия для мобильного рынка? А вы посмотрите на свой Android-смартфон сейчас. Сколько в нём ОЗУ? 4гб? 8гб? 12гб? Смущает ли вас то, что Android умудряется неприятно подтормаживать даже с такими ресурсами? А теперь вспомните Lumia 520: Snapdragon 200, 512 мегабайт оперативной памяти. Вот так она работает из коробки:
Думаю, это всё красноречиво объясняет то, что без WP случилась дуополия на рынке — Android продолжает жиреть, впустую жрать ресурсы и при этом практически не получать новых фишек из года в год, а iPhone хоть и остаётся всё такой же плавной и шустрой, ребята из Apple явно не чувствуют конкуренции и их смартфоны стагнируют в плане дизайна и в некоторой степени интерфейса…
Мои давние читатели знают мою любовь к смартфонам прошлых лет. Для меня нет понятия запланированного устаревания: если под устройство есть комплект разработки и документация, то при большом желании я могу дописать нужные мне приложения сам.
Мой проект SelfEco (сам себе экосистема) как раз об этом — почти полгода назад я написал клиент YouTube и ВК для Android 2.2+. Фактически это означает, что мои приложения работали на ВСЕХ Android смартфонах от 2010 года и новее.
Исходным кодом своих приложений я свободно делюсь — как в качестве примера читателям, так и для возможности каких-то фиксов в будущем или даже модов. В 2021-2022 году я ходил с Lumia 640XL с Win10 Mobile на борту, как с основным смартфоном. И в целом, меня все устраивало и всё нравилось: там и годный клиент ВК был (LunaVK), и клиент телеги нормальный, и браузер кое-какие страницы всё ещё нормально переваривал. Но больше всего мне нравится Windows Phone 8 — она работает ещё шустрее и несколько более строгая в плане дизайна. Да и «люмии» сейчас стоят сущие копейки — моя 640XL обошлась мне в100 российских рублей(~1.5$ по тому курсу), я не шучу. А на онлайн-барахолках можно найтиживые, целыеаппараты с нормальными аккумуляторами по 200-500 рублей, иногда даже в родных коробочках!
Lumia 1320 и Lumia 640XL — подарки читателя Kotenilla!
Дак почему бы не применить всю эту круть и мощь во благо, учитывая дешевизну смартфонов? Решено: Качаем SDK и пишем собственный клиент ВК и YouTube — это минимально-необходимые для меня приложения!
Для того, чтобы отлаживать и устанавливать сторонние приложения на смартфоны с Windows Phone, их нужно предварительно разблокировать и сделать «Interop Unlock». Процедура несложная и занимает немного времени на большинстве люмий. Дабы сильно не затягивать статью, я не буду описывать процесс разлочки здесь — его можно найти на 4pda для разных поколений устройств.
Начинаем с клиента ютуба. Собственно, концепция отнюдь не поменялась с прошлой статьи — мы всё так же используем API Invidous для получения информации о видео. Нативное API YouTube — полная дичь, да ещё и с ограничениями на один токен, в то время как Invidous сам распоряжается токенами и распределяет их как нужно. Нам лишь остаётся написать «морду», которая будет отображать полученные с сервера данные и передавать ссылку на видео в встроенный плеер.
В отличии от Android, никаких проблем с TLS не возникло: смартфон смог без проблем связаться с инстансом Invidous и получить данные о видео в трендах. Сам по себе, формат ответов очень простой и возвращается в виде JSON, который можно описать такой иерархией:
Практически сразу система нам навязывает распараллелленую парадигму написания кода — часть API банально не имеет синхронных аналогов! Например, из WebRequest убрали GetResponse, дабы неопытные разработчики не делали ошибок и не пытались вызывать долгие I/O операции в главном потоке (что вызывает подвисания приложения). .NET сам по себе имеет крутой механизм тасков (многопоточных задач) и реализацию концепции async/await, которая позволяет подождать выполнение операции, не блокируя остальное приложение.
Я решил придержаться более привычной мне концепции на коллбэках, которая позволяет более четко обрабатывать ошибки в подобных кейсах, да и в целом я не очень люблю подобный синтаксический сахар (а async/await и есть «сахар», поскольку разворачивается в стейт-машину). В качестве десериализатора (механизма парсинга JSON напрямую в экземпляры классов, используя рефлексию) я использовал классический Newtonsoft.Json.
После того, как механизм получения и обработки данных с сервера был готов, я начал реализовывать интерфейс приложения. И вот тут WP показал себя во всей красе. ListView? RecycleView? Нафиг эти костыли, винфон умеет нормально рисовать элементы интерфейса, которые вы выделили в ScrollView. И что забавно: в Android даже реализация с ScrollView при активной подгрузке данных вызывала лаги — на WP такого нет вообще! Тут всё просто работает из коробки!
Механизм анимаций здесь тоже декларативный и реализован в концепции т.н «сторибордов» — наборов действий, которые позволяют создавать достаточно сложные анимации вручную.
Буквально через пару часов после создания проекта, у меня уже была готова загрузка и отображение списка трендов:
А затем и логика воспроизведения видео, которая запускает встроенный плеер и передаёт в него ссылку на видео — которая выбирается относительно кодека (только mp4), разрешения устройства и предпочтений пользователя:
Кроме того, в приложение нужно было добавить настройки — для этого WP8 не предоставляет встроенных средств, нужно реализовывать логику самому. Впрочем, ничего сложного в этом нет — глобальный синглтон с полями настроек и логикой сохранения/загрузки (сюда код не поместился, нет нормальной подсветки кода).
WP предоставляет специальное изолированное хранилище для пользовательских программ — IsolatedStorage, в которое нельзя добраться из остальной системы (без разблокированного загрузчика и режима Mass Storage). Там же можно хранить и конфиги — правда с некоторым API для файлов сильно перемудрили — навязывать распараллеливание чтения обычно маленьких файлов — это совсем уже.
Итак, буквально за сутки разработки у меня получилось реализовать приложение, которое может выводить списки ютуба по региону (тренды/популярное), может искать видео и воспроизводить ролики с различными разрешениями. Кроме того, приложение умеет подгружать превьюшки и имеет собственный раздел истории. Неплохо за 24 часа для программиста, который фактически не имел опыта с платформой UWP/WinRT в прошлом, да? :)
Теперь пришло время реализовать клиент ВК! Фактически, ничего сложного в реализации клиента с базовым функционалом нет — это всё такая же «морда» к данным с сервера, к которым добавляется необходимость получать уведомления и реализовывать логику обновления данных.
На этот раз, я решил выбрать API WP8.1: оно гораздо более богатое на возможности и ближе к современному UWP, чем Silverlight из WP8. Так уж сложилось, что API обычного WP8 ближе к WP7 и совместимо с WP8.1 только с помощью специальной прослойки.
Я не ставил целью написать полноценную замену ныне не рабочему официальному клиенту, но я хотел чтобы моё приложение поддерживало базовый функционал:
Мессенджер: Конечно же, самое важное в нашем клиенте — это мессенджер.
Музыка: Куда ж без удобной ВК музыки? Её реализация в кастомных клиентах отнюдь несложная, но достаточно костыльная из-за политики ВК в отношении лицензирования аудио. Снова будем идти на хаки, дабы получить работающее приложение!
Новости: Помимо общения и прослушивания музыки, бывает потребность полистать ленту — дабы узнать новости, или посмотреть свежие мемчики.
Начал я с реализации окна с диалогами и продумывания навигации приложения. WP8.1 всё ещё не имел концепции боковых менюшек, поэтому реализовывать панель навигации пришлось самому. Вместе с ней была реализована верхняя часть, которая содержит в себе заголовок со статусом и анимацию загрузки:
Класс-менеджер для общения с API ВК я решил реализовать по тому же принципу, что и для клиента YouTube: у нас есть два метода на всё-про всё, один сразу десериализовывает ответ в виде объекта Root (для каждого типа ответа — он свой, все они описаны в Data.Packet.Root):
До async/await я не дозрел и здесь :)
Спустя достаточно короткое время, у меня уже была готова подгрузка диалогов:
Реализация обновления во всех разделах одинаковая: есть метод RequestUpdate, который начинает процедуру обновления и получает данные с сервера, а затем ставит в очередь задачу на обновление UI из основного потока с помощью UpdateUI:
И механизма загрузки/отправки сообщений.
В целом, с этим ничего сложного нет, однако теперь самое время разобраться с нотификациями. Пуши я пока-что поднять не смог, вместо них пока что лонгполлинг — достаточно для нотификаций пока приложение находится в фоне, но система со временем «прибивает» неактивные задачи, а сделать «бесконечный» фоновый таск как в Android не выйдет — система очень строго относится к любой фоновой работе.
Пришло время заняться музыкой — вот это действительно важный функционал! Для работы с аудио, я использовал довольно старый, но известный способ, который ВК пока что не пофиксил. Не то чтобы это из вредности, просто сами ВК особо не идут на контакт для интеграции аудио в своё приложение — исключением стали лишь очень крупные клиенты, как Kate Mobile — а значит можно реализовать действительно важные штуки: например, скачивание треков напрямую в музыкальную библиотеку, дабы их можно было послушать оффлайн! Вся работа с музыкой производится через прокси-сервер, поэтому аудио должно быть открыто.
Реализация фонового прослушивания музыки достаточно похожа на другие платформы, но в то же время заметно отличается. Само приложение может воспроизводить звуки с помощью MediaElement или BackgroundMediaPlayer, однако при сворачивании звук будет приостановлен (в отличии от MediaPlayer на Android). Для фонового прослушивания музыки, Microsoft решили сделать отдельный сервис BackgroundMusicPlayer, который запускается при попытке получить доступ к плееру из программы. Общаться с этим сервисом можно через межпроцессные вызовы — RPC и система предоставляет для него API. Вкратце: нам нужно создать фоновую задачу в виде отдельного модуля WinRT, который будет получать RPC-посылки от Foreground приложения и если нужно — отсылать ответы обратно. Ничего сложного!
Отдельного внимания заслуживает механизм скачивания музыки в библиотеку. В WP, программы не могут просто так «вторгнуться» в личное пространство пользователя — им обязательно нужны разрешения. Но это ладно, запросить разрешение — совсем не проблема. Зато настоящая проблема — ПОЛНОСТЬЮ асинхронный API. Захотел найти дескриптор файла в ФС — асинхронно, захотел его открыть — снова асинхронно. Поскольку у меня вся работа по скачиванию ведется в отдельном воркере и я не боюсь за дедлоки, пришлось лепить костыли с Task.Wait() :)
А ещё ВК возвращает mp3 без ID3-тегов, поэтому мне пришлось вручную их дописывать, дабы музыка в плеере удобно сортировалась:
Кроме того, дабы иметь возможность управлять музыкой из других приложений и экрана блокировки, Microsoft предоставляет т.н интерфейс SMTC — общий оверлей окна регулировки громкости, который позволяет управлять воспроизведением музыки. Его реализация простая до жути — просто включаем нужные кнопки (IsPlayEnabled, IsPauseEnabled и.т.п), добавляем обработчик события нажатия кнопки и обновляем информацию и обложку с помощью DisplayUpdater.
Вот таким образом, буквально за несколько дней мы реализовали клиенты нужных нам приложений с базовым функционалом. Разработка клиента YT заняла ровно сутки, разработка клиента ВК — двое суток. Но можно ли всем этим добром по настоящему пользоваться и как оно работает на настоящем устройстве? Смотрите ниже:
Весьма достойно, да? Ещё до публикации статьи, я выложил клиент YT на 4pda и в профильный Telegram-чатик — люди благодарны и действительно довольны. Только в англоязычном чате о WP8.1 (не вклюая WM10 и WP7/WP8) более 2х тысяч человек! Так что да, девайсы прошлых лет действительно нужны достаточно большому числу пользователей.
Ну а разработка клиентов для меня была эдаким челленджом — пилить что-то полезное под новым API всегда интересно, дак ещё и сами девайсы очень крутые с точки зрения UX и скорости работы. А вы как считаете? Жду ваше мнение в комментариях!
Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропустить новые статьи каждую неделю!