Давным-давно (в
восьмидесятые годы) почти в другой галактике (в СССР) жил странный
советский народ.
Все у этого народа было
не как у людей. И
главным отличием этих
существ была неодолимая любовь к трудностям...
БК0010
- первый (и последний)
советский массовый домашний компьютер. Вместе с
компьютером потребитель получал
интерпретатор "языка высокого уровня" Фокал
(изобретенного в лабораториях DEC в шестидесятые годы) с которым шли
первые компьютеры PDP (легендарной
PDP-11 ещё не родилось, а Фокал уже был)
или, так называемый, "Вильнюсский" Бейсик,
поставляемый с более поздними моделями,
а еще позднее и то и другое (Фокал в "блоке МСТД"). Единственным
устройством для хранения
программ и данных, предусмотренным заводом-изготовителем для этого чуда
советской техники был бытовой магнитофон, на который через примитивный
аудиовыход БК со скоростью ~1200 бод можно было записывать информацию.
И
пользователи копили эти программы бобинами, стопками кассет МК-60, на
которых-же и производился обмен программами между ними. Постепенно,
времена и приоритеты менялись
- некоторые пользователи просто забросили свои БК в пользу более
прогрессивных РС, а некоторые обзавелись контроллерами дисководов и
перешли к работе на них. А к середине девяностых про БК, похоже,
окончательно забыли. Теперь с БК реально уже никто не работает. Но, я
уверен, бобины и кассеты с записанными на них произведениями остались
практически у всех бывших пользователей БК. И
иногда хочется
посмотреть, что же на них...
Содержание:
Однажды
мне стукнула в голову мысль "сохранить для потомков" свои программы,
которые я писал для БК пятнадцать лет назад. И я с удивлением ;)
обнаружил, что не имею возможности прочесть данные с моих бобин ни на
одном из имеющихся у меня навороченных компьютеров - ни в одном из них
почему то не предусмотрено БК-совместимого магнитофонного интерфейса. И
это повергло меня в пучину ПНИР (Псевдонаучно-исследовательской
работы),
целью которой было обучение компьютера чтению данных с магнитофонных
лент и дальнейшее приведение этих данных в удобочитаемый вид, а
результатом - представленные ниже утилиты. Очевидно,
что снятие информации с магнитофонных лент возможно только через
аудиокарту и очевидно (мне по крайней мере), что программы считывания и
преобразования следует писать под один из вариантов Unix, чтобы
обеспечить их переносимость. Первым
кандидатом на такую ОС оказался Solaris,
лучший вариант Unix на момент создания версии
1 (да и сейчас). Через некоторое
время потребовалось поддтвердить тезис о пользе Unix c точки зрения
переносимости. и была создана версия 2,
обеспечивающая работу как под
Solaris, так и под Linux. Вот, что, собственно, было сделано и
выставляется сейчас для всеобщего рассмотрения.
Внимание!
Данные, излагаемые мною далее получены при анализе отрывков нескольких
руководств по БК, схеме компьютера, дизассемблированных кодов Монитора
БК и осциллограмм снятых с выходов БК. Поэтому они не претендуют на
полноту и точность. Хотя, на основе этих данных и созданы успешно
функционирующая программы, сведения, очевидно, не свободны от огрех. Я
выражаю особую признательность П.
Б. Эльтерману
за предоставленные им личные записи и результаты его экспериментов с
драйвером магнитофона, которые позволили серьезно ускорить эту работу.
Мне так-же хотелось бы выразить отдельную
благодарность Кириллу
Бухарову за проявленное им терпение при тестировании
Linux-версий
программ.
Особое
Внимание!
ОС Linux является наименее
документированным и наиболее
"глюкавым" вариантом Unix на сегодняшний день. Автор
снимает с
себя всякую моральную ответственность за возможные повреждения вашей
информационной среды (в виде, например, падающих модулей ядра) в случае
использования bkread под этой ОС. В настоящее время тестирование
проводилось под следующими клонами Linux и звуковыми
системами:
Прежде
чем описывать входящие в пакет утилиты, я приведу краткое описание
способа, принятого в БК для записи информации на ленту. Для кодирования
записываемых данных используются последовательности импульсов,
составляющие передаваемые данные и служебную информацию.
Логически данные
(записанный файл) выглядят
на ленте так:
Стартовая
синхропоследовательность
Маркер начала
Заголовок
Данные
Концевая
синхропоследовательность
С точки зрения
читающей программы стартовая
настроечная последовательность
представляет собой 100008 нулевых одиночных
импульсов (один
импульс - один период сигнала см. рис.). Длина (продолжительность)
такого импульса в дальнейшем определяет "эталонную единичную длину" для
всех последующих данных.
Рисунок. Одиночный
импульс.
Маркер начала
это 108
нулевых одиночных импульсов, заголовок
- 248 байт информации о записаном файле и
следующие за этим
108
нулевых импульсов, данные
- это,
собственно, данные файла, заканчивающиеся двухбайтовой контрольной
суммой, концевая
настроечная
последовательность
- 4008 нулевых одиночных импульсов. Все
элементы, кроме массива данных,
заканчиваются
синхроимпульсами, за которыми следует единичный бит (синхропоследовательностью).
Каждый бит кодируется двумя импульсами - информационным и
синхронизирующим. Нулевой бит кодируется двумя одинаковыми импульсами
одиночной длины (см. рис.). Первый импульс своей длительностью
определяет значение бита ("0"), второй - синхронизирующий.
Рисунок. Нулевой
бит.
Единичный бит кодируется первым импульсом, с полупериодом вдвое больше
одиночного (вчетверо длиннее) и следующим за ним синхроимпульсом
одиночной длины (см. рис.).
Рисунок. Единичный
бит (реально).
Реально, при записи амплитуда единичного импульса понижается вдвое
соответственно, в идеале при воспроизведении его размах также должен
быть меньше (см. рис.). Однако, за счет нелинейности частотных
характерисик трактов магнитофонов и выходного тракта БК, при считывании
можно считать что амплитуда импульсов одинакова и, скорее всего именно
поэтому драйвер магнитофона БК так и запрограммирован.
Рисунок. Единичный
бит (идеально).
Синхроимпульс
представляет собой одиночный импульс утороенной длины. Данный тип
импульса в комбинации с единичным битом образует синхропоследовательность
и используется для
обозначения границ элементов, образующих файл на ленте. Синхроимпульс
также передается с половинной амплитудой. Синхропоследовательность,
образующую разделительный элемент между полями в файле можно видеть на
рисунке.
Рисунок.
Синхропоследовательность.
Фактически, синхропоследовательность это последовательность из
импульсов тройной, двойной, а, затем, единичной длины. Биты
записываются в порядке увеличения разряда в байте, т.е. нулевой бит -
первым, седьмой - последним. Для примера на следующем рисунке приведена
последовательность, импульсов образующая комбинацию битов "0101" в
виде,
выводимом драйвером БК.
Рисунок.
Последовательность бит "1010"
На рисунке обозначены значения каждого импульса. При этом "1D" и "0D"
означают стартовые (значащие) импульсы в двухимпульсных посылках,
кодирующих единичный и нулевой биты соответственно, а "0S" означает синхроимпульс (по
длительности
совпадающий с "0D").
Теперь
можно рассмотреть поля файла отдельно.
Внимание! Данные
длиной в слово хранятся и записываются в БК в формате LSB (младший байт
первый), что следует учитывать при написании или портировании утилит
работы с файлами под системы, использующие MSB формат (большинство RISC
систем).
Как
уже указывалось, в начале файла записывается настроечная
последовательность из 100008 нулевых одиночных
импульсов,
которая используется для детектирования начал файла и настройки ПО на
скорость воспроизведения данных. В конце настроечной последовательности
записывается синхропоследовательность.
Маркер
начала, как это следует из косвенных данных к которым у меня был
доступ, должен содержать параметры записи (типа, инверсии данных,
порядка байт и пр.). Однако, так-как в реальных условиях никакие опции
не используются, и не заложены в алгоритмы работы драйвера магнитофона
БК, можно считать, что он содержит 108 нулевых
одиночных
импульсов и синхропоследовательность
в конце. Заголовок
содержит следующие поля:
Байты
Записанная
информация
0-1
Адрес
памяти, с которого записан файл
2-3
Длина
области данных
(без контрольной суммы)
4-248
Имя файла
Таким образом, максимальная длина имени файла - 16 символов (байт).
Если имя файла содержит меньше 16 символов, ПО БК, как правило,
заполняло остающиеся байты пробелами (408).
Заголовок
записывается сплошным потоком бит, никаких разделителей байтов не
предусмотрено. В конце заголовка записывается 108
нулевых
импульсов и синхропоследовательность.
Данные
так же записываются сплошным потоком бит без разделителей байтов в
потоке.
В
конце записываемого массива данных помещается двухбайтовая контрольная
сумма, которая получается в результате 16 разрядного беззнакового
суммирования с переносом всех байтов массива данных. В терминах
ассемблера алгоритм подсчета контрольной суммы выглядит так:
MOV START, R1 MOV LENGTH, R2 CLR R0 LOOP: MOVB (R1)+, R3 BIC #177400, R3 ; СБРОС СТАРШИХ БИТ В СЛУЧАЕ ПЕРЕНОСА ЗНАКА ADD R3, R0 ADC R0 ; УЧЕСТЬ ВОЗНИКНОВЕНИЕ ПЕРЕНОСА SOB R2, LOOP ... ; R0 СОДЕРЖИТ КОНТРОЛЬНУЮ СУММУ
Сразу за
контрольной суммой записывается
импульс шестикратной длительности, назначение
которого - точно
обозначить конец данных и вызвать гарантированную ошибку в случае
пропуска данных при чтении.
Назначение
конечной синхрополедовательности мне не известно и не понятно.
Алгоритм
чтения данных с ленты на основе вышеизложенного получается довольно
простым, хотя и содержит несколько неочевидных моментов, суть которых
рассмотрена после описания:
Алгоритм
чтения
Анализировать сигнал, пока на входе не появится группа из NSTART однородных импульсов.
Настроить временные интервалы на основе среднего из NTUNE последующих интервалов.
Подсчитать контрольную
сумму и
убедиться
в правильности считывания данных.
Некоторые
пояснения
Константы NSTART и
NTUNE в
оригинальном драйвере равны 40008
и 2008 соответственно. Хотя искуственное
разделение
непрерывной настроечной последовательности может показаться неразумным,
связано оно с определенными особенностями функционирования контроллера
DRAM на КР1801ВП13, которые при работе программы записи на МЛ могут в
начале последовательности ускорить работу ЦП за счет временного
уменьшения времени доступа к оперативной памяти как результата работы
алгоритмов (все временные задержки при записи формируются программными
циклами), в результате чего при чтении могли бы неправильно быть
вычислены счетчики, ответственные за измерение длительности импульсов.
Однако, при чтении фактически пропускается NSTARTимпульсов,
что гарантирует прохождение интервала времени, достаточного для
стабилизации скорости, а счетчики формируются уже на основе последующих
NTUNE импульсов.
Аналогично, в оригинальном драйвере не проверяется
значение
следующего за синхроимпульсом бита в синхропоследовательности,
алгоритм просто читает (и пропускает) следующий за синхроимпульсом
бит.
Утилитаbkread - основная
программа пакета
осуществляет чтение с магнитной ленты файлов, записанных по алгоритмам,
принятым в БК. Хотя программа функционирует согласно оригинального
алгоритма БК, написана она была без знания оного, на основе анализа
осциллограмм. Затем, некоторую ясность внесли чтения смутных мануалов к
компьютеру, что дало возможность сделать программу полностью рабочей, а
появление материалов Эльтермана - закрепить полученное, исправить
мелкие
недочеты и довести программу до "публичного" вида. Не могу не отметить,
что при помощи bkread
удалось
перенести на современные носители файлы со всех
доступных
автору
лент.
bkread
читает информацию с
магнитофона через аудиовход. Вызов утилиты производится следующей
командой:
$bkread [ключи] [имя]
после этого программа приступает к чтению информации с ленты. Если
параметр имя
отсутствует, то все
встречающиеся при воспроизведении файлы сохраняются, в текущей
директории, если задано определенное имя,
то сохраняются только файлы с совпадающим именем. В случае, если в
директории уже имеются файлы с таким именем то к имени прибавляется
префикс ".nnn", где nnn -
возрастающее число,
гарантирующее от записи файла поверх существующих. В
командной строке можно задавать следующие ключи:
Ключи управления аудиовходом:
-r число
- число задает
коэффициент усиления картой входного сигнала. Значение должно
находиться
в пределах от 0 до 100 (минимальное и максимальное усиление). Если ключ
-r не задан, то коэффициент усиления зависит от особенностей ОС. В
случае Solaris коэффициент усиления остается равным последнему,
установленному одной из утилит (в т.ч. и bkread).
-m число
- коэффициент
усиления цепи мониторинга входного сигнала. Значение должно находиться
в
пределах от 0 до 100 (минимальное и максимальное усиление). Если ключ
-r
не задан, то коэффициент усиления зависит от особенностей ОС. В случае
Solaris коэффициент усиления остается равным последнему, установленному
одной из утилит (в т.ч. и bkread).
-R число
- задать
альтернативный коэффициент дискретизации аудиоданных, число
соответствует количеству снимаемых с карты за секунду значений.
Задается
либо в виде точного значения (-R
96000),
либо в тысячах (-R 44),
что оставлено для
совместимости с версией 1. Значение по умолчанию - 44100 (т.е. -R 44100, CD quality).
-A спец.
файл -
задать
альтернативное аудиоустройство, полезно если у вас установлено более
одной аудиокарты или используются нестандартные имена файлов устройств.
-M спец.
файл - (только
под Linux!) задать альтернативное микшерное устройство,
полезно
если у вас установлено более одной аудиокарты или используются
нестандартные имена файлов устройств.
Ключи управления анализатором:
-a число
- задает
максимальное количество адаптаций скорости при чтении файла. В bkread используется
адаптивный алгоритм
анализа сигнала, позволяющий по ходу чтения динамически изменять
скоростные коэффициенты, что позволяет компенсировать неравномерность
скорости воспроизведения (записи) на магнитофоне. По умолчанию
количество таких адаптаций неограничено.
-e число
- задает уровень
нуля. По умолчанию нулевому уровню соответствует среднее значение между
максимальным и минимальным значениями амплитуды, выдаваемыми
аудиокартой. В некоторых случаях, например при искажениях сигнала или
при помехах бывает полезно сместить уровень со среднего значения в одну
из сторон. Значение должно лежать в пределах от 0 до 255 так-как bkread использует
8-битный режим ввода.
-s число
- задает
количество единичных импульсов, используемых при определении
синхропоследовательности. По умолчанию используется число 31408
(несколько меньше принятого в драйвере МЛ БК - 42008).
Впоследствии число разделяется на количество импульсов, необходимых для
получения среднего значения длительности единичного импульса по формуле
(n/218) и количество импульсов для
детектирования
настроечной последовательности по формуле (n-n/218)
соответвенно.
-p 0|1
- задает какую
часть
полупериода на входе считать единичным импульсом - отрицательную (0)
или
положительную (1). По умолчанию используется положительная часть.
Ключ -v
включает режим
вывода
расширенной диагностики (автор всегда задает этот ключ, поскольку
наблюдать за происходящим довольно интересно). Пример сессии чтения
приведен ниже. Читается содержимое монитора БК.
$ ./bkread -v -r 80 -m 20 -e 132 MONITOR Opening /dev/dsp as sound device... Opening /dev/mixer as mixer device... Recording level set by "IGain" (12) Monitoring device is "Line " (6) Fragment size set to 4096 bytes Audio: recording gain = 60 Audio: monitor gain = 40 Audio: sample_rate = 44100 Audio: edge level = 128 Analyzer: synchro tuning pattern count = 1632 Analyzer: max. number of adaptations set to unlimited
Signal Period Analyzer Line (2..40): --000000000111111111111SSSSSSSSSSSSSSSS --------------------------------------- 000000001111111111222222222233333333334 234567890123456789012345678901234567890
File Name = "MONITOR " Data Length = 20000 (octal). Data Address = 100000 (octal). Tape Checksum = 17341 (octal). Data Checksum = 17341 (octal). Saving file to: MONITOR (8214 bytes).
Listening for header synchros (S=1536; T=96)... ^CSignal (2) received. Program stopped.
Думаю, вывод утилиты с ключем -v достаточно мнемоничен, чтобы его не
комментировать. Работа прерывается по сигналу SIGINT (в терминах Unix),
в данном случае этот сигнал вызывался нажатием комбинации Ctrl-C (см.
termio(7I)).
Программа сохраняет файлы под именами, заданными в заголовках на МЛ.
Оконечные пробелы отбрасываются. Если файл с таким именем уже имеется
на
диске, bkread
записывает его под
тем-же именем, добавляя ".n" в конец (n последовательно увеличивается
до
тех пор, пока файла с таким именем не обнаружится на диске). К
bkread идет еще небольшой скрипт bk2bin,
призванный конвертировать считанные файлы в формат, понимаемый
некоторыми эмуляторами БК. Основная цель создания данного скрипта, была
несколько иная - показать насколько просто это сделать. Автор
приглашает
разработчиков эмуляторов и ПО для БК к сотрудничеству для написания
других конверторов.
Утилита dasm1
представляет собой простейший вариант дизассемблера из набора команд
процессора КР1801ВМ1 в вид текстовой формат, близкий к формату MACRO-11(tm),
позволяющий сравнительно легко разбираться в двоичных кодах программ
для БК. Фактически, dasm
представляет собой несколько доработанный вариант дизассемблера,
который
я в написал в 1988 году для ДВК-2, на которой мне довелось работать в
то
время. Командная
строка для вызова dasm
следующая:
$
dasm [-a | -b | -c | -f
forced_file] tape_file
Где ключ -a, -b и -c задают формат дополнительного вывода данных:
-a
указывает необходимость
вывода ASCII кодов;
-b
указывает необходимость
вывода байтовых кодов
-c
отменяет пословный вывод
кодов.
При всех заданых ключах (dasm
-a -b)
вывод принимает следующий вид:
Непосредственно за кодами инструкций, после восклицательного знака
(комментарий) следуют: обязательный адрес, пословная расшифровка кода
команды, ее байтовые коды, (все в восьмеричном исчислении) и ее
строковое представление.
Ключ -f задает файл форсированных меток, т.е. если (как
правило ;)
дизассемблер неверно интерпретирует участки кода как данные или как
коды, когда они таковыми не являются, то можно форсировать
интерпретацию
данных в нужном представлении.
Сам файл устанвок
имеет достаточно
примитивный формат:
<type> <addr> <label> ...
Пустые строки и комментарии в файле не допускаются; type - тип
форсируемой области, допустимые
значения c
(code) и d
(data); addr
- адрес начала области (восьмеричный); label
- имя для метки, которая будет обозначать начало области. Легко видеть,
что приведенном выше примере вывода dasm был использован файл
форсированных меток содержащий следующие строки:
d 100004 EMT_4P d 100006 EMT_6P
Длина имени метки - не более 7 символов.
Внимание! dasm - достаточно
примитивная утилита,
которая не будет совершенствоваться или исправляться в дальнейшем,
ввиду
подготовки к выходу более совершенного JDasm, идущего в составе
JavaPDP.
Это, однако, не мешает любителям программирования на C модифицировать и
дополнять программу с целью приведения ее в "божеский вид".
Утилита
focal2txt,
как и следует из имени переводит файлы из внутреннего представления
Фокала в текстовой вид. Командная
строка для вызова focal2txt
следующая:
$
focal2txt tape_file
Утилита выводит программу в текстовом представлении в стандартный
вывод. Никаких преобразований кодировок не производится, поэтому для
просмотра или печати программ следует использовать те или иные
перекодирующие утилиты. В "ближайшее время" готовится к выходу
Java-апплет для просмотра программ на языках Фокал БК-0010 и Бейсик
БК-0010, за дополнительной информацией обращайтесь по адресу imbecyle@mail.ru. Для
компиляции утилит следует сначала подправить Makefile под параметры
ваших ОС и компилятора С, а затем, командой
$
make
создать исполняемые модули.
Теоретически, данные программы должны работать под любой UNIX-подобной
ОС, хотя проверялись они мной только под Solaris 7 и 8 (Intel и SPARC)
и
некоторыми вариантами Linux с компиляторами gcc. Я буду рад новостям
относительно любых новых патформ (кроме, пожалуй, Windows), на которые
удалось перенести эти утилиты или появлению для них графических
wrapper-ов, скажем, на Tcl/Tk. Все сообщения о переносах, ошибках и
модификациях программ прошу присылать на мой E-Mail адрес - imbecyle@mail.ru.