0
<< предыдущая заметкаследующая заметка >>
30 марта 2025
Тридцать лет и три года: формат текстов БК-0010

Тридцать лет и три года пролежал на печи... Хорошее начало, да? Тридцать лет и три года пролежал на даче архив 5-дюймовых дисков от моего первого компьютера БК-0010 — бережно завернутые в фольгу от шальных магнитных полей и уложенные в погреб. Точнее, в подвале дачи пролежало это хозяйство всего 25 лет, и десять лет назад было найдено и перевезено в Чертаново. Правда, система не включилась — скорее всего, размагнитились самописные ПЗУ:

Затем 4 ноября 2021 Александр Шмелев из Музея техники Яндекса помог скопировать информацию со старых дисков:

Не оставляя идей когда-нибудь в будущем оживить технику, я больше всего обрадовался спасенным дискам — ведь там был весь мой, так сказать, детский творческий архив. Но встал вопрос: а как вытащить тексты, которые хранились на БК0010 в своих собственных форматах? Часть текстов для совместимости с появившимися тогда персоналками и их принтерами была мной еще в середине девяностых оттранслирована в кодировку 866 DOS, некоторые даже в 1251 Windows. Но основная часть осталась в нечитаемом формате и имела расширение *.E, *.L или *.ED, что мне сегодняшнему мало о чем говорило. Я лишь помнил, что в каком-то из многочисленных форматов, принятых на БК0010, байты значением от 1 до 8 или 9 заменялись аналогичным числом пробелов, но тут в основном были гораздо более сложные кодировки. Я пробовал штурмовать задачу в 2021 и отложил.

Вы наверно скажете: но ведь есть же БК-эмуляторы? Да, есть. Но во-первых, они почти не работают. Во-вторых, не работают с моей системой — у меня был совершенно особенный БК (см фотки выше) со своей уникальной перепаянной памятью, своим драйвером дисковода, своим разогнанным процессором, своими служебными регистрами и, соответственно, своей наглухо переписанной операционной системой ANDOS, да простит меня Леша Надежин. При включении компьютер выводил на экран мой портрет (!) двухбитный конечно, а далее включались режимы кэш-диска на дополнительных страницах памяти и прочие загадки. В общем, шансов запустить конкретно мои диски на эмуляторе нет. А тыкаться и вспоминать, какие там текстовые редакторы понимали какие кодировки не хотелось и задачу доступа ко всему архиву не решало.

И вот на прошлой неделе случайно наткнулся на файл под названием KREVETKA.E — я помнил, что это стихотворение, посвященное девушке Полине («Что же есть венец творенья? Ну конечно же Полина, мироздания картина увядает без неё...»). Текст мне был известен. И начался увлекательный криптографический анализ. А что еще делать, пока болеешь гриппом? Первое, что я выяснил: если в файле заменить 0x00 на \n, то появляются строчки, соответствующие по числу и длине строчкам оригинала! Уже победа:

Однако получившиеся строчки оказались короче раза в полтора-два. И стало ясно, что число бит в этой кодировке меньше, чем 8 на символ. Возможно, плавающее число бит, просто выровнено по строкам. ChatGPT, как ни старался, тоже не смог расшифровать загадку. Я накидал утилитку, которая представляла строки цепочками битов, начиная с младшего, и пытался расшифровать с первых букв строки. Это было ошибкой — они заглавные и почти не встречаются далее в тексте. Тогда я стал изучать биты с конца строк, и дело пошло. Вскоре мне удалось выстроить биты в правильном порядке и обнаружить, что буквы кодируются нимблами (4 бита). Фактически, в старинном редакторе БК был применен принцип unicode, только для маленьких нимблов. Одним нимблом кодировались пробел и самые частые буквы русского языка, по мнению создателей такие: « оеаитнсрвлмк». Если нимбл был 0 или 1, буква кодировалась следующим нимблом, соответственно символы «пяузбйхщцэ,0» и «дыьгчжюшф.-1». Если же первый нимбл был 2, то буква кодировалась следующими двумя нимблами — там фактически повторялась вся кодовая таблица БК, которая тоже имела нюансы со своими спецсимволами и псевдографикой. Не без ошибок давалась отгадка каждой буквы. Например, поначалу я считал, что некий код кодирует букву 'е', потому что так встречалось в неком тексте, но я невнимательно его прочел и недооцнил себя — это реально был символ '@'. Хитрости на этом не заканчивались: комбинация 0E переключала в нижний регистр, 1E в верхний, 0F в латиницу, 1F в русскую раскладку, но еще при этом они также меняли регистр букв по не очень понятной схеме. Отгадывал я этот ребус на файлике с шуткой о различиях «хлорида алюминия и алюмината хлора», потому что, дескать, «ьор ал,цл не то же самое, что ьор цл,ал». Потребовалось мысленно погрузиться в студенческий идиотизм чтобы восстановить ход своей дурацкой мысли и понять, что шутка про команды ассемблера «XOR AL,CL»... Особенно же загадочно вели себя последовательности нимблов, которые начинались с 2, и далее шел байт в диапазоне от 0x79 до 0x97: из этого байта следовало вычесть десятичное число 120 и нарисовать полученное число пробелов. Но это пробелы. А если байт был равен 0x98, то следовало тем же способом взять число из следующего за ним байта и повторить столько же раз тот символ, что стоит далее! Подозреваю, в формате таилось много и других секретов, но разгадал я пока только эти, и все тексты прочлись, даже с псевдографикой. Речь о текстовом формате, файлы которого начинают с «8CFF», с остальными 8-битными кодировками конечно проще, в итоге я реализовал во вьювере их все. Код расшифровщика, кому интересно:

