Уже к моменту написания предыдущей статьи, ко мне шли очередные подопытные экземпляры тетрисов и первым был получен вот такой:
Подобные тетрисы ориентировочно стали появляться в продаже в конце нулевых. На нем я опробовал новый способ декапсуляции кристалла, боясь повторения предыдущей неудачи. Суть следующая: капля компаунда нагревается феном до такой степени, чтобы он стал мягким, но при этом не хрупким (градусов 150). Не прекращая нагрев, аккуратно подцепляем скальпелем компаунд и пытаемся его отклеить - сначала от платы, а затем, с особой осторожностью, и от кристалла. Звучит довольно просто, но на деле не очень. И хотя у меня было три удачных попытки из трех, вероятность повредить кристалл неосторожным движением пинцета все еще высока, но зато нет необходимости в использовании какой-либо химии, что в домашних условиях очень удобно.
Итак, кристалл первого тетриса:
Ожидаемо, техпроцесс гораздо плотнее. К сожалению, никаких опознавательных знаков, только число 2008, скорее всего это год создания маски.
Не буду пытаться глубоко анализировать, но если кратко: в правом верхнем углу 7.5КБ ПЗУ (которое прочитать визуально через оптический микроскоп думаю будет крайне сложно), под ней 384Б ОЗУ. В левом верхнем углу, по всей видимости, дешифратор инструкций (по нему можно попробовать идентифицировать микроконтроллер). Боюсь ошибиться, но предположу, что это 8-битный микроконтроллер, который к HT-443 не имеет никакого отношения.
Следующий тетрис попал ко мне в виде кучки внутренностей, поэтому я не знаю, как он выглядел в свои лучшие годы. На плате указана дата 12/8/2002 и судя по расположению кнопок - это типичный 1 in 9999 начала нулевых. Вот фотография его кристалла:
Абсолютно та же архитектура и почти та же площадь кристалла, только компоновка несколько отличается. 3КБ ПЗУ, 160Б ОЗУ. Опять никакой идентификации, только год(?) - 2003.
А вот и главный виновник торжества, со скромным названием Super Brick Game E-23 PLUS MARK II 96 IN 1 от тайваньской компании E-Star:
Капля компаунда у него была гораздо больше чем у предыдущих двух, поэтому с декапсуляцией я провозился пол часа, но результат того стоил:
Старый добрый HT-943 (он же HT443A0), только на год старше экземпляра из предыдущей статьи.
Для сравнения размеров кристаллов сделал групповое фото:
По четырем экземплярам, конечно, выводы делать рано, но можно предположить, что основной платформой Brick Game в начале и середине 90-х, когда они еще производились в Тайване были 4-битные микроконтроллеры Holtek, а к концу 90-х - началу 00-х, когда подобные игрушки стали массово выпускаться в Китае, основная платформа поменялась на какую-то, которая была ближе к местным фабрикам.
Чтение ПЗУ
Естественно, меня в первую очередь интересовало ПЗУ, но первый взгляд на него разочаровал - практически нечитаемо:
К счастью, оказалось, что если освещать кристалл под углом, то результат становится гораздо лучше, хоть и не идеальным:
Теперь отчетливо видны границы переходов от "нормальных" транзисторов к тем, у которых увеличена толщина слоя оксида под поликремнием, что делается для увеличения порогового напряжения транзистора, при котором он никогда не открывается (можно считать, что его там нет). На следующем изображении красными точками отмечены "нормальные" транзисторы, слой подзатворного окисла которых позволяет им открываться сигналом выборки с дешифратора:
Как же теперь превратить эту кашу битов в последовательность байт или другими словами получить образ ПЗУ с которым уже можно будет работать дальше?
В прошлой статье я немного затронул эту тему, но постараюсь здесь рассказать подробнее, тем более, что задача оказалась труднее, чем я ожидал.
Рассмотрим ПЗУ и ближайшие окрестности подробнее:
Как я уже отмечал, биты одного разряда каждого байта кучкуются группами, которые на изображении выше отмечены черными прямоугольниками. Чтобы правильно прочитать байт, необходимо определить старшинство разрядов. Для этого можно проследить внутреннюю шину (с которой соединена каждая из групп) до дешифратора инструкций, в котором старшинство восстанавливается через описание инструкций в даташите. Определенный таким образом номер разряда на изображении подписан цифрой.
Сверху можно выделить 12 повторяющихся групп транзисторов (отмечены цветными прямоугольниками) от каждой из которых на линии дешифратора вокруг ПЗУ уходит пара сигналов - прямой и инвертированный (отмечены цветными линиями соответственно группе). Естественно предположить, что этими линиями задается 12-битный адрес считываемого байта, а группы транзисторов формируют схемы регистров счетчика инструкций, стека (он здесь одноуровневый) и некоторой вспомогательной логики. Для правильного порядка чтения байт опять же необходимо определить, как линии дешифратора соотносятся с последовательностью разрядов адреса. Здесь немного сложнее, чем в случае с разрядностью битов. Все 12 разрядов соединены с 8-битной внутренней шиной, старшинство разрядов которой мы уже выяснили. Получается часть разрядов (левые и правые четыре группы) делят младшие разряды шины между собой. Поэтому дополнительно пришлось проанализировать управляющие линии регистров - они полностью совпадают для правых восьми групп и отличаются для четырех левых. Значит четыре левых бита адреса заносятся в счетчик инструкций отдельно от 8 правых из чего я сделал предположение, что они старшие. Номера разрядов адреса также подписаны на изображении.
Есть два момента, которые мне не удалось выяснить без детального восстановления схемы: какая из пары линий дешифратора несет прямой сигнал, а какая инвертированный и то же самое с битами. Получается есть 2 варианта порядка чтения из ПЗУ и 2 варианта чтения байта - вполне приемлемо.
Но на практике я столкнулся с некоторыми проблемами. Для начала я вручную прочитал по десятку байт каждого из вариантов, дизассемблировал его и не увидел там того, чего ожидал. А ожидал я, исходя из информации в даташите, что встретит меня что-то типа безусловного перехода на нулевом адресе, с которого стартует микроконтроллер после сброса. Те же безусловные переходы я ожидал увидеть по 4 и 8 адресу куда прилетают прерывания, ну или в крайнем случае reti если они не используются. Но нет, один вариант был страннее другого и мне пришлось перепроверять кучу других, менее вероятных порядков чтения ПЗУ, которые не вписывались в описанную выше теорию. Ничего не добившись в итоге, я выбрал один из первых четырех вариантов, который был более-менее нормальный и продолжил читать ПЗУ постепенно убеждаясь, что это действительно верный вариант чтения, просто авторы прошивки полностью проигнорировали прерывания и вообще использовали несколько неожиданные инструкции вроде декремента ячейки памяти сразу на старте и вывода 0xE на порт PA который никуда физически не подключен:
000: dec [R3R2] ;0F
001: timer on ;38
002: mov A, 0xE ;7E
003: out PA, A ;30
004: mov R1R0, 0xFF ;5F0F
006: in A, PP ;34
007: ja0 04C ;804C
009: mov A, 0xF ;7F
00A: call E67 ;FE67
00C: jmp 002 ;E002
Эмулятор
Итак, убедившись, что на верном пути, я продолжил расшифровывать ПЗУ, параллельно отлаживая на нем эмулятор, который я начал писать немного раньше. После нескольких дней такой работы, прошивка была восстановлена полностью, эмулятор в целом отлажен, явные ошибки в образе ПЗУ исправлены. Наконец, я увидел заветные "01" на дисплее, испытывая примерно такие же чувства, как Виктор Франкенштейн кричащий "Оно живое!".
Конечно, сначала было не так красиво - из сегментов дисплея я к тому времени добавил только часть игрового поля. Кстати, восстанавливая карту сегментов, поразился, на сколько же они располагаются не однотипно: у одной цифры сегменты адресуются одним образом, у соседней другим, часть игрового поля так, другая сяк - не завидую программистам которые писали код для этого дисплея.
Эмулятор пока сыроват (например, совсем нет звука) и не факт, что я доведу его до ума, но уже сейчас может вполне помочь в исследовании прошивки, если кому-то будет интересно написать свой эмулятор или поискать возможные пасхалки. Можно и просто поиграть, поностальгировать :) Приложение поддерживает базовые средства отладки, содержимое всех регистров и ОЗУ можно менять на лету. Написано на Python с использованием PyQt6, так что может запускаться на всех поддерживаемых этой библиотекой ОС (Linux, Windows и macOS). Исходники доступны на github, там же можно найти образ прошивки.
Скорее всего, еще остались ошибки, поэтому, если у вас есть такая же модель тетриса и вы заметите разницу в поведении с оригиналом, напишите, попробую исправить.