Как выполнить запуск Windows 95 на одноразовом вейпе

Как выполнить запуск Windows 95 на одноразовом вейпе

Возможно, вы уже сталкивались с одноразовыми электронными сигаретами, у которых есть яркий цветной ЖК-экран. Нет смысла говорить о том, насколько вредно для экологии, когда на свалки и просто на обочину дорог выкидываются устройства с литий-ионными батареями (причём нормальными!). Я сам не курю, но интересные вейпы собираю. И вот недавно смог заняться реверс-инжинирингом одной модели с ЖК-дисплеем. Об этом и расскажу.

Модифицированный одноразовый вейп Kraze HD7K с моей собственной темой для Windows 95
Модифицированный одноразовый вейп Kraze HD7K с моей собственной темой для Windows 95

Вейп, который я буду разбирать, называется Kraze HD7K. Но его также знают под другим названием: Raz TN9000. Внутри они одинаковы, отличие только в прошивке и логотипе.

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

Разборка

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

Снята торцевая крышка. Переключатель легко выпадает.
Снята торцевая крышка. Переключатель легко выпадает.
Электронная начинка вейпа Kraze вытаскивается плоскогубцами
Электронная начинка вейпа Kraze вытаскивается плоскогубцами

Вытащив начинку, я увидел, что вейпе используется литий‑ионный элемент 13450 и большая ёмкость для жижи губкой для поглощения жидкости и предотвращения её утечки. Я также заметил небольшой 9-контактный прямоугольный разъем, к которому подключалась чёрная логическая плата с микроконтроллером и ЖК‑экраном, а также зелёная плата питания с датчиком вдоха, разъёмом нагревательной катушки, разъёмом USB‑C и площадками для пайки аккумулятора.

Открытый корпус с батареей ёмкостью 13450 и большим резервуаром для жидкости.
Открытый корпус с батареей ёмкостью 13450 и большим резервуаром для жидкости.
Разобранный Kraze при подаче питания через USB-C
Разобранный Kraze при подаче питания через USB-C

Реверс-инжиниринг

Три основных компонента логической платы вейпа — это микроконтроллер, микросхема SPI‑NOR Flash и ЖК‑экран.

Микроконтроллер Nations Tech N32G031K8Q7-1 и флэш-память Giantech GT25Q80A-UZLI SPI
Микроконтроллер Nations Tech N32G031K8Q7-1 и флэш-память Giantech GT25Q80A-UZLI SPI
Ленточный кабель ЖК-дисплея, номер детали FXD096QQ08B-F
Ленточный кабель ЖК-дисплея, номер детали FXD096QQ08B-F

Микроконтроллер — это Nations Tech N32G031K8Q7–1, содержащий процессор Arm Cortex‑M0 с частотой 48 МГц, 64 КБ встроенной флэш‑памяти и 8 КБ SRAM; флэш‑память SPI — Giantech GT25Q80A‑UZLI объёмом 1 МБ.

ЖК‑дисплей неизвестного производителя, но имеет номер детали FXD096QQ08B‑F, с разрешением 1280×1280 пикселей. размером 80×160 пикселей.

Учитывая, что именно ЖК-дисплей делает этот вейп особенным, я решил разобраться, какой контроллер и распиновку он использует. У меня было предчувствие, что он будет использовать общий интерфейс и контроллер (чтобы снизить затраты), и я искал 0,96-дюймовый ЖК-дисплей с 13-контактным разъёмом FPC. Это привело меня к Smart Prototyping #102106, который использовал 13-контактный разъем и, похоже, имел совместимую распиновку. Вышеупомянутый ЖК-дисплей использует обычный контроллер ST7735S и управляется через 4-проводной интерфейс SPI.

Я посмотрел на других сайтах ЖК-дисплеи с такими же размерами и разъёмом, и все они использовали эту распиновку:

PIN

NAME

FUNCTION

1

TP0/NC

Неиспользуемый (может использоваться для какого-либо сенсорного датчика?)

2

TP1/NC

Неиспользуемый (может быть, используется для какого-либо сенсорного датчика?)

3

SDIN

Передача данных SPI на ЖК-дисплей

4

SCLK

SPI clock

5

RS

Logic low = command, high = data

6

/RST

Сброс

7

/CS

Выбор микросхемы

8

GND

Источник питания/заземление

9

NC

Не подключен

10

VDD

