В марте-мае этого года я потратил несколько недель (по вечерам и выходным) на портирование игрушки Lode Runner с БК-0010 на УКНЦ.
Скриншот меню портированной версии:
Игровой экран портированной версии:
БК-0010 это бытовой компьютер конца 1980-х и начала 1990-х, и отчасти школьный компьютер (классы КУВТ-86). УКНЦ это школьный компьютер 1990-х. БК и УКНЦ частично совместимы по архитектуре и системе команд — оба компьютера восходят к семейству PDP-11.
До этого года я не писал ничего серьёзного под УКНЦ, но приходилось разбираться в машинном коде. Было желание написать что-нибудь, но обычно у меня большие проблемы со свободным временем, так что сделать что-либо с нуля вряд ли получилось бы. И для начала лучше брать задачу попроще. При портировании объём работы обычно намного меньше чем при написании с нуля — сталкиваешься в основном с проблемами несовместимости двух систем.
На форуме zx.pk.ru (одна из площадок где тусуются любители ретрокомпьютинга вообще и PDP-11 совместимых машин в частности) участник hobot расхваливал реализацию Lode Runner на БК — собственно это и стало поводом, для начала я попробовал «посмотреть» на код игрушки, ну и втянулся.
Меню оригинальной версии:
Игровой экран оригинальной версии (на цветном мониторе):
Пару недель по вечерам и выходным я потратил время на анализ и дизассемблирование. В эмуляторе BKBTL добавил возможность собирать трассу — то есть, каждая инструкция дизассемблируется и сохраняется в текстовый файл.
Делаю прогон участка который меня интересует с записью трассы, потом сворачиваю трассу (sort & uniq) — получаю фрагменты логики. Добавляю к этому комментарии, получаю постепенно общий файл.
Звучит просто, но на самом деле это довольно сложная работа, основанная на догадках и их подтверждении или опровержении. Например, смотрим что адрес 001756 перед началом игры получает значение 10, потом декрементируется, при достижении 0 игра заканчивается — видимо, это количество жизней. Находим этому подтверждение, расставляем комментарии по тексту где встречается этот адрес. Это довольно простой пример, в более сложных случаях я потратил много времени на то чтобы догадаться что к чему.
Когда полученный объём стал достаточно большим (40+ КБ текста, больше 1500 строк) и я разобрался хотя бы в общих чертах что к чему, как хранится и выводится — стал думать как это перевести на УКНЦ.
Здесь можно посмотреть на итоговый листинг, полученный в результате дизассемблирования:
github.com/nzeemin/uknc-loderunner/blob/master/original/loderunner.lst
Каждый лабиринт — это 20 строк по 30 блоков, всего 600 блоков.
Тип блока кодируется числом от 0 до 7 — три бита, триплет. На одно 16-разрядное слово получается 5 полных триплетов.
В работе с PDP-11 like машинами повсеместно используется 8-ричная система, поэтому использовать триплеты довольно удобно.
В итоге, каждый лабиринт укладывается в 240 байт.
Типы блоков:
Спрайты этих объектов расположены в порядке нумерации типов блоков. Когда раскодируется лабиринт, одновременно создаётся «образ лабиринта» в памяти (по байту на блок), и тут же рисуется начальное состояние лабиринта на экране.
На БК экран адресуется непосредственно обращением к памяти, строки идут одна за другой, по сути это «framebuffer», и я бы сказал что это прекрасно — очень удобно для программирования графики. Строка БК — 256 цветных пикселей, 64 байта на строку. А вот то, сколько пикселей в строке, зависит от того как вы подключили монитор:
если по чёрно-белому выходу, то это 512 ч/б пикселей в строке (1 бит на пиксел, 8 пикселей на байт),
а если по цветному выходу, то это 256 цветных пикселей в строке (2 бита на пиксел, 4 пиксела на байт).
На УКНЦ же организация экрана совсем другая, и намного более сложная. Экран лежит в трёх блоках памяти, трёх «планах». И каждый пиксель это три бита, по биту в каждом плане — получаем 8 цветов. На УКНЦ у нас есть несколько видеорежимов — 640 ? 288, 320 ? 288, 160 ? 288, точнее, у нас всегда ровно 288 строк и к каждой отдельной строке можно применить свой делитель, получая разное разрешение по горизонтали. Для центрального процессора (ЦП) планы экрана не доступны непосредственно, только через обращение к портам. Причём, для ЦП доступны только два плана из трёх.
В данном случае мне хорошо подходил режим 320 ? 288 — строка получается в 320 цветных пикселей длиной 80 байт в каждом из трёх планов. Если использовать два плана, то пиксели получаются тоже четырёхцветные — почти как на БК.
Начал писать примеры на ассемблере УКНЦ и несколько приуныл — потому что цикл «скомпилил — слинковал — запустил» получается довольно медленный. Проблема в инструментах. Кросс-ассемблер MACRO11 есть, хоть он и несколько глючный. А вот кросс-линкера нет. Но к счастью, не так давно Patron выложил консольную RT-11: zx-pk.ru/showthread.php?t=24755 — по сути это эмулятор PDP11-совместимой машины, взаимодействующий с командной строкой ОС как с терминалом. Тем самым, стала возможной компиляция и линковка родными средствами RT-11. Это я считаю настоящий прорыв, резко ускорило работу.
После этого дело пошло, сделал отрисовку рамки игрового поля, отрисовку спрайтов, разобрался как биты в спрайтах нужно перемешать (для перемешивания написал программу на C#), затем блоками стал переносить код из общего файла с дизасмом в новые исходники. Взял дамп памяти с БК, выделил блок где лежат уровни, RT11-утилитой DUMP сделал текстовик под уровни.
Сначала перенёс блок кода который выводит уровень, на этом отладил вывод спрайтов. Потом игровую логику стал переносить. Т.е. в целом перенос практически один-к-одному, за исключением мест где вывод на экран идёт. Поэтому есть места в логике которые я не понимаю как работают (тот же AI чёртиков), но это и не важно — главное что работают.
В итоге, к началу мая (когда основная работа меня снова поглотила) получился работающий вариант, хотя и без звука.
Фото работающей игры на реальной машине (спасибо hobot):
Скриншот меню портированной версии:
Игровой экран портированной версии:
БК-0010 это бытовой компьютер конца 1980-х и начала 1990-х, и отчасти школьный компьютер (классы КУВТ-86). УКНЦ это школьный компьютер 1990-х. БК и УКНЦ частично совместимы по архитектуре и системе команд — оба компьютера восходят к семейству PDP-11.
Выбор игры
До этого года я не писал ничего серьёзного под УКНЦ, но приходилось разбираться в машинном коде. Было желание написать что-нибудь, но обычно у меня большие проблемы со свободным временем, так что сделать что-либо с нуля вряд ли получилось бы. И для начала лучше брать задачу попроще. При портировании объём работы обычно намного меньше чем при написании с нуля — сталкиваешься в основном с проблемами несовместимости двух систем.
На форуме zx.pk.ru (одна из площадок где тусуются любители ретрокомпьютинга вообще и PDP-11 совместимых машин в частности) участник hobot расхваливал реализацию Lode Runner на БК — собственно это и стало поводом, для начала я попробовал «посмотреть» на код игрушки, ну и втянулся.
Меню оригинальной версии:
Игровой экран оригинальной версии (на цветном мониторе):
Обратная разработка
Пару недель по вечерам и выходным я потратил время на анализ и дизассемблирование. В эмуляторе BKBTL добавил возможность собирать трассу — то есть, каждая инструкция дизассемблируется и сохраняется в текстовый файл.
Делаю прогон участка который меня интересует с записью трассы, потом сворачиваю трассу (sort & uniq) — получаю фрагменты логики. Добавляю к этому комментарии, получаю постепенно общий файл.
Звучит просто, но на самом деле это довольно сложная работа, основанная на догадках и их подтверждении или опровержении. Например, смотрим что адрес 001756 перед началом игры получает значение 10, потом декрементируется, при достижении 0 игра заканчивается — видимо, это количество жизней. Находим этому подтверждение, расставляем комментарии по тексту где встречается этот адрес. Это довольно простой пример, в более сложных случаях я потратил много времени на то чтобы догадаться что к чему.
Когда полученный объём стал достаточно большим (40+ КБ текста, больше 1500 строк) и я разобрался хотя бы в общих чертах что к чему, как хранится и выводится — стал думать как это перевести на УКНЦ.
Здесь можно посмотреть на итоговый листинг, полученный в результате дизассемблирования:
github.com/nzeemin/uknc-loderunner/blob/master/original/loderunner.lst
Лабиринт
Каждый лабиринт — это 20 строк по 30 блоков, всего 600 блоков.
Тип блока кодируется числом от 0 до 7 — три бита, триплет. На одно 16-разрядное слово получается 5 полных триплетов.
В работе с PDP-11 like машинами повсеместно используется 8-ричная система, поэтому использовать триплеты довольно удобно.
В итоге, каждый лабиринт укладывается в 240 байт.
Типы блоков:
; 0 -- пусто
; 1 -- сплошная стена
; 2 -- кирпичная стена
; 3 -- верёвка
; 4 -- чёрт
; 5 -- человек
; 6 -- сундук
; 7 -- лестница
Спрайты этих объектов расположены в порядке нумерации типов блоков. Когда раскодируется лабиринт, одновременно создаётся «образ лабиринта» в памяти (по байту на блок), и тут же рисуется начальное состояние лабиринта на экране.
Организация экрана
На БК экран адресуется непосредственно обращением к памяти, строки идут одна за другой, по сути это «framebuffer», и я бы сказал что это прекрасно — очень удобно для программирования графики. Строка БК — 256 цветных пикселей, 64 байта на строку. А вот то, сколько пикселей в строке, зависит от того как вы подключили монитор:
если по чёрно-белому выходу, то это 512 ч/б пикселей в строке (1 бит на пиксел, 8 пикселей на байт),
а если по цветному выходу, то это 256 цветных пикселей в строке (2 бита на пиксел, 4 пиксела на байт).
На УКНЦ же организация экрана совсем другая, и намного более сложная. Экран лежит в трёх блоках памяти, трёх «планах». И каждый пиксель это три бита, по биту в каждом плане — получаем 8 цветов. На УКНЦ у нас есть несколько видеорежимов — 640 ? 288, 320 ? 288, 160 ? 288, точнее, у нас всегда ровно 288 строк и к каждой отдельной строке можно применить свой делитель, получая разное разрешение по горизонтали. Для центрального процессора (ЦП) планы экрана не доступны непосредственно, только через обращение к портам. Причём, для ЦП доступны только два плана из трёх.
В данном случае мне хорошо подходил режим 320 ? 288 — строка получается в 320 цветных пикселей длиной 80 байт в каждом из трёх планов. Если использовать два плана, то пиксели получаются тоже четырёхцветные — почти как на БК.
Синтез
Начал писать примеры на ассемблере УКНЦ и несколько приуныл — потому что цикл «скомпилил — слинковал — запустил» получается довольно медленный. Проблема в инструментах. Кросс-ассемблер MACRO11 есть, хоть он и несколько глючный. А вот кросс-линкера нет. Но к счастью, не так давно Patron выложил консольную RT-11: zx-pk.ru/showthread.php?t=24755 — по сути это эмулятор PDP11-совместимой машины, взаимодействующий с командной строкой ОС как с терминалом. Тем самым, стала возможной компиляция и линковка родными средствами RT-11. Это я считаю настоящий прорыв, резко ускорило работу.
После этого дело пошло, сделал отрисовку рамки игрового поля, отрисовку спрайтов, разобрался как биты в спрайтах нужно перемешать (для перемешивания написал программу на C#), затем блоками стал переносить код из общего файла с дизасмом в новые исходники. Взял дамп памяти с БК, выделил блок где лежат уровни, RT11-утилитой DUMP сделал текстовик под уровни.
Сначала перенёс блок кода который выводит уровень, на этом отладил вывод спрайтов. Потом игровую логику стал переносить. Т.е. в целом перенос практически один-к-одному, за исключением мест где вывод на экран идёт. Поэтому есть места в логике которые я не понимаю как работают (тот же AI чёртиков), но это и не важно — главное что работают.
В итоге, к началу мая (когда основная работа меня снова поглотила) получился работающий вариант, хотя и без звука.
Фото работающей игры на реальной машине (спасибо hobot):
Ссылки
- zx-pk.ru/showthread.php?t=24886 — тред по этой теме на zx.pk.ru
Комментарии (10)
AndrewN
29.08.2015 23:12Черт! На УКНЦ же был GOBLIN! Это нечто наподобие lode runner
Эх, очень мне нравились эти гоблины, жать всего 15 (вроде) уровнейnzeemin
29.08.2015 23:43+1Да, было такое.
Эти и другие скриншоты здесь: github.com/nzeemin/ukncbtl-doc/wiki/Games-ru
entze
30.08.2015 08:07Насколько я помню, был эмулятор для запуска игрушек с БК на УКНЦ.
Обещали поделится со мной бесплатно, но забыли.
eandr_67
Забавно, но в конце 1980-х я проделывал тоже самое — но переносил на УК-НЦ игры не для БК, а для ДВК-3 с КГД (контроллер графического дисплея). И там, и там RT-11, у монохромного режима УК-НЦ и КГД организация практически идентичная (разница в длинах строк) и единственной серьёзной проблемой было написание утилиты, загружающей в сопроцессор УК-НЦ программу, перестраивающую графический буфер сопроцессора — чтобы для графики использовались все строки экрана, включая служебную зону.
А т.к. мониторы на работе в то время были монохромными, то допустил в этой утилите ошибку в настройке цветов — и на цветном мониторе картинка была не черно-белая, а чёрно-лиловая.
eandr_67
В дополнение: судя по «ЛАТ» в правом верхнем углу, Вы перестройкой видеобуфера не заморачивались. Физически у УК-НЦ не 288, а 320 строк и при желании все их можно использовать: в ОЗУ периферийного процессора (прошу прощения, выше ошибочно назвал его сопроцессором) находится таблица, содержащая адреса и режимы видеострок.
nzeemin
Да, мне не хотелось заморачиваться перестройкой видеорежима и вообще программой под ПП, я сделал проще — включил формат экрана 80x24 через Esc-последовательность.
В следующей версии конечно нужно работать с ПП — в частности, сделать звуковое сопровождение.
nzeemin
А что конкретно вы портировали? Остались какие-то наработки на дискетах или других носителях?
Приходите вот сюда — zx-pk.ru/forumdisplay.php?f=66 — тут относительно много любителей отечественных PDP-11 и есть определённая движуха.
eandr_67
Из названий вспоминается только sherif. И это ведь 25 лет назад было и на работе.