bkread
Утилиты работы с файлами БК001x-xx
Давным-давно
(в восьмидесятые годы)
почти в другой галактике
(в СССР) жил странный советский
народ. Все у этого народа было
не как у людей.
И главным отличием этих
существ была неодолимая любовь к трудностям...
БК0010 - первый (и последний)
советский массовый домашний компьютер.
Вместе с компьютером потребитель получал
интерпретатор "языка высокого уровня" Фокал
(изобретенного в лабораториях DEC в шестидесятые годы) с которым шли
первые компьютеры PDP (легендарной
PDP-11 ещё не родилось, а Фокал уже был)
или, так называемый, "Вильнюсский" Бейсик,
поставляемый с более поздними моделями,
а еще позднее и то и другое (Фокал в "блоке МСТД").
Единственным устройством для хранения
программ и данных, предусмотренным заводом-изготовителем для этого чуда
советской техники был бытовой магнитофон, на который через примитивный
аудиовыход БК со скоростью ~1200 бод можно было записывать информацию.
И
пользователи копили эти программы бобинами, стопками кассет МК-60, на
которых-же и производился обмен программами между ними.
Постепенно, времена и приоритеты менялись
- некоторые пользователи просто забросили свои БК в пользу более
прогрессивных РС, а некоторые обзавелись контроллерами дисководов и
перешли к работе на них. А к середине девяностых про БК, похоже,
окончательно забыли. Теперь с БК реально уже никто не работает. Но, я
уверен, бобины и кассеты с записанными на них произведениями остались
практически у всех бывших пользователей БК. И иногда хочется
посмотреть, что же на них...
Содержание:
Однажды
мне стукнула в голову мысль "сохранить для потомков" свои программы,
которые я писал для БК пятнадцать лет назад. И я с удивлением ;)
обнаружил, что не имею возможности прочесть данные с моих бобин ни на
одном из имеющихся у меня навороченных компьютеров - ни в одном из них
почему то не предусмотрено БК-совместимого магнитофонного интерфейса. И
это повергло меня в пучину ПНИР (Псевдонаучно-исследовательской
работы),
целью которой было обучение компьютера чтению данных с магнитофонных
лент и дальнейшее приведение этих данных в удобочитаемый вид, а
результатом - представленные ниже утилиты.
Очевидно,
что снятие информации с магнитофонных лент возможно только через
аудиокарту и очевидно (мне по крайней мере), что программы считывания и
преобразования следует писать под один из вариантов Unix, чтобы
обеспечить их переносимость. Первым
кандидатом на такую ОС оказался Solaris,
лучший вариант Unix на момент создания версии 1 (да и сейчас). Через некоторое
время потребовалось поддтвердить тезис о пользе Unix c точки зрения
переносимости. и была создана версия 2, обеспечивающая работу как под
Solaris, так и под Linux. Вот, что, собственно, было сделано и
выставляется сейчас для всеобщего рассмотрения.
- Внимание!
Данные, излагаемые мною далее получены при анализе отрывков нескольких
руководств по БК, схеме компьютера, дизассемблированных кодов Монитора
БК и осциллограмм снятых с выходов БК. Поэтому они не претендуют на
полноту и точность. Хотя, на основе этих данных и созданы успешно
функционирующая программы, сведения, очевидно, не свободны от огрех. Я
выражаю особую признательность П. Б. Эльтерману
за предоставленные им личные записи и результаты его экспериментов с
драйвером магнитофона, которые позволили серьезно ускорить эту работу.
- Мне так-же хотелось бы выразить отдельную благодарность
Кириллу
Бухарову за проявленное им терпение при тестировании
Linux-версий
программ.
- Особое
Внимание!
ОС Linux является наименее
документированным и наиболее
"глюкавым" вариантом Unix на сегодняшний день. Автор снимает с
себя всякую моральную ответственность за возможные повреждения вашей
информационной среды (в виде, например, падающих модулей ядра) в случае
использования bkread под этой ОС. В настоящее время тестирование
проводилось под следующими клонами Linux и звуковыми системами:
- Red Hat Linux 7.1 - OSS и ALSA 0.9.0
- Red Hat Linux 7.3 - OSS
- Debian GNU/Linux 2.2 - OSS
|
Прежде
чем описывать входящие в пакет утилиты, я приведу краткое описание
способа, принятого в БК для записи информации на ленту. Для кодирования
записываемых данных используются последовательности импульсов,
составляющие передаваемые данные и служебную информацию.
Логически данные (записанный файл) выглядят
на ленте так:
Стартовая
синхропоследовательность |
Маркер начала |
Заголовок |
Данные |
Концевая
синхропоследовательность |
С точки зрения читающей программы стартовая настроечная последовательность
представляет собой 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
Listening for header synchros (S=1536; T=96)...
Synchros detected. Pattern length = 7.
Pattern length after tuning = 8.
Patterns lengths: 0 = 8; 1 = 16.
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)
вывод принимает следующий вид:
; Disassembler V01.5.1 BK 001x-xx (bkread)
; Alexander "las" Lunev
; Start address = 100000
; Length = 20000
; Tape file name: MONITOR
; Command Operand(s) Address Codes
;
$START$:JMP MONITOR !100000: 000167 000254 167 000 254 000 "w.?."
EMT_4P:.WORD 100742 !100004: 100742 342 201 "??"
EMT_6P:.WORD 101010 !100006: 101010 010 202 ".?"
Непосредственно за кодами инструкций, после восклицательного знака
(комментарий) следуют: обязательный адрес, пословная расшифровка кода
команды, ее байтовые коды, (все в восьмеричном исчислении) и ее
строковое представление.
Ключ -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.
А. Лунев (las)
2000-2004