Источник питания (3.3V)

11

LEDK

Катод светодиодной подсветки

12

LEDA

Анод светодиодной подсветк.

13

GND

Источник питания/заземление

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

Провода, которые я подвёл к ЖК-дисплею для анализа трафика
Провода, которые я подвёл к ЖК-дисплею для анализа трафика
DSView читает данные SPI ЖК-дисплея
DSView читает данные SPI ЖК-дисплея

Чтобы окончательно убедиться в том, что у меня дисплей на базе ST7735S, я перепаял ЖК-дисплей на разъёмную плату TSSOP-to-DIP (что было неприятно, так как шаг выводов немного отличался, а выравнивание требовало большой точности) и использовал графическую библиотеку Adafruit и драйвер ST7735S на микроконтроллере Teensy 3.0. Это сработало! Ну, почти. Черно-белый текст работал идеально, а красный и синий каналы, похоже, менялись местами при использовании процедуры tft.initR(INITR_MINI160x80), и, похоже, я был не единственным, кто столкнулся с этой проблемой.

Всем знакомый «lorem ipsum» на ЖК-дисплее вейпа Kraze HD7K
Всем знакомый «lorem ipsum» на ЖК-дисплее вейпа Kraze HD7K
Почему-то красный и синий текст поменялись местами
Почему-то красный и синий текст поменялись местами

Я решил, что с идеей переиспользования одного дисплея покончено, и начал изучать, как работает сам вейп и как он выводит изображения. Первым шагом было изучение содержимого памяти SPI Flash объёмом 1 МБ, так как это довольно большой объем памяти для такого простого устройства. Я отпаял чип, установил его в переходник SSOP-to-DIP и сбросил его содержимое в файл с помощью универсального программатора MiniPro TL866CS.

Данные из SPI Flash на ЖК-дисплее
Данные из SPI Flash на ЖК-дисплее
Данные ЖК-дисплея хранятся во флэш-памяти SPI
Данные ЖК-дисплея хранятся во флэш-памяти SPI
Крупный план верхнего левого угла главного экрана. Обратите внимание на синие пиксели, совпадающие с необработанными данными
Крупный план верхнего левого угла главного экрана. Обратите внимание на синие пиксели, совпадающие с необработанными данными

Мои подозрения подтвердились, когда я проанализировал данные изображения, отправляемые на ЖК‑дисплей, на соответствие тому, что было в начале SPI Flash. Данные выглядели так, как будто они были в необработанном формате «RGB565», который представляет собой метод упаковки 16-битного пикселя в два байта данных. Термин «565» означает 5, 6 и 5 битовых значений, относящихся к красному, синему и зелёному каналам соответственно.

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

Данные, по-видимому, передавались блоками по 4096 байт, которые, вероятно, выполнялись с использованием DMA (прямого доступа к памяти). Передача данных казалась слишком быстрой и регулярной, чтобы осуществляться только с помощью программного обеспечения. Позже это подтвердилось, когда я смог проанализировать объём оперативной памяти работающего вейпа.

Изучение Flash

После того как чип SPI Flash объёмом 1 МБ был распакован, пришло время изучить и его! Вооружившись электронной таблицей, шестнадцатеричным редактором, ImageMagick и онлайн‑утилитой RGB565 от Rinky‑Dink Electronics, пришло время начать изнурительный процесс распаковки всего содержимого SPI Flash.

Первым делом я попытался извлечь первый кадр изображения, размер которого, по моим расчётам, составлял 25 600 байт (80 x 160 x 2 байта на пиксель). Следующим шагом было использование ImageMagick для преобразования необработанных данных RGB565 в PNG для просмотра на компьютере:

magick convert -size 80x160 rgb565:.bin .png

Результат был похож на изображение, но все цвета были неправильными! Затем я попробовал утилиту RGB565 от Rinky‑Dink, в которой такой проблемы не было. Большинство моих попыток было выполнено с помощью ImageMagick, поскольку мне было легко вырезать и тестировать изображения разных размеров. (Позже я решил добавить тестовое изображение RGB, и, похоже, ImageMagick интерпретирует то, что должно быть RGB, как BRG).

