31 октября 1998 |
|
(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:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Similar articles:
В этот день... 21 November