Ответ на пост «Устройства, которые мы потеряли: Как Siemens C65 стал культовым гиковским гаджетом»1
Очень интересно читать! В свое время, был sl45 перепрошил его вдоль и поперёк, но потом вышла nokia 3650 перешёл на неё, там далее игры от n gage, потом увиде sony ericsson p800 , ну а далее кпк/ коммуникаторы на win mobile. А оказывается сколько интересного в сименсах пропустил, читаю с огромным удовольствием, сейчас коллекционирую старые девайсы, которые были у меня или пропустил ( в журналах видел старых) но полапать хотелось!) Кстати, после sl45 очень хотел полапать U10 (siemens) но к сожалению достать не удалось, нашёл u15 - оказалось полные аналоги motorola только корпус другой слегка. Но все равно ностальгия по 00 зашкаливает. Автор пиши исчо!)
Устройства, которые мы потеряли: Как Siemens C65 стал культовым гиковским гаджетом1
Телефоны Siemens в наших краях получили статус культовых. Если сейчас отмотать время на 2005 год и подойти к случайному школьнику или студенту, то с высоким шансом в его руках окажется какой-нибудь M65 или C65. И отнюдь неспроста: «Сименсы» славились инновациями, неплохими мультимедийными возможностями и невысокой ценой. Однако особо смышленым, но не шибко богатым ребятам всё равно хотелось большего — и толпой они накинулись изучать прошивку в дизассемблере...
В статье мы с вами узнаем историю моддинга телефонов, что у C65 было внутри, изготовим кабель, пропатчим и добавим желанную поддержку MP3-мелодий.
❯ Не сначала...
История мобильного моддинга начинается в далёком 2001 году. Компания Sony, которая пока ещё была не Sony Ericsson, выпускает свой новый телефон — CMD-J70 с достаточно обширным по меркам тех лет функционалом и характерным колесиком JogDial. Как и другие устройства из линейки CMD, модель стала достаточно популярной и нередко в выборе между финским и японским качеством, побеждал именно японец!
Телефоны от Sony базировались на свежей, недорогой и очень удачной аппаратной платформе Texas Instruments Hercules (HERCROM), которая состояла из центрального процессора на ядре ARM7TDMI, работающего на частоте ~50МГц и аналоговой RF-части. Фишка новой платформы была в возможности прошивки без использования программатора, с помощью дата-кабеля, а в скором времени в сеть был слит сервис-мануал на устройство и программа для прошивки. И вот тут то всё началось!
Сначала для J70 делали простые патчи: на графику с Джеймсом Бондом, на мелкие твики системы и конечно же русификаторы. Но затем некий энтузиаст под ником NiMar раскопал функции прошивки и написал самый крутой патч — PRGLoader, который позволял писать новые программы для телефона с нуля на ассемблере или C! Загрузчик разделял и без того небольшую флэш-память телефона на десять слотов для кастомных программ: сначала необходимо было портировать «эльфы» для каждой версии прошивки отдельно, но затем появилась универсальная библиотека функций и программы стали портируемыми.
Это был первый известный случай хакинга телефона и запуска на нём кастомных программ. NiMar раскопал даже функции таймера, так что у телефона появлялась многозадачность... и после такого моддинга, бюджетная модель превращалась почти что в смартфон!
Но конечно одним CMD J-70 дело не ограничилось. В СНГ были очень популярны телефоны Siemens и момент, когда их хакнут, был вопросом времени!
❯ Infineon E-Gold
В отличии от Sony, телефоны Siemens почти всегда базировались на «родной» аппаратной платформе от Infineon (Infineon — дочка Siemens, выделенная в 1998 году в отдельную компанию в рамках реструктуризации). Первой такой платформой была HiGold — серия чипсетов Infineon PMB2800, которая использовалась в телефонах конца 90-х годов: C10, SL10, C25 и других моделях. Поскольку ARM в те годы ещё не настолько доминировал, Siemens решила использовать проверенное процессорное ядро собственной разработки — C166s, которое до сих пор можно найти в ЭБУ автомобилей ВАЗ!
Главной преградой на пути к моддингу устройств с C166s — относительно сложная сегментная модель памяти, напоминающая оную в x86. Сам набор инструкций хоть и простой, и в некоторой степени напоминает ARM, реверс-инжиниринг программ для этой архитектуры не так уж и прост.
Насколько мне известно, HiGold'ы практически никто не патчил, однако следующее поколение — E-Gold, которое использовалось в телефонах начала 2000-х годов, очень быстро хакнули и начали делать самые разные полезные патчи. Самым популярным телефоном на этой платформе был культовый SL45, который не только имел поддержку MP3, но и был первым телефоном с поддержкой Java-приложений. После SL45, Siemens выпустила следующую линейку устройств — S55, M55 и C55, которая также стала популярной за счёт появления подключаемой камеры и неплохих цветных дисплеев... но для них так и не появилось нормального загрузчика кастомных программ.
В те годы студент по имени Илья ( @ILYA_ZX) поспорил с однокурсником на то, что сможет написать «Змейку» для своего A60. Месяц ковыряния в дизассемблере и изучения архитектуры C166s — и вот, Илья представил рабочую игру и бинлоадер своему приятелю. Спор был выигран, исходники опубликованы, но этот проект так и не получил развития, и по сути, «эльфятник» был в зачаточном виде лишь на SL45.
❯ S-Gold
Всё изменилось с выходом новой аппаратной платформы Infineon S-Gold в 2003 году, где инженеры решили использовать новейшее ядро ARM926EJ-S с набором инструкций ARMv5 и частотой аж в 104МГц с возможностью разгона до 208МГц. По сути, S-Gold был флагманским мобильным чипсетом не только для Сименсов, но и в мобильном мире вообще — OMAP'ы для коммуникаторов на Windows Mobile работали на тех же самых ядрах и с той же самой частотой. Первыми телефонами на этом чипсете была легендарная 65'ая линейка Siemens'ов: флагманский S65, «бронированный» M65 и культовая бюджетная «стрекоза» — C65, которые сразу стали бестселлерами на рынке СНГ. Беспорядочному патчингу и моддингу на этот раз мешал новый загрузчик BOOTCore, не позволявший записывать неподписанные прошивки без специального ключа разблокировки — BKey.
Однако руководствуясь опытом с E-Gold'ами, энтузиасты быстро нашли тест-поинт (сажали одну из сигнальных линий флэш-памяти на массу), и смогли вычитать SKey и ESN, необходимые для расчета буткея. Чуточку позже обнаружили уязвимость в Java-машине и написали мидлет для расчета ключа вообще без необходимости что-то разбирать и замыкать. Как удалось угадать алгоритм расчета ключа — доподлинно неизвестно, но есть одна интересная теория.
По информации из дебаг-билдов симулятора, UI-часть прошивки писала некая компания-подрядчик из Польши, которая наверняка имела доступ ко всей внутренней документации для процессора. У некоторых доверенных лиц по слухам даже оказались axf-файлы (промежуточный выходной формат компилятора ARMCC), с отладочной информацией о прошивках и та самая NDA-документация, часть из которой затем слили в сеть. По словам Ильи, один из таких доверенных людей помог разобраться в аудиотракте устройства и сделать то, о чём мечтали тысячи пользователей телефонов Siemens — поддержку MP3-треков. Не исключено, что именно благодаря этому человеку в 2006 году написали первый ELFLoader и дали новую жизнь устройствам от Siemens — уже после закрытия мобильного подразделения.
Однако даже до появления ELFLoader'а, энтузиасты подвергали устройства на S-Gold серьезному моддингу. Например при модификации проверки HWID, прошивку от C72 или SL65 можно было установить на C65 — и это давало очень крутые фишки по типу поддержки 3D или возможности записи видеороликов. А M65 можно было переделать в CX70!
Сегодняшним нашим героем станет именно C65, специально подготовленный мной для коллаборации с @ilya_ZX и блогером MaddyMURK, который не верил, что в эту модель можно добавить поддержку MP3. Мне пришлось потратить несколько дней, чтобы добиться стабильной работы телефона, но спустя 3 месяца после отправки устройства, MaddyMURK слился под предлогом мол «чёта потыкал и мне больше не интересно... Коллабы не будет, отправлю тебе гаджет обратно». Ну и ладно!
❯ Что внутри?
По славной традиции рубрики, сначала мы с вами разберем телефон и узнаем что у него под капотом. Одна из главных фишек телефонов тех лет была в высокой ремонтопригодности даже неподготовленными людьми. Устройства полностью разбирались буквально за несколько минут при наличии пластиковой карты и отвёртки, а заменить основные элементы — дисплей, клавиатуру и динамик с микрофоном, мог даже школьник!
При этом была возможность всегда освежить внешний вид устройства путём переодевания в новый корпус. Во многих городах на рынках можно было купить корпуса с самым разным дизайном и качеством по 100-150 рублей, а поскольку в те годы телефоны берегли гораздо меньше чем сейчас, корпуса были расходниками. И тем не менее, даже сильно исцарапанный гаджет можно было превратить практически в новый всего за пару сотен рублей!
Внутри телефон представлял из себя модульный бутерброд, который состоял из металлической рамки, клавиатуры, дисплея и платы. И вот здесь, инжиниринг Siemens сыграл злую шутку: даже если пользоваться телефоном максимально аккуратно, постоянные изгибы платы в местах нажатия на джойстик со временем обрывало дорожки или срывало слабые пятаки на процессоре, отправляя телефон на очередную замену материнской платы.
После снятия рамки, нас встречает защитный экран, а под ним тот самый чипсет Infineon PMB8875 S-Goldlite. Внутри довольно большого по современным меркам процессора скрывается всего одно ядро ARM926EJ-S, способное работать на пиковой частоте от 104 до 208МГц, контроллер SDRAM-памяти и NOR-флэш накопителей, контроллер периферийных шин I2C/SPI/I2S, а также Watchdog и MMC. В целом, уровень интеграции не очень высокий, у Texas Instruments был выше, но всё равно вполне на уровне. Помимо Siemens'ов, S-Gold использовался в телефонах Panasonic и в качестве модема iPhone 2G (!!!).
Правее расположилась микросхема NOR-флэш памяти производства Intel объёмом в 32МБ. Из них 10МБ отводилось пользователю, а остальной объём был под прошивку и системные диски с кэшем. Несмотря на наличие контроллера MMC, Siemens всё равно решила не распаивать SD-слот, дабы не создавать внутреннюю конкуренцию более дорогому M65 и CX65. Ещё чуть выше распаяна микросхема SDRAM-памяти производства Hynix, объёмом в 4МБ. На первый взгляд кажется немного... Но не всё так просто!
К слову, в E-Gold из-за особенностей архитектуры, наружу торчала лишь стандартная 8080-шина, из-за чего инженеры Siemens были вынуждены использовать куда более дорогую PSRAM-память, в которой контроллер DRAM был уже в самой банке!
С обратной стороны платы нас встречает RF-тракт с усилителем и фронтэндом, а также микросхема Dialog, выполняющая роль контроллера питания. В её задачи входит обработка кнопки включения, WatchDog для сброса питания с процессора в случае зависания, усилитель звука, DC-DC понижающие преобразователи для формирования необходимых питаний на остальные чипы устройства и контроллер зарядки литий-ионных аккумуляторов. К слову, нередко ремонт нерабочих Siemens'ов решался заменой Dialog'ов или перекаткой процессора. Телефоны Siemens были хлебом для мастеров тех лет!
Чуть выше расположилась микросхема производства Epson. Её задачи разнятся от телефона к телефону, но в основном она выполняет роль контроллера камеры или дисплея. В некоторых других моделях, был дополнительный чип, который аппаратно декодировал MP3.
С нижней части платы расположился разъём под названием Lumberg, который служил как для зарядки, так и для подключения аксессуаров. В 65'ой серии, у телефонов появилась аппаратная поддержка USB, поэтому чип выше выполняет роль свича между UART и USB в зависимости от режима. Кроме того, RX и TX уходят к фильтру-стекляшке, так что если ваш Siemens не видит компьютер - смотрите в сторону этого чипа!
И это по сути всё. Простейший конструктив, не без недостатков, но зато позволивший сделать цену на устройство конкурентной с другими телефонами в том же классе - Motorola C650 и Samsung уровня C100. И при всём этом, C65 был значительно мощнее их обоих благодаря использованию новейшего чипсета!
❯ Прошиваем
Для прошивки «Сименсов» сначала необходимо купить или собрать кабель. На Авито иногда попадаются дата-кабели, но далеко не все из них подходят для прошивки: из-за кривого драйвера и неправильной разводки, шнурки на чипах Prolific покупать не стоит. У меня в наличии был как раз именно такой кабель, поэтому я решил переделать его на классический PL2303.
Схема кабеля до безобразия проста: достаточно лишь подключить RX/TX/GND к соответствующим пинам на преобразователе, а между пином CTS и GND установить резистор номиналом 10кОм. На фото не видно, но я впаял обычный SMD-резистор для компактности. Если есть 3D-принтер — можно напечатать дополнительный корпус, чтобы повысить надежность такого кабеля.
Далее выключаем телефон, вставляем дата-кабель и в x65PapuaUtils пытаемся загрузится в сервис-мод. Программа попросит кратковременно нажать на красную кнопку и если всё сделано правильно — телефон загрузится в сервисный режим. Из этого режима можно даже починить «пикающий» телефон путём форматирования раздела с пользовательскими данными и кэшем.
Знакомо?
Теперь необходимо разблокировать загрузчик. Для этого устанавливаем специальный мидлет px65v1 и ждём около 15-20 минут, пока он найдет SKey и ESN. Такое длительное время работы обусловлено тем, что мидлет с помощью уязвимости в Java-машине сканирует всё адресное пространство телефона и ищет нужные значения по паттернам. Далее мидлет передаст эти данные в x65PapuaUtils, а он каким-то неведомым алгоритмом рассчитает действительный ключ и сохранит его в ini-файле. Далее необходимо экспортировать лоадер в формат, пригодный для V_Klay, чтобы в дальнейшем можно было устанавливать патчи. Такая вот нехитрая, но долгая манипуляция!
После этого, я установил прошивку от C72 и применил специальный патч на обход проверки HWID, дабы телефон не пикал при включении. Даже без «эльфлоадера» мы уже значительно расширили функционал телефона относительно стока, но совершенству нет предела! Эльфлоадер, библиотека функций и аудиохук ставятся точно также: необходимо выбрать vkp-файл в V_Klay, нажать «Flash», подключить телефон и ждать завершения.
В V_Klay встроен механизм валидации патчей: если паттерн по заданному адресу отличается от прописанного в патче, программа выдаст ошибку. В случае аудиохука это норма — можно смело прошивать патч!
Для завершения установки эльфлоадера, необходимо создать папку ZBin в внутренней памяти телефона и закинуть туда файлы конфигурации и ассоциации расширений в проводнике с желаемыми программами. После этого, в системе появится диспетчер задач и возможность запуска программ прямо из проводника. Круто!
❯ Знакомимся поближе
После включения нас сразу встречает надпись о том, что xTaskMan запущен. Теперь при зажатии центральной кнопки на джойстике, будет запускаться полноценный диспетчер задач — ведь каждая системная и кастомная программа создаёт окно, между которыми теперь можно легко переключаться без потери данных!
Поскольку мы превратили наш С65 в куда более свежий C72, телефон обзавелся новыми фишками! Например, теперь можно записывать видеоролики и даже играть в 3D-игры. Помимо этого, с C65 на C72'ой прошивке даже в 2025 году можно выйти в полноценный интернет с помощью Opera Mini 6.5...
И конечно же куда без самой желанной фишки Siemens'ов в 2004-2005 году: поддержки MP3-мелодий! Запустив из проводника программу-плеер, мы попадаем в весьма забавный ретро-интерфейс, где энтузиасты реализовали плейлисты, скины, настройки и другие фишки, которых вообще не было в стандартном примитивном плеере. Нажимаем Play — и вуаля! Телефон полноценно воспроизводит мелодию без предварительной конвертации!
О деталях реализации хака рассказал сам автор плеера и патча — @Ilya_ZX. В прошивке телефона есть функция PlayWAVInMemory, которая на входе принимает описание wav-файла и PCM-поток. Путём нехитрых манипуляций, он пропатчил эту функцию так, чтобы на входе она принимала указатель на кольцевой буфер, а когда он опустошался — патч вызывал специальный коллбэк. Затем программа, которая хочет дальше проигрывать звук, заполняла буфер следующим отрывком PCM-звука и таким образом, мы получали возможность декодировать на лету и проигрывать любой формат — хоть OGG, хоть FLAC! При этом несмотря на заблуждение о том, что Siemens'ы банально не тянули декодирование mp3 в реальном времени — телефон мог спокойно проигрывать мелодии с битрейтом до 192кб/с в фоновом режиме с полноценной многозадачностью!
Единственный момент — стандартная прошивка не умеет воспроизводить звук с частотой дискретизации выше 11050Гц, Илья для решения и этой проблемы написал специальный патч, который, правда, не работает именно на C65. Ну что ж, нам и этого хватит!
Учитывая то, что студент из СНГ смог написать такой патч и частично сам плеер, решения инженеров Siemens в последующих моделях выглядили как минимум странно. Например, в CX75 поддержка MP3 была прикручена с помощью внешнего аппаратного аудио-декодера, у которого качество звука было крайне посредственным и на практике нормальный программный декодер MP3 реализовали только в E71 и EL71!
В остальном, C65 превращался практически в полноценный смартфон. Энтузиасты написали самые разные программы: клиент ICQ, E-Mail, погоду, виджеты на рабочий стол по типу загрузки процессора, объёма свободной оперативной памяти, был даже патч на эмуляцию E-Sim за 15 лет до первого телефона с этой технологией и навигация (A-GPS) по вышкам сотовой связи!!! При этом авторы активно делились исходным кодом и эти программы работали почти на любых S-Gold «Сименсах»... Это был венец моддинга мобильных телефонов!
❯ Заключение
Вот такой была история моддинга кнопочных телефонов. Когда у молодых ребят нет денег на топовый гаджет, в ход идут навыки реверс-инжиниринга и моддинга. А ещё это просто невероятно интересно и захватывающе — и в своей статье про хакинг более свежего кнопочника я постарался показать это на практике!
Даже спустя 22 года после релиза C65 коммьюнити моддинга Siemens всё ещё живо и собирается в уютном Telegram-чатике. Ребята просили не публиковать прямую ссылку из-за Хабраэффекта, но если вы олдовый участник клуба Siemens'оводов и действительно хотите в него попасть — найти ссылку можно по запросу «patches kibab».
А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал «Клуб фанатов балдежа», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статьи) можно найти на моём YouTube канале.
Разыскиваются гаджеты
Друзья! Для подготовки статей с разработкой самопальных игрушек под необычные устройства, объявляется розыск телефонов и консолей! В 2000-х годах, китайцы часто делали дешевые телефоны с игровым уклоном — обычно у них было подобие геймпада (джойстика) или хотя бы две кнопки с верхней части устройства, выполняющие функцию A/B, а также предустановлены эмуляторы NES/Sega. Фишка в том, что на таких телефонах можно выполнять нативный код и портировать на них новые эмуляторы, чем я и хочу заняться и написать об этом подробную статью и записать видео! Если у вас есть телефон подобного формата и вы готовы его задонатить или продать, пожалуйста напишите мне в Telegram (@monobogdan) или в комментарии. Также интересуют смартфоны-консоли на Android (на рынке РФ точно была Func Much-01), там будет контент чуточку другого формата :)
Кроме того, я ищу подделки на брендовые смартфоны 2009-2015 года выпуска. Многие из них работают на весьма интересном железе и об их моддинге я бы мог сделать интересный контент. Особо разыскиваются подделки Apple iPhone и HTC (по типу HD2 и Touch Diamond 2) на Windows Mobile и Android, а также Samsung Galaxy. Также представляют моддерский интерес первые смартфоны Xiaomi из серии Mi, Meizu (ещё на Exynos) и телефоны Motorola на Linux (например, EM30, RAZR V8, ROKR Z6, ROKR E2, ROKR E5, ZINE ZN5, о которых я хотел бы подготовить отдельные статью и видео, поскольку они работали на очень мощных для своих лет процессорах, поддавались серьезному моддингу и были способны запустить даже Quake.
Большое спасибо читателям и зрителям за подгоны, без вас контент бы не выходил!
Подготовлено при поддержке @Timeweb.Cloud
Пишем один «exe», который работает на 3-х разных ОС без перекомпиляции
Нет, это не шутка и не кликбейт. Такое действительно возможно - правда через небольшой хак.
Недавно я задался вопросом: а возможно ли написать для ARM нативную программу, которая будет бесшовно работать сразу на 4-х операционных системах без необходимости перекомпиляции для разных платформ и ABI. Мне очень хотелось реализовать возможность писать кроссплатформенные эльфы для мобильных телефонов из нулевых и попытаться портировать на них эмуляторы ретро-консолей. Погрузившись в документацию на исполняемые форматы, я пришёл к выводу, что да - это возможно и смог реализовать такую программу на практике без читерства по типу VM! Всех гиков приглашаю под кат!
❯ Зачем и почему?
Давным-давно, в далёком 2001 году, мир увидел легендарный японский телефон - Sony CMD-J70. Ещё до создания совместного подразделения с Ericsson, Sony выпускала достаточно занимательные девайсы, которые привлекали внимание не только рядовых пользователей, но и моддеров всех мастей. Уже через пару лет после выхода, в программном плане телефон копали все кому не лень: кто-то менял графику, кто-то писал патчи, а со временем написали даже бинлоадер (PRGLoader) - загрузчик внешних "экзешников", позволявший запускать на телефоне произвольный софт, написанный на ассемблере!
Сейчас сложно себе представить, но в те годы это был нереальный отвал башки: на большинстве телефонов были доступны разве что Java/Mophun-приложения, которые обладали ограниченным функционалом и уж тем более не позволяли лезть в дебри прошивки телефона, а здесь были программы которые буквально позволяли делать с телефоном всё что захочешь: светомузыку из подсветки, кастомные игры, обои на главный экран... всё это было доступно только на куда более дорогих смартфонах с Symbian и Windows Mobile на борту!
Недавно мы с вами вспоминали о легендарном Siemens M55 и узнали, что у него находится под капотом. Несмотря на диковинную архитектуру Infineon C166, даже под этот телефон делались патчи и была написана как минимум одна кастомная игра. Но рассвет моддинг-сцены Siemens произошёл с выходом платформы S-Gold на базе стандартного ядра ARM926EJ-S, когда в ~2004 году энтузиасты полностью взломали алгоритм генерации BootKEY для загрузчика, а затем в 2006 году реализовали полноценный эльфлоадер, который позволял загружать программы написанные на C и скомпилированные самым обычным компилятором ADS. В отличии от бинлоадера для CMD-J70, "эльфятник" позволял угонять функции RTOS для создания потоков и привносил в бюджетные телефоны полноценную вытесняющую многозадачность с настоящим диспетчером задач и возможностью запуска несколько программ одновременно:
Энтузиасты раскапывали прошивку в дизассемблере, изучали её и пытались понять как работают разные её подсистемы. Результатом стало появление нативного клиента почты с предком пуш-уведомлений, аськи (NatICQ), порты самых разных эмуляторов ретро-консолей и даже полная программная поддержка MP3 в тех телефонах, где её отродясь не было! И представьте себе, почти все эти программы можно было свернуть и продолжить работу в браузере или, например, Card Explorer'е! Одним из эльфописателей был Хабровчанин @ilya_ZX
Но если вы думаете что одними телефонами Siemens энтузиасты были едины, то вы ошибаетесь - ведь круче были только "моторолки"! В 2004-году, недорогая Motorola E398 с двумя громкими динамиками, светомузыкой и поддержкой MicroSD-флэшек, стала настоящим бестселлером и привлекла к себе не меньше энтузиастов, чем Siemens. Ребята сплотились на форуме MotoFan, нашли уязвимость в загрузчике и хакнули верификацию RSA-подписи у прошивок, позволив не только модифицировать Seem'ы (что-то типа NVRAM), но и создавать для телефона кастомные прошивки - монстрпаки, которые прибавляли громкость и без того не самым тихим динамикам и в различных аспектах изменяли главное меню устройства. Со временем, @Andy51 и ещё несколько энтузиастов реализовали эльфлоадер (EP1) для E398, раскопали прошивку и написали много полезного софта, время от времени переключаясь на Linux-телефоны от Motorola...
Вероятно многие читатели подумают мол "было и было, мой айфон/сяоми может запускать любой произвольный софт и эти ухищрения давным-давно неактуальны...". Но как бы не так: про моторолки и сименсы не просто всё чаще вспоминают, у них есть до сих пор активное моддерское коммьюнити, которое продолжает пилить для них кастомный софт и далее колупать прошивку. Всё тот же @EXL портировал крутой софтрендер для E398 и в 2025 году наконец-то взломал C350, @Azq2 пилит аппаратный эмулятор Infineon S-Gold и многие другие делают свой вклад в моддинг сцену уже не таких мейнстримных, но отнюдь не устаревших устройств!
Однако порог вхождения для написания эльфов достаточно высокий: нет никакой отладки кроме printf, любая ошибка в приложении приводит к зависанию или ребуту телефона (на сименсах с характерным "пик"), а API напрямую импортируется из прошивки телефона и может быть достаточно комплексным - ни о каких кроссплатформенных эльфах и речи не идет. Поэтому в какой-то момент мне стало интересно: а возможно ли написать такой эльфлоадер, который за своим рантаймом будет прятать детали реализации работы с аппаратной начинкой телефона и при этом загружать один и тот же бинарник на всех поддерживаемых платформах без особых патчей и изменений? Принявшись за изучение ABI ARM и спецификации Elf, я начал дизассемблировать и изучать самые маленькие тестовые программы...
❯ Формат ELF, ABI ARM и тулчейн
Начнём с самого простого: что же такое эти самые эльфы? Elf - формат исполняемых файлов, широко применяемый как в мире Unix-систем, так и в embedded-устройствах. Самые распространенные тулчейны - GCC и clang/llvm, по умолчанию собирают программы именно в этом формате и по своей сути, это прямой аналог .exe (PE) файлов из Windows. Помимо кода, Elf также содержит в себе множество секций и различных данных, при этом разработчики формата старались сделать его настолько гибким, чтобы его можно было использовать на любых архитектурах: от x86, до risc-v.
Каждая программа состоит из так называемых секций - участков кода, данных и метаданных, необходимых для её загрузки в память. Среди секций простой программы можно выделить как минимум четыре основных:
.text - хранит в себе код программы и обычно записывается в память с флагами MMU R X (чтение и выполнение)
.data - преинициализированные данные, имеет флаги R W (чтение и запись). Например, заполненная структура в C:
int a[] = { 1, 2, 3 };
.bss - не инициализированные данные, иными словами глобальные переменные, которые при старте программы должны быть забиты нулями. Имеет те же флаги, что и .data.
.rodata - различные константы: строковые, const-преинициализированные массивы, а также структуры и т.п, имеет только флаг R и на системах с MMU попытка запись в эту секцию повлечет SIGSEGV.
За загрузку всех этих секций отвечает загрузчик Elf в ядре ОС. Однако это справедливо только для простых программ, которые загружаются в фиксированный адрес виртуальной памяти и которые не используют внешние библиотеки (.so, аналог в Windows - .dll). Поскольку адрес загрузки для всех библиотек предсказать невозможно, разработчики ABI придумали позиционно-независимый код (PIC и его производное - PIE), который может загружаться в любую область памяти и оттуда выполняться.
Реализация PIC может достигаться тремя разными способами:
Первый способ заключается в использовании глобальной таблицы смещений (GOT) и релокаций. Релокации - специальные данные в Elf, которые позволяют переместить программу в другой адрес путём патчинга адресов в секции .got "на лету": иными словами, сам код (.text) остаётся позиционно-независимым (дабы библиотеку можно было загрузить один раз и использовать во множестве процессов) и обращается к GOT относительно PC, но в самом GOT (который представляет из себя массив void* addresses[]) указатели на остальные сегменты находятся так, будто программа загружается по смещению 0x0. Задача динамического линкера - посчитать абсолютный адрес для всех указателей в GOT: в простейшем случае, это got[address] += baseAddress.
Релокации могут затрагивать сразу literal pools в обход GOT, если архитектура предусматривает их наличие.
Релокацией занимается динамический линкер или интерпретатор в мире Unix (тот самый ld.so, что часто "not found" :) ), а самих релокаций есть много разных видов в зависимости от архитектуры процессора. В ARM чаще всего встречается R_ARM_REL32
Второй способ заключается в том, что мы компилируем программу так, будто она должна загружаться по фиксированному адресу 0x0 - то есть без PIC, однако просим линкер (--emit-relocs) создать информацию о всех обращениях к памяти в виде всё тех же релокаций. Вместо R_ARM_REL32, линкер создаёт релокации R_ARM_ABS32, которые можно разрешить обычным сложением.
С таким подходом количество релокаций кратно увеличивается, однако из-за отсутствия GOT немного повышается быстродействие программы (вместо трёх LDR для загрузки слова из памяти нужно всего два: из Literal pool в регистр и затем из фактической памяти).
Третий способ поддерживается не везде, но в ARM он является одним из самых распространенных в embedded-среде: код собирается с флагами /rwpi и /ropi полностью не зависит ни от GOT, ни имеет каких либо релокаций. Вместо этого, для адресации базового адреса программы он использует выделенный регистр R9, который загрузчик должен заполнить адресом, куда он загрузил программу (mov r9, textSectionBase). Такой подход теоретически чуточку быстрее, чем GOT, но медленнее второго подхода из-за необходимости добавлять сложение регистра с PC перед каждым фетчем из памяти.
Поскольку в телефонах MMU обычно не используется, эльфлоадеры загружают программы по тому адресу, что им выделяет системный аллокатор памяти и вынуждены использовать PIC. Чаще всего используются релокации (как минимум на Siemens и Motorola), на некоторых платформах используется второй подход с использованием регистра R9.
Для большей гибкости, я решил выбрать второй подход и построить свой эльфлоадер поверх уже существующих загрузчиков, обернув API прошивок в ряд собственных стандартизированных функций: работа с дисплеем, вводом, файлами, а также звуком. При этом эльфы должны собираться современным компилятором clang с поддержкой C99, чтобы была возможность легко портировать современные single-header программы по типу эмуляторов, да и в целом не писать код на манер Ansi C, когда переменную нигде нельзя объявить кроме начала блока.
Далее я сутками игрался с компиляторами и пытался заставить выдать их подходящий для моих целей код и по итогу написал скрипт для линкера, который для простоты загрузки файла объединяет все секции в один .text (таким образом остаётся всего один Program Header):
OUTPUT_FORMAT("elf32-littlearm")
SECTIONS
{
. = 0x0;
.text : {
*(.r9ptr)
*(.text*)
*(.data*)
*(.bss*)
*(.rodata*)
*(.functions)
}
.rel : {
*(.rel*)
}
/DISCARD/ : {
*(.ARM.*)
}
}
И следующий набор опций для компилятора, который устанавливает архитектуру и целевой процессор, ABI для FPU, включает генерацию релокаций и отключает выравнивание в линкере для выходного файла (иначе файлы забиты нулями и весят целых 64Кб:
CLANGFLAGS = -mno-unaligned-access -O3 -ffast-math -ffixed-r9 -T ld.script -target armv5e-none-eabi -nostartfiles -fno-exceptions -fno-rtti -mfloat-abi=soft -I$(ELFROOT) -Ilibnesemu/
LDDFLAGS = -Wl,-zmax-page-size=1,--emit-relocs
Когда компилятор наконец-то начал выдавать корректный код, я принялся писать сам эльфлоадер. За качество кода и отсутствие нормальной структуры не ругайте - это эмбеддед, тут можно ;))
На входе лоадеру поступает адрес загруженного в память эльфа и его длина. Задача эльфятника - верифицировать заголовок и убедится что он собран с подходящими параметрами:
// Read and verify ELF header
Elf32_Ehdr* hdr = (Elf32_Ehdr*)data;
PRINT("Loading ELF...");
if(hdr->e_machine != EM_ARM)
{
PRINT("Not an EM_ARM executable");
return 0;
}
if(hdr->e_ident[EI_DATA] != PLATFORM_ELF_ENDIANESS)
{
PRINT("Endianess mismatch");
return 0; // Wrong endianess
}
Проанализировать таблицу заголовков с служебной информацией о том, что находится по тому или иному смещению в файле: загружаемая секция, таблица символов или строк, а затем загрузить все секции в участок памяти, который нам выдал аллокатор. На MMU-системах адрес должен быть выровнен по размеру страницы, иначе система не даст выдать страницам флаг EXEC!
ret = (ExecInfo*)ExecAlloc(sizeof(ExecInfo));
sections = (Elf32_Phdr*)(&data[hdr->e_phoff]);
sh = (Elf32_Shdr*)&data[hdr->e_shoff];
symSectionIndex = hdr->e_shstrndx;
codeSize = 0x0;
PRINT("Processing program headers");
// Process program headers and determine total size
for(i = 0; i < hdr->e_phnum; i++) {
Elf32_Phdr hdr = sections[i];
if(hdr.p_type == PT_LOAD) {
if(hdr.p_offset == 0x0)
continue;
codeSize += hdr.p_memsz;
}
}
PRINT("Allocating memory for .text");
textSection = (char*)ExecAlloc(codeSize);
textOffset = textSection;
ret->CodeSection = textSection;
if(!textSection)
{
free(ret);
PRINT("Failed to allocate .text section");
return 0;
}
Далее найти секцию с таблицей символов и с строками, где содержатся имена символов:
PRINT("Analyzing section table");
for(i = 0; i < hdr->e_shnum; i++)
{
Elf32_Shdr sec = sh[i];
if(sec.sh_type == SHT_STRTAB && i != hdr->e_shstrndx && strTable == 0)
{
strTable = &data[sec.sh_offset];
PRINT("Found string table");
}
if(sec.sh_type == SHT_SYMTAB)
{
PRINT("Found symbol table");
symbols = (Elf32_Sym*)&data[sec.sh_offset];
symNum = sec.sh_size / sizeof(Elf32_Sym);
}
if(sec.sh_type == SHT_REL && relocs == 0)
{
UtilPrint("Found relocations");
relocs = (Elf32_Rel*)&data[sec.sh_offset];
relNum = sec.sh_size / sizeof(Elf32_Rel);
}
if(sec.sh_type == SHT_RELA)
{
PRINT("Found unsupported relocation types");
return 0;
}
}
if(!strTable || !symbols)
{
free(ret);
PRINT(".strtab or .symtab not found");
return 0;
}
А затем найти функцию ElfMain, которая служит точкой входа и пропатчить таблицу импортированных функций! На этом, загрузка эльфа завершена - можно устанавливать регистр R9 и вызывать Main!
PRINT("Relocation fix-up");
for(i = 0; i < relNum; i++)
{
Elf32_Rel rel = relocs[i];
int sym = ELF32_R_SYM(rel.r_info);
switch(ELF32_R_TYPE(rel.r_info))
{
case R_ARM_ABS32:
*((unsigned int*)&textSection[rel.r_offset]) += (unsigned int)textSection;
break;
case R_ARM_JUMP24:
break;
case R_ARM_CALL:
break;
default:
PRINT("Unsupported relocation type");
}
}
PRINT("Patching import table");
// Analyze symbol table and patch all imported function pointers to real counterparts
for(i = 0; i < symNum; i++)
{
Elf32_Sym sym = symbols[i];
uint8_t* symName = &strTable[sym.st_name];
int symType = ELF32_ST_TYPE(sym.st_info);
if(symType == STT_OBJECT && strstr((const char*)symName, "SYS_"))
{
int funcNumber = ExecFindFunction(symName);
if(funcNumber == -1)
{
PRINT("Failed to import function: ");
UtilPrint((char*)symName);
PRINT("");
continue;
}
//drawDebug(FuncExportTable[funcNumber].Pointer == 0 ? "Not OK" : "OK");
*((unsigned int*)&textSection[sym.st_value]) = (unsigned int)FuncExportTable[funcNumber].Pointer;
}
if(symType == STT_FUNC && strstr((const char*)symName, "ElfMain"))
{
PRINT("ElfMain function is found");
ret->Main = (ExecMainFunction)&textSection[sym.st_value];
}
В Elf уже есть механизм импорта функций из сторонних библиотек, называется Platform Linkage Table. Для импорта функций прошивки, эльфлоадер Siemens использует SWI (сисколлы, что-то типа программных прерываний в x86 - int 10h и т.п.), Motorola же патчит thunk-функции на лету, которые сами вызывают настоящую функцию:
А я решил поступить несколько изящнее. В моем эльфятнике, функции импортируются с помощью специального макроса, который создаёт переменную-указатель на функцию, который изначально располагается в секции .functions. При этом с помощью ключевого слова asm, символу присваивается иное имя - с префиксом SYS_, которое означает то, что загрузчик эльфа должен пропатчить адреса функций на реальные (которые предварительно зарегистрированы в рантайме) в процессе загрузки программ и таким образом, избежать thunk-функций и позволить оптимизатору легко выкидывать указатели на неиспользуемые функции:
#ifndef LOADER
#define IMPORT(name, ret, ...) __attribute__ ((section(".functions"))) ret (* name )( __VA_ARGS__ ) asm( "SYS_" #name )
#define IMPORTNOARGS(name, ret) __attribute__ ((section(".functions"))) ret (* name )() asm( "SYS_" #name )
#else
#define IMPORT(name, ret, ...) ret name( __VA_ARGS__ )
#define IMPORTNOARGS(name, ret) ret name()
#endif
Что самое забавное, лучший способ отладить эльфлоадер - в QEMU с GDB под Linux. Однако я решил время не терять и отлаживал его сразу на смартфоне с Windows Mobile. А раз WM стал первой поддерживаемой платформой - на нем мы с вами и реализуем рантайм.
❯ Портируем на Windows Mobile (CE)
Поскольку всю жизнь я сижу в основном на Windows, а WinAPI в CE практически полностью копирует десктопную версию, никаких проблем с портированием рантайма не возникло. Единственный выбор который передо мной встал: стоит ли прокидывать stdlib из хост-системы в "эльфятник", или же воспользоваться реализацией newlib в clang/gcc. В процессе портирования на другие платформы выяснилось, что нормально libc реализован, по сути, только на Windows, во все остальных реализациях были лишь самые основные функции по типу malloc, free, memcpy, strcmp и т.п. Поэтому я решил не городить велосипеды и прокинул из хост-системы лишь аллокатор - т.е malloc и free:
// stdlib
IMPORT(elf_malloc, void*, int size);
IMPORT(elf_free, void, void* ptr);
/*IMPORT(elf_strcmp, int, char* str1, char* str2);
IMPORT(elf_strcpy, char*, char* dst, char* src);
IMPORT(elf_strlen, int, char* str);
IMPORT(elf_strstr, char*, char* string, char* substring);
IMPORTNOARGS(elf_rand, int);
IMPORT(elf_memcpy, void*, void* dst, const void* src, uint32_t length);
IMPORT(elf_memset, void*, void* dst, int what, uint32_t length);
IMPORT(elf_memmove, void*, void* dst, void* src, uint32_t length);*/
Далее я сразу решил, что платформозависимые функции для работы с дисплеем использовать не буду и из хост-системы мне нужен будет лишь указатель на фреймбуфер, а блиттинг, рисование текста и прочие операции я реализую сам. На первый взгляд может показаться что это единственное верное решение, однако на практике в некоторых телефонах (Motorola E398, Razr V3) активно использовались 2D GPU от ATI и Nvidia, которые рисуют (BitBLT) изображение значительно быстрее любой программной реализации.
Ниже представлена черновая реализация без преобразования пиксельформатов (поскольку на подавляющем числе телефонов использовался 565) и поддержки прозрачности через колоркей. Её можно оптимизировать до быстрого копирования по сканлайнам через memcpy:
for(i = 0; i < bitmap->Height; i++)
{
for(j = 0; j < bitmap->Width; j++)
{
LCD_PLOT_565(clamp(x + j, 0, lcd->Width), clamp(y + i, 0, lcd->Height), bmp[i * bitmap->Width + j]);
}
}
С точки зрения отрисовки текста, нативные функции платформ тоже предоставляют крутые фичи по типу сглаживания, поддержки не-моноширинных шрифтов, множества кодировок, а также различные типы выравнивания. Но здесь встаёт вопрос с портативностью таких решений: разные рендеры шрифтов оперируют по разному и не все из них используют в качестве системы координат пиксели. Соответственно, я пошёл по олдовому "эмбеддерскому" пути и сделал обычные битмапные шрифты, которые (пока) статически слинкованы с самим эльфятником.
__inline int LcdDrawChar(LcdInfo* lcd, char chr, uint32_t x, uint32_t y, uint16_t color)
{
if(x >= 0 && y >= 0 && x + FONT_WIDTH < lcd->Width && y + FONT_HEIGHT < lcd->Height)
{
int i, j;
unsigned char* glyph = &embedded_font[chr * 8];
for(i = 0; i < FONT_HEIGHT; i++)
{
short* fb = &((short*)lcd->Pixels)[(y + i) * lcd->Width + x];
for(j = 0; j < FONT_WIDTH; j++)
{
if((*glyph >> (FONT_WIDTH - j)) & 0x1)
*fb = color;
fb++;
}
glyph++;
}
return true;
}
return false;
}
void LcdDrawString(LcdInfo* lcd, char* str, uint32_t x, uint32_t y, uint16_t color)
{
SWITCH_CONTEXT;
if(lcd && x >= 0 && y >= 0)
{
unsigned int i;
for(i = 0; i < strlen(str); i++)
{
if(!LcdDrawChar(lcd, str[i], x, y, color))
return; // Out of screen
x += FONT_WIDTH;
}
}
END_CONTEXT;
}
Отладив эльфлоадер, я написал небольшую тестовую программу для вывода картинки и текста:
#include <system.h>
int ElfMain(void* ptr)
{
LcdInfo* lcd = lcdInit();
lcdDrawBitmap(lcd, bitmap, 0, 0);
lcdDrawString(lcd, "Test", 0, 0, COLOR_BLUE)
return 100;
}
И получил следующий результат:
Вот теперь всё работает! Пришло время портировать эльфятник на весьма необычную платформу, о потенциалах моддинга которой знают единицы...
❯ Портируем на MRP/MRE
И имя этой платформе, вернее даже двумя платформам - MRP и WRE. Эти платформы использовались на бюджетных китайских телефонах с 2007 по 2016 год. Встретить их можно было везде: легендарная Nokla TV E71/E72, клоны 6700, бюджетные телефоны Fly/Explay/DEXP и даже в оригинальных телефонах Nokia на платформе S30+ (например 230)!
И хотя люди часто считали такие устройства бесполезными в плане установки сторонних приложений, многие ранние "нонейм"-телефоны поддерживали запуск нативных программ через небольшой костыль - установку специального "загрузчика" dsm_gm.mrp и ввод комбинации *#220807# в номеронабиратель. Конечно, знали об этом костыле единицы и в 2010 году MediaTek решила сделать свою платформу под названием MRE (MAUI Runtime Environment), приложения для которой можно было запускать прямо из проводника без установки! SDK для обеих платформ сейчас свободно лежит в сети.
Обе платформы, по сути, занимаются тем же самым, что и мой эльфятник - прокидывают нативные функции MMI (оболочка телефона) в приложения и для загрузки позиционно-независимых программ используют третий подход с регистром R9, который обязательно необходимо где-то хранить и восстанавливать. Изначально мой эльфятник использовал такой же подход, из-за чего я написал отдельный костыль для "свичнга" контекстов, причем восстановление R9 я делал в отдельной функции из-за бага ассемблера в ADS:
#define SWITCH_CONTEXT unsigned int staticBase; __asm { MOV staticBase, sb;
LDR r0, [sb];
MOV sb, r0 }
#define ELF_CONTEXT(ptr) unsigned int staticBase; void* elfStaticBase = ptr; __asm { MOV staticBase, sb; \
MOV r9, elfStaticBase }
#define END_CONTEXT RestoreSB(staticBase);
Но я не учел то, что MMI хоть и построены по event-based принципу, в них нельзя так просто взять и сделать while(true) {}, а необходимо использовать таймеры, что влечет за собой постоянные костыли с свичингом контекстов что по итогу только снижает производительность. По итогу я перешел на релокации и реализовал проброс таймеров.
Во всем остальном, MRP и MRE простые как табуретка, никаких проблем с пробросом ввода и графики не возникло:
LcdInfo* LcdInit()
{
LcdInfo* ret;
ret = (LcdInfo*)malloc(sizeof(LcdInfo));
ret->Width = screenInfo.width;
ret->Height = screenInfo.height;
ret->Pixels = (void*)w_getScreenBuffer();
return ret;
}
void LcdFree()
{
}
void LcdLock(LcdInfo* info)
{
}
void LcdFlush(LcdInfo* info)
{
mrc_refreshScreen(0, 0, 240, 320);
}
И вот, наша программа уже запускается на двух совершенно разных ОС без каких либо проблем!
❯ А если что-то посложнее Hello, world?
Наверняка у читателя возникнет вопрос мол "окей, твой эльфятник может и способен запускать простые программы, но как насчет чего-то посложнее?". И конечно-же, для тестов я решил портировать не абы что, а целый эмулятор NES! В конце-концов, одна из целей разработки такого эльфятника - возможность запускать Java-игр и эмуляторов на многих кнопочных телефонах из нулевых.
Какое то время назад, я обнаружил весьма шустрый эмулятор NES от неизвестного разработчика из Китая. Код был неважного качества, никаких копирайтов в нём не было. Но поскольку сам эмулятор был быстрый (быстрее, наверное, только vNesC, который является прямым source-портом Java-эмулятора vNes на C), я отвязал его от целевой платформы и превратил в небольшую библиотеку для легкого портирования на любые платформы путем вызова всего нескольких функций:
typedef struct {
uint16_t* FrameBuffer;
uint8_t* JoyState;
} emuContext;
emuContext* emuInitialize();
uint8_t emuLoadROM(void* rom, int length);
void emuReset();
void emuDoFrame();
void emuShutdown();
И, соответственно, базовый порт на наш эльфятник выглядит примерно так:
#include <string.h>
#define FUNC_PROTOTYPES
#include <system.h>
#include <nes.h>
#include "nes_rom.h"
emu_context* ctx;
LcdInfo* lcdInfo;
void EmuTick()
{
emuDoFrame();
LcdLock(lcdInfo);
short* pixels = (short*)lcdInfo->Pixels;
for(int i = 0; i < EMU_FRAMEBUFFER_HEIGHT; i++)
{
memcpy(&pixels[i * lcdInfo->Width], &ctx->FrameBuffer[i * EMU_FRAMEBUFFER_WIDTH], lcdInfo->Width * 2);
}
LcdFlush(lcdInfo);
}
void EmuSetupTimer()
{
TimerAttach(1, EmuTick); // As fast as possible
}
void EmuSetupRegularLoop()
{
while(true)
EmuTick(); // TODO: If elfloader port will be usable on Android, add FPS limit :)
}
int ElfMain(unsigned int* basePtr, void* test)
{
lcdInfo = LcdInit();
ctx = emuInitialize();
if(!emuLoadROM(nes_rom, sizeof(nes_rom)))
{
UtilPrint("Failed to load ROM");
return 100;
}
emuReset();
switch(GetMainLoopType())
{
case PLATFORM_LOOP_MMI_TIMER:
EmuSetupTimer();
break;
case PLATFORM_LOOP_REGULAR:
EmuSetupRegularLoop();
break;
}
return 100;
}
А вот и результат:
❯ Заключение
Вот так и можно написать программу, которая бесшовно работает на трёх разных операционных системах, которые не имеют ничего общего друг с другом! На первый взгляд всё это кажется сложным, однако на практике очень просто и интересно! Нужно лишь взять дизассемблер в зубы и немножечко изучить то, что выдаёт компилятор.
А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал «Клуб фанатов балдежа», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статью) можно найти на моём YouTube канале.
Очень важно! Разыскиваются девайсы для будущих статей!
Друзья! Если вам понравилась сегодняшняя статья про разработку эльфов, то спешу объявить: для подготовки будущих материалов с разработкой самопальных игрушек под необычные устройства, объявляется розыск телефонов и консолей! В 2000-х годах, китайцы часто делали дешевые телефоны с игровым уклоном — обычно у них было подобие геймпада (джойстика) или хотя бы две кнопки с верхней части устройства, выполняющие функцию A/B, а также предустановлены эмуляторы NES/Sega. Фишка в том, что на таких телефонах можно выполнять нативный код и портировать на них новые эмуляторы, чем я сейчас занимаюсь, а затем написать об этом подробную статью и записать видео! Если у вас есть телефон подобного формата и вы готовы его задонатить или продать, пожалуйста напишите мне в Telegram (@monobogdan) или в комментарии. Также интересуют смартфоны-консоли на Android (на рынке РФ точно была Func Much-01), там будет контент чуточку другого формата :)
А также я ищу старые (2010-2014) подделки на брендовые смартфоны Samsung, Apple и т. п. Они зачастую работают на весьма интересных чипсетах и поддаются хорошему моддингу, парочку статей уже вышло, но у меня ещё есть идеи по их моддингу! Также может у кого-то остались самые первые смартфоны Xiaomi (серии Mi), Meizu (ещё на Exynos) или телефоны на Linux (например Motorola EM30, RAZR V8, ROKR Z6, ROKR E2, ROKR E5, ZINE ZN5 и т. п., о них я хотел бы подготовить специальную статью и видео т. к. на самом деле они работали на очень мощных для своих лет процессорах, поддавались серьезному моддингу и были способны запустить даже Quake!). Всем большое спасибо за донаты!
Ответ nymezide в «Десятое королевство (2000) Культовый фэнтези сериал, который поздно оценили по достоинству / Загрузил сюда»3
Мой первый фантастический сериал, каждый вечер летом ждал новую серию. Было неимоверно круто, даже на черно-белом телевизоре, с дикими помехами. Капитан Пауэр и солдаты будущего.
Десятое королевство (2000) Культовый фэнтези сериал, который поздно оценили по достоинству / Загрузил сюда3
История создания / актеры / о продолжении / сами серии онлайн 1080
Десятое королевство (мини-сериал 2000). Режиссеры - Дэвид Карсон, Херберт Уайз. Оценка IMDb: 8.20. https://www.kinopoisk.ru/series/77217/ В России оценка 8,5 из 10.
Сюжет - Официантка нью-йоркского кафе Вирджиния однажды спасает пёсика, который оказывается заколдованным принцем Венделом, сбежавшим из Страны Девяти Королевств в наш мир, спасаясь от злой Королевы-Мачехи. Принц приходится внуком Белоснежке и является прямым наследником трона, но у Королевы другой план. Она посылает уродливых и злых троллей убить принца, и они тоже перебираются в наш мир. Так, неожиданно для себя, обычная современная девушка оказывается в самом центре невероятных и фантастических событий.
Сериал запомнился харизматичными персонажами, тонким стебом над классическими сказками, а также хорошей игрой актеров. Декорации и грим для 2000-го года на очень высоком уровне для ТВ. Бюджет составил 44 миллиона $ ( 5 частей по полтора часа). "«Десятое королевство» опередило своё время, став одним из первых сериалов, переосмысляющих сказочную тематику в постмодернистском ключе. За прошедшие годы сериал не устарел"
Основные роли сыграли - Кимберли Уильямс-Пэйсли (Вирджиния / актрису можно было видеть не так давно в Рождественские хроники и его продолжении / до сериала в Отец невесты и его продолжении) , Джон Ларрокетт ( Тони / сейчас играет в сериале Ночной суд (2023 -...), который является продолжением сериала 1984-го с ним же / актер в основном сериальный). В 2024 актеры выглядят так (вполне хорошо) -
Самый популярный персонаж сериала пожалуй Волк - Скотт Коэн. Актер более менее проявил себя с середины 90-х - криминальный фильм Готти (1996) и Джиа (1998), где главная роль у Анджелины Джоли. После сериала были главные роли в мелких фильмах, где выделяется артхаус Круг (2005). Потом череда слабых фильмов и ролей 3-го плана, но потом Любовь и прочие обстоятельства (2009) , где он сыграл главную роль вместе с Натали Портман. Правда после провала этого фильма актер укатился в сериалы на мелкие роли и всплыл позже -
Преданность (сериал 2015) - тут у актера одна из 3-х главных ролей, но сериал закрыли. Качественным вышел фильм Валет червей (2015) и роль второго плана в Джеймс Уайт (2015) + роль в хорроре Химера (2018). Недавно актер сыграл главную роль - Ощущение, что время действовать прошло (2023) + сейчас его можно видеть в - Пингвин (сериал 2024 с Фареллом) - Люка Фалконе.
Самыми известными актерами сериала были конечно Рутгер Хауэр ( Бегущий по лезвию, Слепая ярость, Попутчик + куча ролей первого и второго плана)
Дайэнн Уист ( Эдвард руки-ножницы , Ханна и ее сестры (она тут получила Оскар) , Пули над бродвеем (а тут у нее второй Оскар), Свободные 1984, Пурпурная роза Каира, Я - Сэм, Пропащие ребята, а сейчас можно увидеть в сериале Мэр Кингстауна)
Стоит отметить короля троллей - Эд О’Нил ( главная роль в Женаты и с детьми (сериал 1987-1997, Он сведет меня с ума , Маленькие гиганты / много успешных ролей второго плана)
Уорвик Дэвис думаю в представлении не нуждается ( франшиза Лепрекон, франшиза Гарри Поттер, Виллоу, Звездные воины ...) Менее знакомым будет пожалуй принц в исполнении Дэниэл Лапэйн ( если что сами найдете информацию)
Не буду останавливаться на забавных троллях ( дети короля троллей) -
"В феврале 2000 года на американском канале NBC состоялась премьера фэнтезийного мини-сериала «Десятое королевство». Невысокие рейтинги поставили на продолжении крест, но это не помешало сериалу со временем приобрести культовый статус, прежде всего на видео." Похожая ситуация потом произошла с другим сериалом - "Светлячок".
"Съёмки продолжались почти семь месяцев ( подготовка шла 2 года) и велись во Франции, Австрии и Англии. Самым романтичным местом этой волшебной вселенной — Городом поцелуев, в котором все обречены влюбляться, — стали целых три городка в Эльзасе. Внешне идиллическую деревеньку под названием Маленькая Овечка снимали в музее под открытым небом Вельд и Даунленд в Западном Суссексе. Роль архитектурного ансамбля королевского замка Венделла «исполнил» Уодсдонский особняк в историческом графстве Бакингемшир. Австрийский замок Хоэнверфен предстал в сериале Мемориальной государственной тюрьмой Белоснежки. Благодаря разнообразию локаций удалось создать впечатление, что герои действительно путешествуют по огромному миру Девяти королевств."
Было изготовлено 4000 костюмов и построено 150 декораций.
Джон Ларрокетт, сыгравший отца Вирджинии Энтони, также сыграл роль великана, который перешагивает через мост Нью-Йорка в титрах.
Всего в фильме снималось 130 актеров и 3550 статистов.
Карта девяти королевств на самом деле представляет собой немного переделанную карту Европы.
О возможном продолжении -
Подробнее тут, тк я использовал часть текста из этого поста ( там много о мире сериала, создании и тд - История сериала «Десятое королевство». Старые сказки, подозрительные грибы и одна собака
"В финале сериала прозвучали слова Вирджинии: «И это конец первой из историй о Десятом королевстве», подтверждающие, что сиквел был запланирован. Но из-за низких рейтингов его так и не сняли, хотя Саймон Мур долго надеялся на такую возможность. В 2000 году на вопросы фанатов сценарист отвечал кратким содержанием сиквела: события должны были развиваться преимущественно во Втором королевстве, стране диких лесов и пряничных домиков, частью которой правит Красная Шапочка III, а другой частью — Великая Гретель. После гражданских войн населяют королевство в основном женщины. Если в первой части главной героиней была Вирджиния, то в сиквеле основное внимание должны были уделить Волку. Мур намекал на то, что Волк с Вирджинией поженились и она беременна. Ориентировочно вторая часть называлась «Домом Волков». Позднее появилось больше подробностей сценария: Волк и Вирджиния держат собственный ресторан, в котором подаётся, разумеется, сплошное мясо. Их ребёнок родился волчонком, чем Вирджиния недовольна. Пара вновь отправляется в путешествие сквозь волшебное зеркало, чтобы магия могла превратить ребёнка в обычного малыша. Волк оказывается во Втором королевстве, где царит самое негативное отношение к его сородичам, и пытается его изменить, устраиваясь преподавателем в колледж для девочек. Ещё он выясняет, что его родителей не сожгли охотники, и, вероятно, с ними встречается."
"В 2001 году Мур пытался запустить работу над сиквелом, а Скотт Коэн рассказал в интервью, что ознакомился с десятью страницами сценария, горячо их одобрил и ему не терпится вернуться к роли Волка. Все актёры первой части были вновь готовы сниматься, кроме Джона Ларрокетта, который не хотел во второй раз так надолго уезжать из дома, но согласился на камео. В том же году канал Showtime выразил интерес к финансированию съёмок, но позднее его не подтвердил. В 2002-м на канале Hallmark по-прежнему колебались по поводу сиквела, но в качестве утешительного приза профинансировали другой проект Мура — телефильм «Снежная королева» с Бриджит Фонда в главной роли. В 2003 году канал всё же согласился на съёмки, но Мур в письмах поклонникам описал ситуацию: ему был предложен значительно более низкий бюджет и другие актёры. На такие условия он не согласился, не желая ронять планку оригинала. Последние неутешительные новости прозвучали в 2006 году, когда сериал уже обрёл культовый статус на видео и его поклонники регулярно писали на студию с просьбой о продолжении. В своей колонке в интернете Мур написал, что с удовольствием занялся бы проектом, но, увы, придётся подождать, «пока не придёт время и не появится такая возможность. Если этому суждено случиться, это однажды произойдёт».
Загрузил вам в 1080 качестве онлайн -
Также можно обсудить фильмы и сериалы у меня в телеграмме. Тут 8000+ человек и много всего - https://t.me/mrBordo
Думаю еще не поздно снять продолжение ( в ближайшие 2-3 года). Можно вернуть всех трех главных героев + принца, карлика Желудя и троицу троллей. Можно устроить мягкий перезапуск, где будет пара молодых главных героев ( сын главных персонажей + какую-нибудь боевую эльфийку из фэнтези мира) + двух повзрослевших главных героев оригинала. Тони можно отправить на второй план. Ввести нового интересного злодея и в помощь ему троицу троллей. Можно неплохо обыграть современный мир / фэнтези мир.
Хотя зная как сейчас снимают сериалы-продолжения у меня такое лицо -
Всем приятного просмотра !!!
Неналата (Nenalata)
Руины столицы последнего разрушенного города-государства айлейдов. Расположены в устье реки Серебрянки и заняты ныне нежитью. У входа нас уже поджидает Умбакано со своим наемником Мареком. В глубине развалин находится тронный зал Неналаты, куда мы и должны сопроводить нашего коллекционера, задумавшего, как выяснится чуть позже, ни много ни мало пробудить древних эльфов и стать их королем. В дороге альтмер с телохранителем будут осмотрительно держаться сзади, так что зачистка территории ляжет на наши плечи. Но в конце пути перед стеной, перекрывающей вход в тронный зал, альтмер выдвинется вперед и вставит в соответствующий паз резную панель из Малады. Проход откроется, Умбакано прошествует к трону, усядется и напялит на голову корону. Ударят молнии, трон окутается светящимся облаком, а из открывшихся тайных проходов в зал повалит нежить. На экране всплывет табличка с уведомлением о том, что Умбакано превратился в злобного айлейдского короля и пора срочно отсюда валить.













































