Изображение из Rinky-Dink RGB565
Изображение из Rinky-Dink RGB565
Результат преобразования ImageMagick. Цвета неправильные
Результат преобразования ImageMagick. Цвета неправильные
Эталонное изображение с цветными полосами RGB/YCM/BW
Эталонное изображение с цветными полосами RGB/YCM/BW
Рендеринг ImageMagick данных RGB как BRG
Рендеринг ImageMagick данных RGB как BRG

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

Есть целая последовательность изображений
Есть целая последовательность изображений
Предыстория есть, а что после нее?
Предыстория есть, а что после нее?
Хорошо, это 72 пикселя в ширину. Однако неправильное смещение
Хорошо, это 72 пикселя в ширину. Однако неправильное смещение
Выравнивание исправлено!
Выравнивание исправлено!

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

Глядя на случайный фрагмент Flash, кажется, что это последовательность изображений, но шириной не 32 пикселя
Глядя на случайный фрагмент Flash, кажется, что это последовательность изображений, но шириной не 32 пикселя
Это 33х33? Нет...
Это 33×33? Нет
34? Всё ещё нет
34? Всё ещё нет
30? Нет, но он наклонен в другую сторону,  так что истина где-то рядом
30? Нет, но он наклонен в другую сторону, так что истина где-то рядом
Ага! Ширина 31 пиксель
Ага! Ширина 31 пиксель
Вооот, уже что-то. Надо просто вытянуть изображение по высоте
Вооот, уже что-то. Надо просто вытянуть изображение по высоте
Готово!
Готово!

Так продолжалось до тех пор, пока я не заполнил более 95 % всего адресного пространства в 1 МБ. Я даже нашёл неиспользуемые анимации (по крайней мере, для версии, настроенной для моего региона). Там было немного пустого пространства, которое я некоторое время игнорировал… но, как оказалось, зря. Там хранились ещё какие-то скрытые данные (это был счётчик, который vape использовал для определения уровня жидкости в вейпе, которые нужно отобразить). Я не буду показывать всю таблицу, так как она занимает более 100 строк, но вот выдержка из неё.

