Скрытый машинный код в комментарии BASIC: как разработчики прятали секреты в 1980 году
В июле 1980 года журнал Recreational Computing опубликовал листинг игры The Wizard's Castle — одного из первых рогаликов на BASIC для микрокомпьютера Exidy Sorcerer. Первая строка программы выглядела безобидно: 10 REM"(C2SLFF4. На первый взгляд это просто комментарий, который интерпретатор BASIC про

В июле 1980 года журнал Recreational Computing опубликовал листинг игры The Wizard's Castle — одного из первых рогаликов на BASIC для микрокомпьютера Exidy Sorcerer. Первая строка программы выглядела безобидно: 10 REM"(C2SLFF4. На первый взгляд это просто комментарий, который интерпретатор BASIC пропускает. Однако за этой абракадаброй скрывался исполняемый машинный код для процессора Z80. Разработчики использовали хитрость: строка REM загружается в память, но не выполняется как BASIC, а затем через POKE и CALL управление передается на этот код. Без него игра не запускалась. Эта история — яркий пример инженерной смекалки и защиты от пиратов в эпоху ранних домашних компьютеров.
Как комментарий стал машинным кодом
The Wizard's Castle, написанная на BASIC для Exidy Sorcerer, использовала необычный прием. Первая строка программы содержала не просто комментарий, а закодированную последовательность байтов, которая при загрузке в память представляла собой машинный код для Z80. Интерпретатор BASIC, встречая команду REM, пропускает остаток строки, но сама строка все равно сохраняется в памяти. Автор игры воспользовался этим, чтобы спрятать исполняемый код внутри комментария. Когда игра запускалась, BASIC-код с помощью команд POKE и CALL передавал управление на этот скрытый участок памяти, и машинный код выполнялся. Таким образом, игра не работала без этой строки, что делало ее защищенной от случайного копирования или модификации.
Как это работает: технические детали
Ключ к пониманию — в том, как Exidy Sorcerer обрабатывает строки BASIC. Каждая строка хранится в памяти в виде последовательности байтов: сначала два байта адреса следующей строки, затем номер строки, затем токены команд и данные. Команда REM кодируется одним байтом (0x91), после которого следует все, что идет до конца строки. Интерпретатор не проверяет содержимое после REM — он просто переходит к следующей строке. Таким образом, после REM оказывается машинный код, который не выполняется как BASIC, но находится в памяти. Чтобы его выполнить, нужно передать управление на этот адрес. В игре это делается через POKE, который записывает адрес скрытого кода, и CALL, который его вызывает. Строка 10 REM"(C2SLFF4 содержит 11 символов после REM. Каждый символ соответствует определенному байту в кодировке ASCII Exidy Sorcerer. Например, символ «"» имеет код 0x22, «» — 0x5F, «(» — 0x28, «C» — 0x43, «2» — 0x32, «S» — 0x53, «L» — 0x4C, «F» — 0x46, «F» — 0x46, «4» — 0x34. Эти байты образуют последовательность, которая при правильной интерпретации является кодом Z80. Конкретно этот код, вероятно, инициализирует какие-то переменные или подготавливает графику. Без этого кода игра не работала корректно — например, могла вылетать или показывать неверные данные.
Почему разработчики прятали машинный код в комментариях?
В конце 1970-х — начале 1980-х годов компьютеры были медленными и имели мало памяти. BASIC был интерпретируемым языком, что делало его удобным для написания программ, но медленным для выполнения. Машинный код работал намного быстрее, но требовал ассемблера или ручного кодирования. Разработчики часто смешивали BASIC и машинный код, чтобы ускорить критически важные участки, такие как графика или ввод-вывод. Однако публикация листинга в журнале создавала проблему: как передать машинный код, если журнал печатает только BASIC? Решение — спрятать машинный код в REM-строке. Это было не единственным случаем: подобные трюки использовались и в других играх, например, в некоторых программах для TRS-80. Кроме того, такой метод служил защитой от копирования: если кто-то перепечатывал листинг вручную, он мог случайно пропустить или исказить строку REM, и игра не запускалась. Это был простой, но эффективный способ обезопасить свой труд.
Предыстория и контекст: почему это важно
Эта история интересна прежде всего ретро-энтузиастам и исследователям истории вычислительной техники. Она показывает, как разработчики обходили ограничения платформы и как публикации листингов могли содержать скрытые элементы. Для современных программистов это напоминание о том, что даже в простых комментариях может быть скрыт функционал. В контексте России и СНГ, где компьютеры серии Exidy Sorcerer были редкостью, эта история может быть менее известна, но она является частью глобального наследия раннего программирования. Подобные трюки встречались и на других платформах, например, на ZX Spectrum, где разработчики прятали код в строках REM или в неиспользуемых переменных. Это было время, когда каждый байт памяти был на счету, а программисты проявляли чудеса изобретательности.
Что будет дальше: восстановление и новые открытия
Сейчас, благодаря эмуляторам и инструментам дизассемблирования, можно восстановить исходный код и понять, что именно делал скрытый машинный код. Возможно, найдутся и другие подобные примеры в старых листингах, которые еще не были обнаружены. Это также повод для сообщества ретро-вычислений выпустить исправленные версии игр, где скрытый код будет задокументирован. Современные исследователи уже начали анализировать такие программы, и, возможно, вскоре мы узнаем больше о том, как работала The Wizard's Castle и другие игры того времени.
Итог
Строка 10 REM"(C2SLFF4 — это не просто комментарий, а хитрый способ спрятать машинный код в BASIC-программе. Этот трюк позволял разработчикам ускорять игры и защищать их от простого копирования. История демонстрирует изобретательность программистов 80-х и напоминает, что даже в безобидных комментариях может скрываться нечто большее. Для ретро-энтузиастов и историков технологий это ценный артефакт, показывающий, как ограничения платформы рождали нестандартные решения.