[показать спрятанное]
const BK = {

    get_charset: function(s) {
        if( s[0]==0x8C && s[1]==0xFF ) return 'ED'; // ED BK0010
        var utf=0, winkoi=0, dos=0, win=0, koi=0;
        for(var i=0;i<s.length;i++) {
            if(s[i] < 0x80) continue;
            const c = s[i]-0x80;
            if(c > 79 && c < 83) utf++; // utf
            if(c > 63) { // win or koi
                winkoi++;
                if(c < 96) koi++; else win++;
            }
            if(c<=47 || (c>95 && c<114)) dos++;
        }
        if(utf > Math.max(winkoi,dos)) return 'utf';
        if(dos > winkoi) return '866';
        return koi > win ? 'koi8r' : '1251';
    },

    convert_to: function(s, charset) {
        if(!charset) charset = BK.get_charset(s);
        BK.charset = charset;
        BK.datatext = s;
        if(charset == 'utf') return new TextDecoder('utf-8').decode(s);
        if(charset == 'ED') return BK.convert_ED(s); // это точно формат редактора ED
        var o='';
        for(var i=0;i<s.length;i++) o += s[i] < 0x80 ? BK.koi7[s[i]] : BK[charset][s[i]-0x80];
        return o;
    },

    view: async function(url,e,charset) {
        const s = await BK.readfile(url);
        var txt = BK.convert_to(s,charset);
        txt = h(txt).replace(/\n/g,'<br>');
        alert(txt);
    },

    getc: function(str,i) {
        var x=str[i++],y=x;
        if(x>2) c=BK.tab[x];
        else if(x==1) c=BK.tab1[y=str[i++]];
        else if(x==0) c=BK.tab0[y=str[i++]];
        else c=BK.tab2[y=(str[i++] + (str[i++]<<4))];
        return [c,i,x,y];
    },

    recod: function(str) {
        var caps=0, LAT=0, s="", c, ci, x, y, nn, i;
        for(i=0;i<=str.length-1;) {
            [c,i,x,y] = BK.getc(str,i);
            if(i>=str.length && x==0) break; // убрать последний 0

            if(y >= 0x79 && y < 0x98) c=' '.repeat(y-120); // повтор пробелов
            if(y==0x98) { // повтор нужного символа
                [c,i,x,y] = BK.getc(str,i);
                if(y > 120) {
                    [c,i] = BK.getc(str,i);
                    c=c.repeat(y-120);
                }
            }
            if( x==0 && y==0x0E ) { caps=0; LAT=0; continue; }
            if( x==0 && y==0x0F ) { caps=1; LAT=1; continue; }
            if( x==1 && y==0x0E ) { caps=1; continue; }
            if( x==1 && y==0x0F ) { caps=0; LAT=1; continue; }

            if(c==undefined) c=`&#9568;${x}&#9571;`;
            else {
                c = caps ? c.toUpperCase() : c;
                if(LAT) {
                    ci = BK.rus.indexOf(c);
                    if(ci !== -1) c=BK.lat[ci];
                }
            }
            s += c;
        }
        return s;
    },

    convert_ED: function(s) {
        var result="", str=[], d, i;
        for(i=2;i<s.length;i++) {
            d = s[i];
            if(d==0x00) { result += BK.recod(str)+"\n"; str=[]; }
            else {
                str.push(d & 0x0F);
                str.push((d & 0xF0) >> 4);
            }
        }
        if(str) result+=BK.recod(str)+"\n";
        return result.replace(/ +\n/g,"\n");
    },

tab2: "
((((((((((((((((((((((((π┴♥┐╡├└═╤♠┌┬╨↓┼║┤←╬↑♣─╫│♦┘╞╥╧╞→█!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~█
",
tab0: ['(00)','п','я','у','з','б','й','х','щ','ц','э',',','0','   ',"caps","LAT"],
tab1: ['(10)','д','ы','ь','г','ч','ж','ю','ш','ф','.','-','1','     ',"CAPS","lat"],
tab: "[[[ оеаитнсрвлмк",
rus: "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя",
lat: "ABWGDEVZIJKLMNOPRSTUFHC^[]}YX\\@Qabwgdevzijklmnoprstufhc^[]}yx\\@q",
"1251" :"
ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—.™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬.®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя
",
"koi8r":"
─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ
",
"866"  :"
АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■
",
"koi7" :[...["\n"],...[
' ', // 1
'  ', // 2
'   ', // 3
'    ', // 4
'     ', // 5
'      ', // 6
'       ', // 7
'        ', // 8
'         ', // 9
'\n', // 10 (\n)
'!', // 11
' ', // 12
'' // 13 (\r) нахуй
],...("!!!!!!!!!!!!!!!!!! !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~_".split(''))
],
};

В итоге я, спустя тридцать лет и три года, получил свои архивы, полные милого детского мусора: рефераты и курсовые проекты (включая военную кафедру, где мы «взрывали» какой-то мост предполагаемого противника в Германии), кучи моих ранних текстов, стишков и шуток, начатые и недописанные романы, которые сегодня стыдно перечитывать, тайный личный дневник с любовными пиздостраданиями, всякие программки и утилитки на ассемблере для БК или IBM (боже, какой он был простой и короткий, ассемблер тех времён!), а также смешные материалы секты Мировое Братство Овса, которую мы с друзьями придумали и веселились (сильно позже из этого родилась литературная конференция ОВЕС.РАСТЕТ). Сегодня за создание подпольной религиозной секты (каждого, кто жрет овес, мы называли жрецом), я подозреваю, вполне реально уехать лет на 8. Но тогда время было мирное и спокойное, начало девяностых, студенты и школьники веселились как умели, никто их не кошмарил, не цензурировал и не «регулировал».

Так или иначе, не думаю, что весь этот мусор с двух десятков флоппи-дисков сегодня достоин вашего внимания. За исключением разве что коллекции анекдотов...

Анекдоты! Все в те годы любили анекдоты. Это сегодня, если кто-то предлагает вам рассказать анекдот (или цитирует песню Высоцкого) — скорее всего это существо возраста 50+. А тогда анекдоты заменяли детям тикток и стэндап. Свои любимые анекдоты рассказывали журналистам в интервью видные актеры, политики и прочие ВИП-персоны. Как только люди собирались числом более двух — сразу начинали рассказывать друг дружке анекдоты. Кто их придумывал, эти анекдоты, было загадкой: лично мне так и не удалось придумать ни одного. В конце 1980-х и в начале 1990-х анекдоты были. А интернета у меня не было, FIDO не было, и даже брошюрки типа «1000 анекдотов про тёщу» еще не наводнили книжные лотки страны. Но у меня был какой-никакой компьютер БК0010 и принтер. И поэтому я увлекался коллекционированием анекдотов. Это было интереснее, чем марки и вкладыши от жвачки. Я внимательно запоминал услышанные анекдоты, а дома набирал их на клавиатуре в файлы по тематикам. Иногда редактировал от косноязычия и возвращал им литературную форму. А после печатал на принтере и раздавал друзьям. Я даже переписывался с коллекционерами анекдотов из разных городов! Помню, особенно содержательный обмен бумажными письмами у нас шел с коллекционером из города Кимры по имени Папа Карло. Он специализировался на анекдотах про панков. Потом Папе Карло исполнилось 18 и его забрали в армию. Я посылал ему туда лучи поддержки и свежие находки, он первое время даже отвечал, но было ему уже не до панков.

Итак, погрузимся в мир бытового фольклора 35-летней давности. Поручик Ржевский, Чукча, Штирлиц, Василь Иваныч, Ленин, Прапорщик, Вовочка и Марь Иванна, Винни Пух и Пятачок, Армянское Радио и другие забытые герои с дискетки БК-0010 «АНЕКДОТЫ», которая пролежала по подвалам и антресолям тридцать лет и три года, и теперь расшифрована! Разумеется, юморок тупой, баяны старые, так что дискетка сильно на любителя:

https://r.lleo.me/lleo/BK-0010/FLOPPY/АНЕКДОТЫ?before=infinity--081a6425a2992e7cc8c9dd

<< предыдущая заметка следующая заметка >>
пожаловаться на эту публикацию администрации портала
архив понравившихся мне ссылок

Комментарии к этой заметке скрываются - они будут видны только вам и мне.

Оставить комментарий