(c) Alex Rostov / Dementia Corp.
__________________________________________
Бегущие строки вне экрана.
Тема бордюрных эффектов уже давно была
неплохо освещена в литературе, но на неко-
торых тонкостях их реализации я хотел бы
остановиться подробнее. Основанием для по-
добного шага служит бедственное положение
демомейкинга в Барнауле. Я хотел бы видеть
в Барнауле не только свои демки, и не дем-
ки моих хороших друзей и знакомых, а новые
( пусть не особо профессиональные, но
НОВЫЕ!!! ). В связи с этим я вновь затра-
гиваю эту тему. Эта коротенькая статья,
надеюсь, поможет Вам разобраться со столь
интересным эффектом, как графика вне
экрана...
1. Вступление
...в тот день я унес свою челюсть в
кормане, так как она начисто отвалилась.
Был солнечный осенний день. Я первый раз
увидел скрытую часть Insult Megademo...
2. Теория
Для начала не мешало бы разобраться,
что такое BORDER и как на нем формируется
изображение. Как известно, BORDER- это об-
ласть, находящаяся вне стандартного спект-
румовского экрана и занимающая все остав-
шееся от него место. К сожалению, единст-
венное, что мы можем сделать с BORDERom,
это поменять его цвет. Никаких точек на
нем мы поставить не сможем. А как же тогда
пускать по BORDERy бегущие строки ?- спро-
сите Вы. А вот как. На помощь нам приходит
наша родная электронно-лучевая трубка. Все
дело в том, что изображение на экране мо-
нитора появляется не сразу (будь то SCREEN
или BORDER), а прорисовывается сверху вниз
слева направо с определенной частотой - 50
кадров в секунду. Цвет BORDERa зависит от
содержимого порта №254 (#FE). В нем нахо-
дится байт, младшие три бита которого от-
вечают за цвет BORDERa ( остальные биты
на цвет не влияют, мы их сбрасываем в 0 ).
Теперь нам необходимо только "подсовывать"
лучу, прорисовывающему картинку на экране,
необходимые нам значения. Как только луч
доходит до места, в котором нам надо пос-
тавить точку, посылаем в порт #FE цвет
точки. Как только луч прошел точку, посы-
лаем в порт номер цвета фона, либо другой
точки. Вот, в принципе, и весь алгоритм.
3. Проблемы
Несмотря на столь простой алгоритм,
на практике мы сталкиваемся с довольно
серьезными проблемами. Одна из них - это
проблема синхронизации. Вся беда том, что
практически никогда нельзя угадать, где
находится луч в данный момент времени.
Решить эту проблему очень простым и
эффективным способом помогает порт #FF, но
так как не у всех он есть ( точнее его
почти ни у кого нет ), то от этого способа
мы сразу абстрагируемся и рассказывать про
него я здесь не буду. Если кому интересно,
можете позвонить мне - я расскажу, как он
работает.
Еще одним вариантом решения данной
проблемы является синхронизация под пре-
рывания. Так уж получилось, что частота, с
которой приходят прерывания копейка в ко-
пейку совпадает с частотой прорисовки - 50
герц (= 50 кадров в секунду). Из сего де-
лаем вывод, что через 1/50 секунды луч бу-
дет находиться там же, где он сейчас нахо-
дится и где он находился 1/50 секунды (т.е
ровно одно прерывание) назад.
К сожалению это решает проблему лишь
наполовину. Мы по прежнему не знаем, где
именно находится луч. Это зависит от типа
компьютера (точнее от его INTa), а так как
компьютеры у всех разные, ни о какой син-
хронизации на первый взгляд не может быть
и речи ( тут я сделаю небольшую оговорку:
последнее время все демы ( 99.9% ) пишутся
под INT компьютера Pentagon 128 ). Но и из
этой ситуации есть выход. Такой выход, по-
моему первыми нашли авторы KAZAN Demo
(Enlight 97). Они предложили пользователю
самому производить настройку программы под
свой компьютер путем регуляции задержки,
предшествующей выводу бордюрного изображе-
ния:
1. прерывание
2. регулируемая задержка
3. вывыд изображения
Есть еще один способ, дающий наилучшие ре-
зультаты - запретить прерывания и добиться
путем регулирования задержки того, чтобы
ровно через 1/50 секунды, когда луч ока-
жется в нужном месте, программа как раз
дошла до процедуры вывода изображения. На
самом деле это совсем не сложно, если у
Вас под рукой таблица со временем выполне-
ния каждой команды ( в тактах ) и если Вы
знаете, сколько тактов процессора проходит
за 1/50 секунды.
Есть еще одна проблема, решить которую
на сей раз никак не удастся. Она состоит в
том, что команда вывода байта в порт тре-
бует не меньше 12 тактов, а за один такт
луч смещается на два пиксела. Получаем
2*12=24 пиксела (= 3 знакоместа). Это зна-
чит, что точку, уже чем 3 знакоместа нам
поставить не удастся ( высота "точки" - 1
пиксел ). Тут уж ничего не поделаешь, с
этим придется смириться. Именно по этой
причине бордюрная графика редко выходит за
рамки горизонтальных полос ( почему-то мне
вдруг вспомнилась процедура загрузки прог-
рамм с ленты... ). Как было уже сказано
выше, за один такт луч проходит два пиксе-
ла, та что перемещать изображение на бор-
дюре влево/вправо можно только на 2*n пик-
селов ( n=1,2,3... ), регулируя задержку.
По вртикали переместить изображение можно
на любое целое количество пикселов.
4. Реализация
Итак, мои маленькие любители бордюрных
ных эффектов, настало время поговорить о
главном - о применении вышеизложенной тео-
рии к бегущей строчке на бордюре.
Допустим, мы хотим запустить скролл в
верхней части экрана, над экранной облас-
тью ( допустим, что Вы поняли, где это на-
ходится :-). Для того, чтобы прерывания не
мешали нам работать, повесим на прерывания
IM2 всего одну команду:
RETI
т.е. прерывание не выполняет никаких функ-
ций, следовательно не будет влиять на луч,
осуществляя дополнительную, неизвестно ка-
кую задержку. Далее выполняем циклически
следующий алгоритм:
- ждем, когда придет прерывание. Это де-
лает комманда ассемблера
HALT
- производим нужную задержку, например
выполняя в цикле какую-нибудь нейтраль-
ную комманду типа
NOP, или
LD A,A
Параметры цикла зависят от типа компью-
тера, от расположения скролла и подби-
раются вручную.
- выводим изображение. На этом пункте я
остановлюсь иболее подробно. Для вывода
будем использовать команды:
OUT (С),A #ED79
OUT (С),В #EDЧ1
OUT (С),D #EDS1
OUT (С),E #EDS9
OUT (С),Н #EDб1
OUT (С),L #EDб9
Для работы нам понадобится буфер размером
(l*2+1)*h+1 байт, где l - длина скролла в
"точках" по три знакоместа (18), h-высота
скролла (8) в "точках" по x пикселов ( на-
пример х=4 ). То есть буфер будет состоять
из x*h строк по l*2+1 байт. Теперь обьясню
откуда берутся +1. Во первых в конце дан-
ного буфера расположим байт 201 ( комманда
RET ), а во вторых в конце каждой строки
расположим байт 0 (комманда NOP). Так как
этот буфер будет состоять из кодов команд
ассемблера (во как хитро !..), RET нам по-
надобится для того, чтобы обеспечить воз-
врат в программу, когда мы будем обращать-
ся к этому буферу как к подпрограмме ( при
помощи команды CALL ). Каждая строка буфе-
ра будет состоят из l (18) штук команд
OUT (С),N ( N - какой-нибудь регистр ) то
есть из последовательности байт ED NN ED
NN ED NN ... NOP. Зачем NOP ? А вот зачем.
Все дело в том, что луч пробегает одну
строку экрана за 224 (запомните это число)
такта процессора ( если у Вас не совсем
"левый" спекки ). Как уже было упомянуто,
команда OUT (С),N выполняется за 12 тактов
процессора. Очевидно, что в одну строку мы
сможем поместить целиком не более 224/12 =
18 "точек" по 24 пиксела. Но т.к 12*18=216
у нас остается 8 "лишних" тактов. Вот их
то и заполняет NOP.
Теперь для вывода изображения ( напри-
мер бегущей сироки ) расположим после каж-
дого байта #ED один из следующих байтов:
#79 (регистр A), #41 (В), #51 (D), #59 (E)
#61 (Н) или #69 (L). Пустим желтый скролл
по синему фону (например). Тогда если N-ю
точку нужно окрасить в желтый цвет, запи-
сываем после N-го байта, равного #ED байт
#69, если в синий - #61. Теперь перед вы-
зовом этой подпрограммы в регистр L занес-
ти 6 (желтый), а в Н - 1 (синий) и все ОК!
Теперь для того, чтобы сменить цвет скрол-
ла достаточно изменить регистр L, цвет фо-
на - Н.
Вывести-то вывели. А как заставить ее
бежать ? Это реализуется путем изменения
задержки перед вызовом подпрограммы вывода
изображения Помните, что при изменении
держки на один такт изображение сдвигается
нп два пиксела! Желаю удачи в программиро-
вании. По всем вопросам звоните мне:
42 - 48 - 07 ( Саша )
The END
Other articles: