Когда мои родители продали дом и перебрались на белоснежные просторы Великого севера, они вывезли несколько коробок моего барахла, которое долго пылилось в гараже. Мы сейчас разбираем вещи и роемся в этих коробках на случай, если в не столь далёком будущем нам самим понадобится переехать. В одной из коробок нашлась моя старая компьютерная игра-лабиринт DUNGEONS & DRAGONS™ от Mattel Electronics.
Это большая, «делюксовая» из двух игр D&D от Mattel (у Intellivision, конечно, был свой набор, а у нас был Tandyvision), вторая — DUNGEONS & DRAGONS™ компьютерная игра в жанре фэнтези. Это было портативное устройство с неожиданно привлекательной реинкарнацией игры Hunt the Wumpus, о которой мы поговорим в другой раз. Эта игра больше похожа на настолку, но в ней есть компьютерный антагонист и звуковое сопровождение.
Слово «реализация» заменено на слово «реинкарнация», поскольку, как нетрудно понять из одноимённой статьи, эти игры имеют очень мало общего, за исключением общей идеи охоты на монстра в лабиринте https://ru.wikipedia.org/wiki/Hunt_the_Wumpus.
На коробке написано «copyright 1980», но мне кажется, мы купили её в конце 1982 или в начале 1983 года. Как бы то ни было, я, наверное, тогда был маловат для такой игры: в рекламе говорилось «от 8 и старше», а мне было всего шесть или около того. В ней нужно было руководствоваться несколькими звуковыми сигналами и строить лабиринт с объектами в нём (вы, ваш соперник, дракон, сокровище и прочее подобное). Насколько я помню, мы в эту игру почти никогда не играли.
Ну что ж, лучше уж поздно, чем никогда. И, да, давайте выясним, на чём эта штука работает. (Тизер: на четырёх битах и у нас есть фото кристалла микросхемы с подписями. Читаем дальше).
Углы этикетки были слегка загнуты, но я подмазал её клеем-карандашом, в остальном она как новая, и все элементы игры на месте. В 1982 году рекомендованная цена игры была 55 долларов, а в 2023 году — все 170. Игра, определённо, должна излучать флюиды премиум-класса, чтобы оправдать такую цену (подозреваю, что мои родители купили её на одной из распродаж Kaybee Toys). Элементы игры лежат в удобном выдвижном ящичке.
Единственным в коробке, что уже не выглядело как новое, кроме самой коробки, были правила игры. Но, думаю, это не время помяло их, а мы сами, пытаясь разобраться, как играть.
Как ясно из названия, в сердце игрового процесса — пошаговое прохождение лабиринта в подземелье восемь на восемь клеток. Зубцы между клетками поля служат для установки между ними красных «стен», на которые вы будете натыкаться, когда выстроите лабиринт визуально. Игра сообщает нам о происходящем двенадцатью уникальными звуковыми сигналами. Поскольку нам нужно знать их значения, шесть нижних клавиш в левом ряду воспроизводят их по требованию (нажатием кнопки SWITCH мы переходим к следующим шести сигналам). Однако все они хорошо различимы и их значения угадываемы, поэтому я не припомню, чтобы у нас были какие-то проблемы с их запоминанием. Основная цель игры — добыть сокровища и вернуться с ними в своё убежище раньше, чем до них доберётся другой игрок, и раньше, чем дракон доберётся до вас. На повышенном уровне сложности появляются «двери», которые открываются и закрываются случайным образом. Однако это раздражает, и я уверен, что в таком режиме мы играли ровно один раз. Приличную партию вы, вероятно, сможете разыграть за 10–15 минут.
Краткая выжимка из правил находится в очень неудобном месте — на нижней стороне выдвижного ящичка. Так что, если вы потеряете буклет, вам придётся либо вынуть ящик, либо переворачивать коробку вверх дном.
Игра запитана от одной 9-вольтной батарейки, но вы можете подключить адаптер переменного тока (в комплекте его нет). На наклейке написано, что нужно заменить батарейку, если игра начинает вести себя странно. Вот это я охотно сделал бы со своей кошкой, но понятия не имею, где у неё спрятан батарейный отсек.
Mattel’овский шифр изделия выдавлен в пластике (1991-2109-E © MATTEL INC. 1980).
Фигурки довольно симпатичные. Они отлиты из металла и чувствуется приятная тяжесть. Не сомневаюсь, что вес помогает игре обнаружить их присутствие в игровых локациях, а игрокам — понять, что они купили не хлам. Вот дракон. Он проработан до мельчайших деталей.
Вот ~мышки на корм этому дракону~ бесстрашные воины.
А вот вожделенные сокровища.
Три зелёных жетона обозначают тайные комнаты игроков (начальная и конечная позиции) и местоположение сокровищницы, чтобы вернуть туда сокровища, если незадачливому герою не удастся выбраться с ними из лабиринта. Фигурка сокровищ здесь в основном для вида. Игрок, овладевший сокровищами, заберёт её себе, оставив на её месте зелёный жетон. Но выглядят они классно.
Вскрытие игры больше всего затрудняют вот эти защитные винты Mattel. Они же какое-то время использовались в картриджах Intellivision. На форумах полным-полно вопросов о том, какой насадкой их отвинтить. Точно под их резьбу не подошла ни одна из них, но, кажется, чтобы вскрыть игру, почти не повредив резьбу, достаточно хорошо подошла моя отвёртка TA2.7.
Винты вывернул, ящик достал, батарейный отсек открыл. Но это ещё не всё!
Развинченный корпус всё ещё крепко держится набором очень тугих пластиковых замков. Мне понадобилось добрых десять минут возни с пластиковым шпателем и нейлоновой монтажной лопаткой, чтобы крякнуть этот корпус (и крякал он при этом не раз. Поддевать корпус металлической лопаткой или шлицевой отвёрткой не надо, не надо и ещё раз не надо. Пластмасса очень легко гнётся. Даже я немного повредил его нейлоновым инструментом, но, по счастью, видно это только тому, кто знает, куда смотреть. Дольше всего пришлось потрудиться над той стороной, где был ящик. Место соединения двух половин утоплено, и вам действительно придётся втирать туда свой рабочий инструмент.
Половинки корпуса разделены. Это игровой планшет (а по сути клавиатура с мембранной плёнкой).
С обратной стороны — множество слоёв и токоведущих дорожек, схемы которых замыкаются при прижатии слоёв друг к другу. Линии идут столбцами и строками к ленточному соединителю небольшой логической платы.
В остальном компонентов очень мало. Динамик — здесь он остался слева за кадром — посажен на то, что когда-то, видимо, было монтажной шпатлёвкой, а теперь высохло до состояния рыхлого крошащегося комка. Кроме нескольких разбросанных по плате резисторов, пары конденсаторов и биполярного транзистора 2N2222, на плате «доминирует» 28-выводная микросхема производства Texas Instruments c обозначением M34012-N2LL в плоском DIP-корпусе, датируемый 23-й неделей 1982 года (что соответствует моим воспоминаниям о времени покупки игры). Батарейный отсек подключён к небольшому коммутатору справа.
DIP означает «dual in-line», данное сокращение обозначает самый распространённый тип корпуса — плоский, с параллельными выводами вдоль длинных сторон корпуса.
На нижней стороне платы — маркировка «MATTEL, INC. © 1980 1991-9229 REV-C». Отверстие с маркировкой FR на самом деле пустует. Просто на этом фото через него отсвечивает отражение ленточного разъёма. Судя по тому, что я здесь вижу, разъём питания должен быть с положительным полюсом на концевом контакте и тоже 9-вольтным (в руководстве об этом ничего не сказано). Ну что ж, 9-вольтные батарейки недорого стоят.
Теперь о центральном процессоре. Хотя по номеру микросхемы можно отнести его к Texas Instruments TMS34010, для них микросхема и слишком маленькая, и слишком древняя. Для детской игрушки нужно что-то простое, недорогое и массовое, и у Texas Instruments есть очень подходящий вариант.
M34012 — это, по сути, итерация микроконтроллера Texas Instruments TMS1100, который, в свою очередь, развился из TMS1000 и произошёл от TMS0100, который в 1971 году был первым в мире микроконтроллером. В этих кристаллах ОЗУ, ПЗУ и средствам ввода и вывода находятся в одном кристалле с поддержкой сегментных дисплеев и считывания нажатий. При этом требования к внешней элементной базе очень малы. Впервые TMS0100 использовали (под шифром TMS1802NC) в новаторском для своего времени карманном калькуляторе Sinclair Executive, и с этой задачей схема справилась отлично. Texas Instruments переработала конструктив TMS0100, что в 1974 году дало начало «производственной линейке» TMS1000. А в 1975 году фирма слегка модернизировала ОЗУ и ПЗУ и выпустила серию TMS1100. Микросхема M34012 спроектирована на основе p-МОП транзисторов, что позволяет ей запитываться практически напрямую от 9-вольтной батареи или другого нестабилизированного источника с близким напряжением.
Реже применяемый по сравнению с n-МОП, p-МОП — это тип транзистора, где основными носителями заряда являются не электроны, а дырки, а внутренняя ёмкость, как правило, выше.
В отличие от другого нашего любимого игрового микроконтроллера, изготовленного по техпроцессу MOS Technology 7600, по которому никто не нашёл ни краткой спецификации, ни даже рекламного проспекта, по семейству TMS1000/1100 документации столько, что её хватит даже для упрощения написания MAME-драйверов для таких игр. Программируемая логическая матрица (ПЛМ) на выходе и даже ПЛМ дешифровки инструкций были настраиваемыми: пришлите обе ПЛМ и масочное ПЗУ в Texas Instruments вместе с пачкой денег и вы получите огромное количество тестовых игровых контроллеров практически едиными блоками. Texas Instruments использовали их не только в своих собственных игрушках Speak & Spell для потребительского рынка, но и для игры Simon от Milton Bradley (теперь — Hasbro), видеоигры Merlin от Parker Brothers и Microvision от Milton Bradley, первой игровой консоли со сменными картриджами (после того как энергопотребление 8021-го процессора Intel оказалось слишком высоким). К 1979 году фирма Texas Instruments уже не в первый раз раз продала около 26 миллионов схем этого семейства в год, а в конце восьмидесятых использовались уже её более новые версии, созданные по техпроцессам n-МОП и КМОП (комплиментарный МОП-процесс, то есть построенный на парах транзисторов n-МОП и p-МОП).
Вот снимок топологии кристалла M34012, любезно предоставленный Шоном Риддлом, у которого есть снимки кристаллов целого ряда подобных схем. Я описал кристалл по руководству программиста и раннему патенту Texas Instruments, где был изображён кристалл TMS1000. Самые крупные участки на кристалле занимают 512 бит ОЗУ (организованные в 128 тетрад [1 тетрада (nybble) = 4 бита или пол-байта]) и 2 Кб масочного ПЗУ
Запись информации в ПЗУ производится в процессе изготовления микросхемы — при формировании металлизации. Используются для хранения данных, которые не потребуется изменять
А ещё 64 тетрад и 1 Кб ПЗУ в TMS1000, а также две ПЛМ.
Тактовая частота MAME оценивается в 475 кГц, что основано на номинальных значениях ближайших к кристаллу резистора и конденсатора, хотя это значение и имеет тенденцию к колебаниям. Все инструкции выполняются в один такт. Микросхема имеет 4 входа (K-входы для клавиатурных рядов) и 19 выходов, объединённых в две группы, одна группа из 8 одновременно задаваемых из выходного пятибитного регистра на выходе ПЛМ (O-выходы) и 11 управляемых индивидуально (R-выходы). В Texas Instruments R-выходы предусмотрены для управляющих шин, а O-выходы — для светодиодной индикации. Тем не менее в данной игре все O-выходы и почти все R-выходы (кроме одного, идущего к динамику) обслуживают клавиатуру. Поскольку входа четыре, клавиатура делится на две половины и каждая состоит из четырёх строк [это видно в том же файле Шона Риддла по ссылке]. Рабочее напряжение в игре подаётся по отдельной выходной шине на каждый из 9 столбцов в каждой половине (таким образом, всего используется 18 шин). Нажатия кнопок передаются обратно на K-входы.
В схемах семейства TMS1000 используется гарвардская архитектура:
https://ru.wikipedia.org/wiki/Гарвардская_архитектура — архитектура с двумя шинами, отличительной особенностью которой является то, что для лучшей производительности используются две памяти (память команд и память данных), а также раздельные шины адреса и данных для доступа к ним.
Поэтому ПЗУ имеет отличный от ОЗУ диапазон адресов. TMS1000 работает с 43 инструкциями, 12 из которых управляются фиксированной логической схемой, а остальные ставятся в очередь ПЛМ (в TMS1100 их число увеличено до 54, и некоторые из них несколько видоизменены). Как и большинство фирм, Mattel использовала один из стандартных дешифраторов команд в виде ПЛМ Texas Instruments, а не заказывала кастомизированный. Каждая схема семейства TMS1000, включая ту, которую мы рассматриваем, имеет на выходе кастомизированную ПЛМ, что продиктовано сложностями преобразования данных из 5-битного формата в 8-битный. Для игры через MAME требуются ПЗУ и содержимое обеих ПЛМ.
В 1970-е годы родилось много странных архитектур, но семейство TMS1000 — безусловно, одно из самых странных. У TMS1000 — 4-битный накопительный регистр (accumulator — A),4-битный Y-регистр (Y), 2-битные (в TMS1100 их три) X-регистр (X) в качестве регистра адреса страницы ОЗУ, 6-битный программный счётчик (program counter — PC), 6-битный регистр возврата из подпрограммы (subroutine return register — SR, иными словами, регистр связи), 1-битная защёлка вызова (call latch — CL) во избежание случайной перезаписи SR, 4-битный регистр адреса страницы ПЗУ (ROM page address register — PA), 4-битный буферный регистр страницы ПЗУ (ROM page buffer register — PB, также используется с регистром возврата из подпрограммы), 5-битный регистр O-выходов (O), единственный бит состояния (S) который по умолчанию установлен в значение true и по биту для каждого R-выхода, индексируемого по Y (R(Y)). (K-входы считываются при помощи специальных инструкций).
Хотя каждая инструкция весит всего один байт, в схеме используется 6-битный программный счётчик, что означает, что передавать можно всего 64 байта ПЗУ, поэтому PA выбирает одну из 16 страниц. При запуске PA задаётся страница 15, а PC — 0. Программный счётчик зацикливает данные, то есть после 63-го байта идёт 0-й на той же странице. Кроме того, единственные команды перехода работают при бите состояния S в значении true. Для длинного перехода [перехода на адрес в другом сегменте памяти] или вызова нужно обеспечить S = true (то есть при необходимости нужно выполнить холостую или заведомо истинную инструкцию), задать PB желаемую страницу (LDP x) и затем выполнить переход (BR): центральный процессор поместит данные PB в PA и на новой странице начнёт отсчёт с нового PC. Вызовы (CALL) для сохранения адреса обратного перехода выполняют подкачку регистров PB и PA, таким образом вы не сможете выполнить длинный вызов в рамках подпрограммы, и, пока инструкция RETN не очистит защёлку CL, последующие вызовы не изменят значений SR и PB, которые будут, как и прежде, указывать на начальный адрес обратного перехода и страницу. После выполнения перехода, прошедшего или нет, бит состояния S снова устанавливается в true.
Исполнение программы в TMS1100 несколько усложняется: ПЗУ там дублируется, поэтому для нового второго банка добавлен набор однобитных защёлок глав (chapter latches). По аналогии с SR, PA и PB здесь у нас есть CS (chapter subroutine, подпрограмма главы), CA (chapter address, адрес главы) и CB (chapter buffer, буфер главы), все они включены, и все имеют логическое состояние «ноль». Новая инструкция COMC переворачивает значение CB. При переходе (branch) CA задаётся значение CB, а PA — значение PB. При вызове (call) CS тоже задаётся значение CA, так что обратные переходы (returns) по-прежнему работают.
Аналогичным образом, поскольку Y используется в ОЗУ в качестве индекса, всего 16 из 64 тетрад TMS1000 могут получить адрес из одного только Y. Двухбитный X служит регистром страниц ОЗУ и выбирает «file». В TMS1100 ОЗУ также дублируется, но здесь всё решается применением трёхбитного X вместо двухбитного и соответствующим изменением соответствующей инструкции LDX. Возможный недостаток конструкции состоит в том, что Y может индексировать R-выходы только при незаданном третьем бите, поэтому инструкция COMX были изменена так, чтобы менять только значение нового бита, а не дополнять весь регистр. (Значения Y от 11 до 15 задают значения R-выходов только в расширенных версиях микросхем TMS1200 и TMS1300, где таких выходов 16, а не 11).
4-битный сумматор на снимке кристалла не дублирует функцию компаратора, и на выходе сумматора может быть либо A, либо Y, либо ни одно из этих значений (небольшая полоска схемы под сумматором осуществляет выбор адреса). Перенос (carry) или заимствование (borrow), если оно реализовано, переходит к S. Арифметическое логическое устройство выполняет только операции сложения и вычитания, побитовых логических инструкций нет. С другой стороны, инструкции SBIT и RBIT могут задать быты 0 или 1 на любой позиции любой тетрады, индексируемой при помощи X и Y, а TBIT1 могут проверить значение (бита по S), поэтому любая логическая операция можно реализовать (довольно трудоёмким) способом обхода всех четырёх битов и установки соответствующих значений.
Единственный регистр, который может записывать в регистр O-вывода, — это накопительный регистр, но так как он всего четырёхбитный, пятый бит приходится брать из S. Есть инструкции memory-to-memory и даже constant-to-memory (TCMIY), но из всех регистров только накопительный может загружать и хранить данные из памяти, только он может суммировать и вычитать значения из памяти, только он может получить сигналы с K-входов (хотя вы также можете протестировать их как группу), только его значения можно сравнивать (со значениями памяти или Y, результат с S), и только он может суммировать или вычитать значение больше единицы.
Зная всё это, рассмотрим те программы, которые мы подчистую переписали из руководства программиста. Первая из них производит сдвиг на шесть тетрад в памяти, где нулевая позиция соответствует цифре наименьшего значащего разряда, как при вводе новой цифры на калькуляторе.
lshft cla ; clear A
ldata tcy 0 ; transfer constant 0 to y
l1 xma ; exchange memory indexed by Y and the accumulator
iyc ; y++, carry to S
ynec 7 ; s = (y!=7)
br l1 ; branch if true to l1
retn ; if this were a call
При вводе значения ldata накопительный регистр вместо нуля приобретает значение цифры наименьшего значащего разряда.
- А вот программа сложения двух банков по шесть тетрад. Поскольку эта программа предназначалась для калькулятора, она выполняет сложение в двоично-десятичном представлении, рассматривая каждую тетраду как цифру. X задаёт адрес назначения суммы m, переворачивая значение старшего бита. Таким образом, в TMS1100 при X, равном 0, это означает, что нужно цифры в файле 0 прибавить к цифрам в файле 4 и хранить их в файле 0 и так далее. В версии 1100 нет инструкции ALEC (A меньше константы [похоже, речь идёт о less or equal — меньше либо равно]), которая присутствовала в TMS1000. Это не позволяет напрямую проверить факт вхождения нашей цифры в диапазон, для этого нужны дополнительные ухищрения.
a040 tcy 0
cla
ad1 comx ; flip X bit 3 (note: on TMS1000 this flips both bits of X)
amaac ; add m(x,y) to accumulator, carry to S, result to accumulator
comx
amaac
br gt15 ; branch if carry set (greater than 15)
a6aac ; add six to digit. 10 becomes 16, which is zero, etc. (carry to S)
br gt9 ; greater than 10
a10aac ; add ten to digit to fix a digit less than 9
tamza ; transfer accumulator to memory indexed by Y and clear accumulator
br incy
gt15 a6aac ; 16 becomes 6, 17 becomes 7, etc.
gt9 tamza
iac ; increment accumulator, inverse of carry to S
incy iyc
ynec 7
br ad1
retn
Последовательность инструкций AnAAC представляет собой одну группу микрокоманд с множеством мнемоник, но с кодированием нестандартных констант. CLA и IAC также взаимосвязаны.
И вот, наконец, перед нами программа, которая выдаёт шесть тетрад в качестве сегментов на O-выходы, подтягивая каждый R-выход к нижнему логическому значению от 6 слева до 0 справа, чтобы дисплей знал, какая цифра отображается, в цикле до тех пор, пока на К-входах не сработает какая-либо клавиша, после чего система заблокирует ложные повторные нажатия этой клавиши. При этом предполагается, что семисегментное преобразование цифр при выводе на светодиоды происходит на выходной ПЛМ.
disp tcy 7
dis1 dyn ; y--, inverse of borrow to S
tma
iyc
rstr ; R(Y)=0
dyn
tdo ; O=A
setr ; R(Y)=1
knez ; any K bits set?
br exit ; yup
ynec 15 ; s = (y!=15) which would mean it underflowed
br dis1 ; continue digits
br disp ; start over from the left
exit tcy 15
tya ; transfer Y to A; can't load non-zero constants to A directly
delay dan ; decrement A, inverse of borrow to S
br delay; branch as long as we don't borrow
dyn
br delay
; total delay 544 cycles
Если вам действительно нужно значение K, вы можете выбрать его до задержки с помощью TKA и заранее спрятать накопительный регистр где-нибудь в памяти.
Дополнительное ОЗУ также может управляться R-выходами. Например, для микросхемы на 256×4 бит ОЗУ микроконтроллер может поместить адрес на R(0) — R(7), Chip Select на R(8) и Read/Write на R(9), выдать данные для записи на младшую тетраду O-выхода и прочитать данные с K-входов. Система мультиплексирования может сделать возможным применение этих линий для других целей, хотя мы приближаемся к моменту, где лучше подойдёт более мощный процессор. К счастью для Mattel, небольшого объёма встроенной ОЗУ оказалось более чем достаточно для управления состоянием игры, условиями игроков и одним особо разъярённым драконом.
При сборке не забудьте вернуть этот колпачок на выключатель питания и совместить отверстия в мембране слоёв клавиатуры и корпуса. Пришлось немного прижать их пальцами, чтобы всё встало на свои места.
И, да, прежде чем положить игру обратно в коробку, сыграем в неё, чтобы лучше понять, как много всего достигнуто такими скромными средствами. Отведай-ка моей булавы, литой четырёхбитный дракон с компьютерным управлением!
Краткий каталог курсов
Data Science и Machine Learning
- Профессия Data Scientist
- Профессия Data Analyst
- Курс «Математика для Data Science»
- Курс «Математика и Machine Learning для Data Science»
- Курс по Data Engineering
- Курс «Machine Learning и Deep Learning»
- Курс по Machine Learning
Python, веб-разработка
- Профессия Fullstack-разработчик на Python
- Курс «Python для веб-разработки»
- Профессия Frontend-разработчик
- Профессия Веб-разработчик
Мобильная разработка
Java и C#
- Профессия Java-разработчик
- Профессия QA-инженер на JAVA
- Профессия C#-разработчик
- Профессия Разработчик игр на Unity
От основ — в глубину
А также