INDEX (#)

OFFSET (HEX)

LENGTH (HEX)

FRAME H (PX)

FRAME V (PX)

CATEGORY

SEQ (#)

0

0

6400

80

160

Background

0

1

6400

2880

72

72

Battery Icon

0

2

8C80

2880

72

72

Battery Icon

1

19

33D00

6400

80

160

Vaping Animation

0

20

3A100

6400

80

160

Vaping Animation

1

72

D53E2

6400

80

160

Plugin Background 3

0

73

DB7E2

E9A

21

89

Charger Logo Wipe

0

74

DC67C

E9A

21

89

Charger Logo Wipe

1

104

F8000

4

N/A

N/A

Total Vape Time x0.01s (LSB->MSB)

N/A

105

F8004

1

N/A

N/A

Vape In Use Flag (0xBB)

N/A

Создание инструментов

Когда весь SPI Flash был расписан, я (не без помощи ChatGPT) смог сделать пару пользовательских инструментов: сплиттер и переупаковщик Flash‑изображений. Я также использовал инструменты преобразования библиотеки Rinky‑Dink UTFT для замены данных изображения (т. е. для поддержки пользовательских тем). Представьте себе: поддержка пользовательских тем/скинов на вейпе — это реальность! Без помощи производителя!

Сплиттер флэш-памяти в действии
Сплиттер флэш-памяти в действии
Переупаковщик
Переупаковщик

Для чего я этим занялся

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

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

Реально Windows 95?

Ну… не совсем. Мне нужна была интересная и совершенно другая тема для пользовательского интерфейса, а я не настолько артистичен, чтобы создавать тему Doom (я пытался, но не смог придумать ничего, что бы работало в рамках ограничений оригинальной прошивки).

Используя лишь копию Windows NT 4.0 (по сути, корпоративную/профессиональную версию Windows 95), несколько виртуальных машин, инструменты для создания скриншотов и записи, а также Microsoft Paint, я смог создать пользовательский интерфейс, который точно воссоздаёт ностальгический интерфейс Windows 95 на крошечном пространстве 80×160.

Совет: если вам нужно часто перепрограммировать устройство, использующее внешнюю (последовательную) микросхему памяти, подумайте о том, чтобы добавить или сделать для неё разъём. Кроме того, вейпы, использующие 2-контактный микрофонный элемент для определения вдыхаемого воздуха, можно активировать замыканием контактов на землю с помощью кнопки или даже ёмкостной нагрузки пальцем. Если вейп требует наличия нагрузки, подойдёт небольшая галогенная лампочка.

Главный экран

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

Увеличенная в 4 раза имитация созданной мной темы Windows 95.
Увеличенная в 4 раза имитация созданной мной темы Windows 95.
Разобранный вейп Kraze с разъемом SPI Flash для удобства тестирования
Разобранный вейп Kraze с разъемом SPI Flash для удобства тестирования
Разобранный вейп Kraze с подключенной SPI Flash для удобства тестирования
Разобранный вейп Kraze с подключенной SPI Flash для удобства тестирования

Уровень заряда батареи

Значок батареи, хотя и выглядит тривиально, требует много ручной работы. Начиная с Windows 95 и заканчивая XP, стандартные значки батареи в пользовательском интерфейсе Windows были очень ограниченными: полный, наполовину, почти пустой и пустой. Мне пришлось копировать ряды пикселей и выравнивать их по нужным уровням, а затем вручную дорисовывать пиксели там, где это требовалось. Я также использовал немного более детализированный набор иконок из Windows XP, который добавил немного больше яркости в левую часть значка, а не однотонного синего цвета. Хотя это несколько нарушает «чистоту» набора иконок, улучшение внешнего вида стоило того, чтобы пойти на компромисс.

Анимация батареи
Анимация батареи
Набор значков взят из systray.exe Windows 95/NT 4.0
Набор значков взят из systray.exe Windows 95/NT 4.0
Набор значков взят из файла batmeter.dll Windows XP
Набор значков взят из файла batmeter.dll Windows XP

Уровень жидкости в вейпе

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

В конце концов я решил, что у меня достаточно места, чтобы сделать самое крошечное в мире окно Проводника с шестью маленькими значками размером 16×16. Я выбрал значки, которые можно увидеть в корневом каталоге C:: папка, пакетный файл, системный файл, приложение, файл настроек.ini и неизвестный файл (тот, на котором изображён маленький логотип Windows). По мере того как жидкость для вейпа заканчивается, иконка удаляется из окна. Как только микроконтроллер посчитает, что жидкость полностью исчерпана, мигающая иконка папки становится почти аналогом аналогичного явления на компьютерах Mac, если он не может найти операционную систему для загрузки.

Анимация зарядки

Это было ещё одной проблемой, в основном из-за ограниченного размера анимации: тридцать кадров размером 21× 89, расположенных не по центру на статичном фоне. Кроме того, прошивка задерживает воспроизведение последней анимации примерно на секунду, поэтому любой цикл анимации должен быть полностью остановлен на последнем кадре.

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

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

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

Это  имитация анимации зарядки
Это  имитация анимации зарядки
Выделенная часть — то, что можно анимировать
Выделенная часть — то, что можно анимировать

Вейп-анимация

Этот этап, пожалуй, был самым забавным, но в то же время самым сложным в реализации. Я знал, что хочу использовать заставку для анимации парения, но какую именно? Мне нужна была заставка, которая была бы одновременно культовой и в то же время зацикленной. «Flying Windows» были конкурентом, но плохо масштабировались и, из‑за своей случайной природы, плохо зацикливались. По той же причине была пропущена трёхмерная «Flower Box» (и в любом случае, зацикливание раз в секунду выглядело бы не очень хорошо). 3D‑лабиринт, 3D‑текст и простые графические заставки тоже были недоступны… так что же осталось? В итоге осталась только одна заставка: Трубопровод.

Анимация парения на вейпе
Анимация парения на вейпе
Скриншот заставки на виртуальной машине
Скриншот заставки на виртуальной машине

3D Pipes — одна из самых известных заставок эпохи Windows 95, и хотя она генерировалась случайным образом, в ней были относительно чёткие переходы, что упрощало анимацию зацикливания. Она также хорошо масштабировалась как с точки зрения разрешения, так и по времени, но её было очень сложно записывать.

В конце концов я решил запустить версию Windows 95 на виртуальной машине Windows XP с настраиваемым размером экрана, максимально приближенным к соотношению сторон 1:2. После записи экрана мне нужно было выбрать последовательность, которая выглядела лучше всего, извлечь из видео 16 кадров, уменьшить их масштаб до 80×160, и только после этого я получил анимацию в виде зацикленной заставки, но результат стоил затраченных усилий.

Я продолжил ковыряться в вейпе и нашёл ещё кое-что интересное.

Секретный порт

Во время первоначальной разборки я заметил, что линии программирования SWD (Serial Wire Debug) микроконтроллера выведены на порт USB‑C, но необычным способом. Линии CC1/CC2 использовались не только в качестве обычных разъёмов 5.1k, позволяющих зарядным устройствам USB‑C распознавать вейп, но и в качестве разъёма для программирования. Мне пришлось изготовить специальный кабель для взаимодействия с ним, но я смог использовать свой Segger J‑Link для связи с микроконтроллером на месте. И вот он, бонус: прошивка полностью читаема, без какого‑либо шифрования или защиты от считывания!

Специально изготовленный отладочный кабель для отладки электронных сигарет с SWD на линиях CC1/CC2.
Специально изготовленный отладочный кабель для отладки электронных сигарет с SWD на линиях CC1/CC2.
Segger J-Link Commander имеет доступ к встроенному микроконтроллеру
Segger J-Link Commander имеет доступ к встроенному микроконтроллеру

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

Время парения

Счётчик использования/времени вейпа ровно через 10 секунд использования. 0x3E8 = 1000 или 10,00 секунд
Счётчик использования/времени вейпа ровно через 10 секунд использования. 0x3E8 = 1000 или 10,00 секунд

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

Только после того, как я решил проверить разницу во внешней SPI Flash между «затяжками», я заметил, что байты меняются в районе расположения 0xF8000, в море пустых/0xFF байтов. Стирание байтов из мест 0xF8000-0xF8004 привело к тому, что счётчик жидкости для вейпа сбросился и стал показывать, что устройство полное.

Поскольку датчики вдыхания вейпа обычно включают 10-секундный тайм‑аут, я решил запустить 10-секундную «затяжку» и заметил, что ячейка памяти обновилась до 0×3E8, что соответствует 1000 в десятичной системе счисления. Тогда было легко определить, что микроконтроллер подсчитывает время испарения с точностью до 0,01 секунды.

Работа с буфером

Поскольку у меня был доступ к памяти микроконтроллера почти в режиме реального времени, я решил экспериментально определить, где данные из SPI Flash копируются в оперативную память. Поскольку я уже знал, что микроконтроллер использует DMA для потоковой передачи данных изображения с флэш‑памяти SPI, я решил, что смогу заполнить все его содержимое понятным для человека текстом (в моем случае я выбрал последовательные копии сценария «Bee Movie») и наблюдать за изменением содержимого ОЗУ в Segger J‑Мем. Этот метод сработал, и стало очевидно, где в оперативной памяти находится буфер DMA!

Копии сценария Bee Movie во флэш-памяти SPI отображаются в буфере RAM
Копии сценария Bee Movie во флэш-памяти SPI отображаются в буфере RAM

Скрытые данные

От скуки и желания повторно протестировать анимацию зарядки во время разработки я быстро подключал и отключал питание к порту зарядки. После нескольких последовательных быстрых подключений и удалений я увидел, что на чёрном экране появился красный текст. На нем было написано «GV‑K23 0904V1», и попытка перехватить его была трудной, пока мне не пришла в голову идея использовать J‑Link Commander для остановки процессора сразу после старта.

Учитывая, что на экране был текст, но в дампе прошивки текстовых строк не наблюдалось, я решил, что это должно быть растровое изображение. И оказался прав. Оно хранилось в самом конце прошивки. Если определить, где оно находится в дампе, было просто, то попытаться восстановить его из дампа — нет. Из‑за лишней подложки в 0×00 байт (по сути, чёрной, если интерпретировать её как RGB565), которая не совпадала с 60-пиксельными/120-байтными строками, пришлось долго экспериментировать с размерами и смещениями изображения, пока я не получил разборчивую картинку. Даже сейчас я всё ещё не уверен, что захватил весь битмап.

Та самая картинка
Та самая картинка
Визуализация дампа флэш-памяти прошивки
Визуализация дампа флэш-памяти прошивки
Так выглядело скрытое изображение
Так выглядело скрытое изображение

Что было дальше

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

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

Надеюсь, что этот проект будет расширяться и дополняться. И мы найдём новые способы использования начинки одноразовых вейпов с экранами. А ещё очень жду какого-нибудь умельца, который сможет запустить на таком же вейпе Doom!

Спасибо за внимание!

 

Источник

Читайте также