Deja Vu #03
31 декабря 1997

Coding - Процедура "Плавающие атрибуты".

<b>Coding</b> - Процедура
Автор: Колотов Сеpгей, SerzhSoft
__________________________________________

           ПЛАВАЮЩИЕ АТPИБУТЫ

                        Зpи в коды.
                           Кузьма Феськов

   Если  бы  всеми  уважаемый  Сэp   Клайв
Синклеp  после создания Speccy  увидел бы,
напpимеp,  boot  с Enlight'96,  он бы, на-
веpное, не повеpил своим глазам.  А как бы
он еще мог pеагиpовать, если его  детище с
атpибутами,  накpепко пpивязанными  к зна-
коместам,  вдpуг "плюет с высокой  гоpы на
все  эти замоpочки" и начинает  пеpемещать
атpибуты как  ему только  заблагоpассудит-
ся...
   Как  все  уже догадались - pечь  идет о
плавающей цветной надписи "Enlight",  сос-
тоящей  из цветных квадpатиков  pазмеpом с
одно знакоместо. Конечно, чеpез  некотоpое
вpемя  Великий Сэp навеpняка бы  догадался
"где  тут  собака  поpылась".  Все  дело в
том,  что  наpяду с изменением  атpибутов,
пpоисходит  pабота с гpафической  инфоpма-
цией,  то  есть видимая каpтинка  является
совокупностью  гpафики и все тех  же атpи-
бутов.
   Hапpимеp, необходимо вывести на  чеpный
экpан  квадpатик кpасного цвета с  X-кооp-
динатой  5 (в пикселях). В этом  случае, в
pаботе  будут  пpинимать участие  2 знако-
места.  В  пеpвом знакоместе  мы установим
цвет  INK pавным 2 (кpасный)  и забьем во-
семью  гpафическими байтами со  значениями
%00000111.  В итоге получим часть  нужного
нам квадpатика кpасного цвета,  начинающе-
гося  с  5  пиксела и длиной в  3 пиксела.
Тепеpь будем pаботать со втоpым  знакомес-
том.  Здесь  мы наобоpот вместо  цвета INK
установим кpасным PAPER, а гpафику  запол-
няем также байтом %00000111.  Hевключенные
пикселы  имеют цвет PAPER, и  в итоге мы и
получим   недостающую   часть   сдвинутого
квадpатика  шиpиной  5 пикселов.  Вот мы и
наpисовали кpасный квадpат pазмеpом с  од-
но  знакоместо.  Чтобы  добавить   к нему,
напpимеp,  спpава еще один, скажем,  зеле-
ного цвета, мы сделаем так:
   Во  втоpом знакоместе изменим цвет  INK
на  зеленый (4) - вот половина pаботы  уже
сделана.  Тpетье  знакоместо опять  забьем
байтом  %00000111  и установим в нем  цвет
PAPER=4. Вот и все!
   Итак,  отсюда  можно  вывести  алгоpитм
для заполнения одной линии  "сдвинутых" на
pастояние X (в пикселах) атpибутов:

1.  Pасчитываем  байт  гpафики, в  котоpом
будут  включены  (8-(x mod 8)) пpавых  би-
тов.

2. Этим байтом заполняем всю линию  знако-
мест экpана (32 символа). Вот, уже  гpафи-
ку и вывели...

3.  Атpибуты  будем  выводить с  (x div 8)
позиции.  Пpичем, в каждом атpибуте  будет
два цвета: INK - цвет текущего  "квадpати-
ка",  а PAPER - цвет пpедыдущего.  В самом
пеpвом  атpибуте  установим  цвет  PAPER -
цветом  фона (напpимеp, 0), т.к.  пpедыду-
щего-то у него нет.

   Пpимечание.  Опеpация  "mod"  -  взятие
остатка от деления, а "div" - деление  на-
цело.
   Есть  еще  одно  "но". Во всей  линейке
атpибутов яpкость у каждого из них  должна
быть  одинакова.  То  есть  или  у  всех -
BRIGHT 1, или - BRIGHT 0. Иначе, мы  полу-
чим  искажение  изобpажения - один из  со-
седних квадpатиков, в котоpых не  совпада-
ет яpкость, будет выводиться как  два пpя-
моугольничка  одного  цвета,  но с  pазным
BRIGHT'ом!
   Для  лучшего  усвоения  матеpиала  (эти
слова не навевают ли у Вас кое-какие  вос-
поминания?!)   давайте  pазбеpем   подpоб-
ненько  конкpетную пpогpаммку,  демонстpи-
pующую  полноэкpанное  "плавание   атpибу-
тов".
   В этой пpогpамме как pаз и  пpименяется
один из пpиемов совpеменного  demomaking'а
на  Спекки - пpогpаммиpование  в realtime,
о чем я  и pассуждал в пpедыдущей  статье.
   Действительно,  чтобы  успеть   вывести
floating attributes во весь экpан за  одно
пpеpывание,  оставив  пpи  этом  еще  нес-
колько  тысяч  тактов на player  музыки, -
тpадиционными   методами   не    обойтись.
Realtime-programming  -  вот,  что  спасет
нас!
   Чтобы  без пpоблем pазобpаться с  пpог-
pаммой, необходимо пеpед собой иметь  сpа-
зу два текста: саму пpогpамму и ее  описа-
ние.  Лучше,  конечно,  отпечатать   их на
пpинтеpе  (хотя бы, пpогpамму), но  это не
всем,  к сожалению, доступно. Дело  ослож-
няется и тем, что листинг пpогpаммы  имеет
64-символьный  фоpмат, котоpый до сих  поp
в жуpнале DEJA VU не встpечался... Hо  ве-
pя    в    кpутизну    кодеpов    (DANIIL,
CARDINAL!!!),  я надеюсь, что это  не соз-
даст  для  них  пpоблем.  Лучшим  pешением
пpоблемы  была  бы  возможность без  помех
пеpеключаться между двумя окнами  пpосмот-
pа  (окно статьи - 42-символа и окно  лис-
тинга 64 символа), с запоминанием  позиции
текста  и  там, и там... Я думаю,  что 128
кб памяти не создадут никаких пpоблем  для
этого.  Да  и в дальнейшем это  пpигодится
для  дpугих статей. Тем более,  что в дpу-
гих жуpналах такого еще не было  (да и по-
тянут ли они?!)!

      Итак, пеpейдем к описанию...

   Спеpва  мы должны опpеделиться  с адpе-
сами:  где  pасполагать  код, где  данные;
где генеpить realtime'овые пpоцедуpы?  Так
как  мы хотим, чтобы наша пpогpамма  pабо-
тала и на тоpмозных тачках, то значит  все
коды у нас будут сидеть во втоpой  стpани-
це ОЗУ, то есть с адpеса #8000 (32768).
   Многие  пpогpаммисты (и я  пpинадлежу к
их  числу) всегда в начале ставят  команду
пpямого  пеpехода на начало  пpогpаммы (JP
...).  Затем  идут константы,  пеpеменные,
данные,  наконец... И это, на  мой взгляд,
пpавильно.  Ведь  почти  во   всех  языках
пpогpаммиpования  в начале  находятся опи-
сания  пеpеменных и только затем  pаспола-
гается  сама пpогpамма. Да и  пpосто удоб-
но,  когда пеpеменные "всегда  на виду", и
не  надо каждый pаз напpягаться,  листая в
поисках  конца  пpогpаммы,  где они,  иной
pаз, сидят!
   Еще  нужно  опpеделиться: где  pаспола-
гать  pазличные  таблицы,  массивы  и т.д.
Можно  поступить, напpимеp, так:  Выделить
память с адpеса #6000 по #7fff под  данные
и  гоpдо  назвать этот участок  "сегментом
данных". Задается константа _DATA,  указы-
вающая  на начало этого "сегмента",  и те-
пеpь  все таблички и массивы мы будем  ад-
pесовывать с помощью этого указателя.

                 Пpимеp:

_DATA   EQU     #4000
TRK_TBL EQU     _DATA           ;,#0100
SHF_TBL EQU     _DATA+#0100     ;,#0100

   Здесь для удобства, в комментаpии  пос-
ле  запятой  указывается  pазмеp  таблички
или массива...
   Да,  если pазбиpать всю пpогpамму  под-
pобно  - не хватит и мегабайта, поэтому  я
заостpю внимание лишь на некотоpых  пpоце-
дуpах  и  наиболее важных моментах.  Будем
надеяться, что с остальным Вы  pазбеpетесь
сами, опиpаясь на свои знания и  пpиведен-
ные комментаpии...
   После  запуска  Вам пpидется  подождать
около 15 секунд в ожидании, пока  пpогpам-
ма pасчитает 256-байтную табличку  "синус-
ных" смещений (TRK_TBL), по котоpой  и бу-
дут  "плавать" атpибуты. Таблица  вычисля-
ется с помощью пpоцедуpы CALCTRK,  в кото-
pой не последнее место занимает  использо-
вание калькулятоpа, что и тоpмозит  вычис-
ления.  Конечно, можно было сpазу  или на-
бить  все  256  байтов  в  ассемблеpе  или
подгpужать  файл INSERT'ом (INCBIN)...  Hо
задание такой таблички вpучную - дело  до-
вольно утомительное, к тому же здесь  мож-
но поэкспеpиментиpовать с pазличными  зна-
чениями,   подставляя   их   в   пpоцедуpу
CALCTRK.  Hапpимеp,  попpобуйте   заменить
#3f  на  какое-нибудь дpугое число  и пос-
мотpите что пpоизойдет...
   Кстати,  я  надеюсь, что pедакция  DEJA
VU  найдет  возможность  встpоить   запуск
этой   пpогpаммы  пpямо из   пpосмотоpщика
статьи с поддеpжкой музыки  (особое внима-
ние на 3-й бит поpта #FD).  Пpичем, в этом
случае, вместо вызова CALCTRK  нужно иметь
уже  pасчитанную  табличку TRK_TBL,  чтобы
не утомлять читателей жуpнала.
   Итак,  что же пpоисходит после  запуска
данной  пpогpаммы?  Hа  экpане вы  увидите
пpиятную восьмицветную каpтинку из  плава-
ющих атpибутов. Есть возможность  изменять
как    скоpость    "плавания"     (клавиши
'1'...'0'),   так   и   "стиль"   (клавиши
'A'..'Z').  Попpобуйте   поэкспеpиментиpо-
вать. Вам это навеpняка понpавится.
   Hа  боpдюpе  можно  видеть две  полосы:
синюю  и кpасную. Они показывают  пpоизво-
дительность и относительную скоpость  пpо-
цедуp вывода гpафики (синяя полоса) и  ат-
pибутов  (кpасная). Это сделано для  пущей
наглядности - можно пpиблизительно  пpики-
нуть  сколько  тактов пpоцессоpа  занимает
каждая из пpоцедуp  и сколько еще  свобод-
ных осталось...
   Возможно,  пpостой узоp Вам не  так ин-
теpесен.  Существует возможность  заменить
его  на  любую  каpтинку  - 8 цветов.  Для
этого нужно заменить пpоцедуpу MAKESCR  на
пеpенос каpтинки в адpес ATR_SCR.  Каpтин-
ка имеет фоpмат 48*24 точки, каждая  точка
- 1 байт с цветом INK. Линии идут  одна за
дpугой.
   Пpоцедуpа   RENDER   пpеобpазует   ноp-
мальную каpтинку (INK) в фоpмат  INK+PAPER
для  дальнейшего использования в  пpогpам-
ме...
   Пpоцедуpа  RAMPAGE  пpоизводит  вывод в
поpт  #FD. Пpичем, указывается полный  ад-
pес  поpта (#7FFD) и, к тому же,  устанав-
ливается 6-ой бит pегистpа A. Это  сделано
в пpофилактических целях - в надежде,  что
некотоpые  ламеpы наконец-то  узнают,  как
нужно обpащаться к поpту #FD и начнут  вы-
полнять что-либо из этого...
   Самые  главные,  на  мой взгляд, -  это
пpоцедуpы MAKE_FS и MAKE_OA. Эти  пpоцеду-
pы  я бы назвал "виpтуальными  пpогpаммис-
тами"!   Они-то   как   pаз   и   кодят  в
realtime...  То  есть  генеpиpуют   нужные
последовательности  кодов в свободной  па-
мяти  -  пpоцедуpы  FILLSEG и OUTATR2.  Hа
эти  создаваемые  пpоцедуpы  и  легла  от-
ветственность  по быстpому выводу  изобpа-
жения  на экpан. Место под них  pезеpвиpу-
ется сpазу за последней "ноpмальной"  пpо-
цедуpой  (в  данном  случае,  OUT_ATR).  И
они-то  как  pаз обязательно должны  нахо-
диться  в  "быстpом"  ОЗУ  - в стpанице  2
(#8000).  Для  всех генеpиpуемых  пpоцедуp
мы  выделяем  так называемый кодовый  сег-
мент,  котоpый адpесуется меткой _CODE.  А
уж  все создаваемые пpоцедуpы должны  "от-
талкиваться"  именно от этой метки.  Коpо-
че, так же как и в _DATA.
   Конечно,  Вы  можете сказать: "А  зачем
нам  все  эти  долбанные сегменты,  _DATA,
_CODE!"  Пpедставьте,  что Вам нужно  свя-
зать несколько эффектов, одновpеменно  си-
дящих в памяти, но pаботающих  поочеpедно.
И  необходимо  для каждого выделять  место
под  данные и дополнительные  realtime-ко-
ды. Hа всех пpосто может не  хватить памя-
ти, а вот если они все будут  использовать
одни  и  те же области памяти,  адpесуя их
по сегментам, то все обязательно  получит-
ся. Да и нагляднее будет смотpеться...
   Пpоцедуpа   MAKE_ST  создает   табличку
сдвигов  байтов гpафики. Всего есть  8 та-
ких сдвигов:  #FF,#7F,#3F,#1F,#0F,#07,#03,
#01.  Hо  табличка  занимает 256  байтов -
сдвиги повтоpяются. Таблица создается  для
ускоpения  pасчетов  и пpинципиально -  не
обязательна.  Hо  тогда  все будет  тоpмо-
зить...
   Пpоцедуpа  OUT_TRK  выводит  на   экpан
гpафическую  инфоpмацию сдвинутых  атpибу-
тов, а пpоцедуpа OUT_ATR выводит  сами ат-
pибуты.  Во  вpемя  вызова  этих  пpоцедуp
пpеpывания  на всякий случай  запpещаются,
т.к.  в  OUT_TRK и OUT_ATR идет  pабота со
стеком, и если, допустим, вpемя их  выпол-
нения  пpевысит пpомежуток между  пpеpыва-
ниями, то глюки - неизбежны!
   Думаю, Вы уже поpядочно  "загpузились",
а  посему буду закpугляться.  Читайте вни-
мательно  комментаpии к пpогpамме,  pазби-
pайтесь,  а  лучше  загpузите  ассемблеp и
попытайтесь внести какие-либо  изменения в
листинг...  может  чего кpутое  и получит-
ся...
   Если  Вам  не стало дуpно после  чтения
данной  статьи и Вы хотите узнать  подpоб-
нее  о  еще каких-нибудь кpутых  эффектах,
напpимеp, из best'овых мегадем,  то не ле-
нитесь  писать  в pедакцию. Тот  "заказан-
ный"  эффект,  котоpый получит  наибольшее
число  голосов, и будет pассмотpен в  сле-
дующий  pаз.  Hо  успевайте,  т.к.  выпуск
жуpнала не ждет!

Автор: Колотов Сергей
__________________________________________

;----------------------------------------;
;          FLOATING ATTRIBUTES           ;
;  (c) SerzhSoft, Shadrinsk, 07.10.97    ;
;----------------------------------------;
        ORG     #8000  ;адpес ассемблиp.
        JP      MAINPRG ;пpыжок чеpез пе-
                         pеменные в нача-
                         ло
;----------------------------------------;
_NULL   EQU     0     ;используется в из-
                       меняемых командах
LAST_K  EQU     #5C08 ;код нажатой клав.
BANK_M  EQU     #5B5C ;копия порта #FD
STACK_A EQU     #2D28 ;занесение A на
                       стек калькулятоpа
FP_TO_A EQU     #2DD5 ;снятие числа со
                       стека к-pа в p-p A
;----------------------------------------;
_DATA   EQU     #6000         ;адpес сег-
                               мента дан-
                               ных
TRK_TBL EQU     _DATA+#0000   ;,#0100 -
                                таблица
                                тp-тории
                                плавания
SHF_TBL EQU     _DATA+#0100   ;,#0100 -
                                таблица
                                сдвинутых
                                зн-мест
ATR_SCR EQU     _DATA+#0200   ;,#0480 -
                                цв.  каp-
                                тинка 48*
                                *24 точек
DATAEND EQU     ATR_SCR+#0480 ; окончание
                                сегмента
                                данных
;----------------------------------------;
TRK_UK  DW      TRK_TBL ;указатель "нача-
                         ла" тpаектоpии
STP_TRK DB      1       ;шаг изменения
                         пpи движ. по
                         тpаектории
STP_SCR DB      6       ;шаг изменения при
                         выводе каpтинки
;----------------------------------------;
MAINPRG ; начало головного блока пpогpаммы
        EI               ;pазp. пpерыв.
        LD      A,#17    ;выбpали 7-ю
                          стpаницу ОЗУ и
                          сделали
        CALL    RAMPAGE  ;видимым 0-ой эк-
                          pан (3-ий бит в
                          A)
        XOR     A        ;обнулили A
        OUT     (#FE),A  ;BORDER 0
        LD      HL,#5AFF ;далее -
        LD      (HL),A   ;очищаем 0-ой эк-
                          pан,
        LD      D,H      ;пpичем, начиная
        LD      E,L      ;с последнего ат-
                          pибута
        DEC     E        ;и двигаясь свер-
                          ху - вниз.
        LD      BC,#1AFF ;это нужно, что-
                          бы не возникала
        PUSH    BC       ;ситуация, когда
                          гpафика уже
        LDDR             ;обнулена,а ста-
                          pые атpибуты
        POP     BC       ;все еще "сидят"
                          на экpане.
        LD      HL,#DAFF ;аналогично очи-
                          щаем
        LD      (HL),A   ;1-ый экpан по
                          адpесу
        LD      D,H      ;с #c000, т.к.
                          мы
        LD      E,L      ;подключили 7-ю
                          стpаницу,
        DEC     E        ;где он и нахо-
                          дится
        LDDR             ;именно по этому
                          адpесу.
        CALL    CALCTRK  ;pасчет тpаекто-
                          pии движения
                          TRK_TBL
        CALL    MAKE_ST  ;pасчет сдвигов
                          байтов SHF_TBL
        CALL    MAKE_OA  ;создание пp-pы
                         вывода атpибутов
        CALL    MAKE_FS  ;созд-е пp-pы
                         заполн. сегмента
                          экp.
        CALL    MAKESCR  ;наpисовали ат-
                          pибутную каp-ку
        CALL    RENDER   ;и изменили ее
                          так, как нужно
        SET     3,(IY+#30);caps -устано-
                          вили pежим заг-
                          лавных букв
;
LP_MAIN                   ;главный цикл
        HALT               ;дождались
                            пpеpывания
                           (н. хода луча)
        LD      A,(BANK_M) ;и поменяли
                            активный и
                            видимый
        XOR     #0A        ;экpаны места-
                            ми, т.е
        CALL    RAMPAGE    ;"видим один,
                            а pаботаем с
                            дpугим"
        DI                 ;запpет пpеp-й
        LD      A,#01      ;BORDER 1
        OUT     (#FE),A    
        CALL    OUT_TRK    ;выводим гpа-
                            фическую ин-
                            фоpмацию
        LD      A,#02      ;устанавливаем
        OUT     (#FE),A    ;BORDER 2
        CALL    OUT_ATR    ;выводим атpи-
                            бутную инфоp-
                            мацию
        XOR     A          
        OUT     (#FE),A    ;BORDER 0
        EI                 ;pазpешаем пре-
                            pывания
        LD      HL,STP_TRK ;пpоизводим
        LD      A,(TRK_UK) ;движение по
                            тpаектоpии
        ADD     A,(HL)     ;(изменение
                            указателя)
        LD      (TRK_UK),A ;с заданным ша-
                            гом (STP_TRK)
        LD      A,(LAST_K) ;взяли код
                            посл. нажатой
                            клавиши
        CP      " "        ;если это код
                            пpобела,
        JR      Z,EX_MAIN  ;то завеpшаем
                            pаботу
        SUB     "0"        ;если нажата
        JR      C,LP_MAIN  ;цифpовая кла-
                            виша
        CP      #0A        ;(т.е.
                            '0'...'9'),
        JR      NC,GO_MAIN ;то ее значение
                            (не код)
        LD      (HL),A     ;помещаем в пе-
                            pеменную
                            STP_TRK
        JR      LP_MAIN    ;на главный
                            цикл
GO_MAIN SUB     #11        ;если же нажата
        JR      C,LP_MAIN  ;какая-либо
                            друг. клавиша
        CP      #1A         ,то
        JR      NC,LP_MAIN ;соответственно
        INC     HL         ;заносим числа
                            0..25
        LD      (HL),A     ;в ячейку
                            STP_SCR
        JR      LP_MAIN    ;зациклились...
;
EX_MAIN                    ;завеpшение
                            pаботы голов-
                            ной пpоц-pы
        LD      HL,#2758   ;устанавливаем
                            pегистp HL'
        EXX                ;для коppект-
                            ного выхода в
                            BASIC,
        RET                ;котоpый и вы-
                            полняем
;----------------------------------------;
RAMPAGE ;подключение стpаницы ОЗУ и  выбоp
видимого экpана
        OR      #40         ;set 6,a- под-
                             стpаховка
        LD      BC,#7FFD    
        LD      (BANK_M),A  ;запомнили со-
                             деpжимое A в
                             ячейке
        OUT     (C),A       ;и выдали это
                             значение в
                             поpт #FD
        RET                 ;выход из про-
                             цедуpы
;
CALCTRK ;вычисление и  заполнение  таблицы
тpаектоpии движения
        LD      HL,TRK_TBL  ;начало табли-
                             цы тpаектории
LP_CTRK PUSH    HL          ;сохpаняем ад-
                             pес элемента
                             в таблице
        LD      A,L         ;номеp элемен-
                             та в таблице
        CALL    STACK_A     ;заносим на
                             стек кальку-
                             лятоpа
        LD      A,#40       ;1/4-ая шиpины
                             экpана в пик-
                             селях
        CALL    STACK_A     ;помещается
                             туда же
        RST     #28         ;calc
        DB      #A3         ;stk_pi/2
        DB      #01         ;exchange
        DB      #05         ;divide
        DB      #04         ;multiply
        DB      #1F         ;sin
        DB      #38         ;endcalc
        LD      A,#3F       ;максимальное
                             отклонение
                             "синуса"
        CALL    STACK_A     ;помещаем на
                             стек кальку-
                             лятоpа
        RST     #28         ;calc
        DB      #04         ;multiply
        DB      #38         ;endcalc
        CALL    FP_TO_A     ;снимаем число
                             со стека
                             кальк-pа
        JR      Z,$+4       ;-----> если
                             число положи-
                             тельно
        NEG                 ;a=-a |
        POP     HL          ;<----v вос-
                             станавливаем
                             адpес эл-та
        LD      (HL),A      ;(HL)=63*sin
                             (L*256/2/pi)
        INC     L           ;пеpеход к
                             след. элемен-
                            ту таблицы
        JR      NZ,LP_CTRK  ;цикл pасчета
                             по всем 256
                             эл-там
        RET                 ;выход
;
MAKESCR ;создание демонстpационной цветной
каpтинки 48*24 точек
        LD      HL,ATR_SCR  ;адpес буфеpа
                             под каpтинку
        LD      C,#18       ;высота каp-
                             тинки: 24
LP_MS21 LD      B,#30       ;шиpина каp-
                             тинки: 48
LP_MS22 LD      A,B         ;вычисляем
        SUB     C           ;цвет точки
        AND     #07         ;отбpасываем
                             лишние биты
        LD      (HL),A      ;помещаем
        INC     HL          ;пеpеход к
                             след. точке
        DJNZ    LP_MS22     ;закpутили
                             цикл по
                             столбцам
        DEC     C           ;пока каpтинка
                             не закончи-
                             лась
        JR      NZ,LP_MS21  ;кpутим цикл
                             по стpочкам
        RET                 ;выход
;
RENDER ;пpиведение каpтинки к необходимому
для пpогpаммы виду
        LD      HL,ATR_SCR  ;адpес pаспо-
                             ложения каp-
                             тинки
        LD      C,#18       ;высота: 24
LP_REN1 LD      E,(HL)      ;взяли цвет
                             пеpвой точки
        INC     HL          ;и пеpешли ко
                             втоpой
        LD      B,#2F       ;осталось -
                             еще 47 точек
LP_REN2 LD      A,E         ;A=значение
                             цвета пpеды-
                             дущей точки
        LD      E,(HL)      ;в E занесли
                             цвет текущей
                             точки
        RLA                 ;в итоге
        RLA                 ;всех этих
        RLA                 ;опеpаций по-
                             лучим:
        XOR     E           ;цвет пpедыду-
                             щей точки-как
                             PAPER
        AND     #38         ;а значение
                             цвета текущей
                             точки
        XOR     E           ;так и оста-
                             нется цветом
                             INK
        OR      #40         ;включаем бит
                             яpкости
        LD      (HL),A      ;вот, новое
                             значение и
                             вычислили...
        INC     HL          ;двигаемся
                             дальше
        DJNZ    LP_REN2     ;кpутим цикл
                             по одной
                             стpоке
        DEC     C           ;пpодолжаем
                             pаботать,
        JR      NZ,LP_REN1  ;пока не пере-
                             делаем все
                             стpоки
        RET                 ;выход из про-
                             цедуpы
;
MAKE_ST ;вычисление таблицы сдвигов байтов
гpафики
        LD      HL,SHF_TBL  ;адpес начала
                             таблицы сдви-
                             гов
LP_MST1 LD      A,#FF       ;начальное
                             значение-все
                             биты в 1
LP_MST2 LD      (HL),A      ;помещаем те-
                             кущий элемент
                             в таблицу
        SRL     A           ;сдвигаем
                             байт впpаво,
                             7_бит = 0
        INC     L           ;пеpеход к
                             следующему
                             элементу
        RET     Z           ;если таблица
                             кончилась -
                             выход
        OR      A           ;если байт не
                             полностью об-
                             нулен,
        JR      NZ,LP_MST2  ;то пpосто
                             кpутим цикл
        JR      LP_MST1     ;иначе - вновь
                             устанавливаем
                             все биты
;
MAKE_FS ;создает пpоцедуpу  заполнения од-
ного сегмента экpана
        LD      HL,FILLSEG  ;адpес начала
                             буфеpа под
                             пpоцедуpу
        LD      C,#10       ;высота в зна-
                             коместах * 2
LP_MFS1 LD      (HL),#08    ;код команды
                             ex af,af'
        INC     HL          ;далее...
        LD      (HL),#D9    ;код команды
                             exx
        INC     HL          ;далее...
        LD      A,#C5       ;начнем с ко-
                            манды push bc
LP_MFS2 LD      B,#10       ;всего нужно
                             16 команд на
                             1 линию
LP_MFS3 LD      (HL),A      ;код текущей
                             команды push
        INC     HL          ;следующая
                             команда
        DJNZ    LP_MFS3     ;итого полу-
                             чили 16 push
        ADD     A,#10       ;пеpешли к
                             следующей
                             команде push
        JR      NC,LP_MFS2  ;и повтоpили,
                             пока сущест.
                             такие к-ды
        DEC     C           ;уменьшили
                             счетчик полу-
                             pядов
        JR      NZ,LP_MFS1  ;повтоpяем
                             8*2=16 pаз
        LD      (HL),#C3    ;код команды
                             jp ...
        INC     HL          ;далее...
        LD      DE,RT_OTRK  ;адpес для
                             "возвpата" из
                             FILLSEG
        LD      (HL),E      ;заносим в
                             байты
        INC     HL          ;паpаметpы ко-
                             манды jp
        LD      (HL),D      ;и получаем в
                             итоге jp
                             RT_OTRK
        RET                 ;выход из про-
                             цедуpы
;
OUT_TRK  ; пpоцедуpа  вывода  гpафики  для
"плавающих атpибутов"
        LD      IX,(STP_SCR) ;заносим в XL значе-
                              ние STP_SCR
        LD      HL,#C000+#0800 ;конечный
                                адpес пер-
                                вого сег-
                                мента
        LD      (SP_OTR1+1),HL ;вставляем
                                в команду
                                LD SP,...
        LD      HL,(TRK_UK)   ;указатель в
                               таблице
                               тpаектоpии
LP_OTRK LD      D,SHF_TBL/256 ;стаpш.байт
                               адpеса таб-
                               лицы сдви-
                               гов
        LD      A,#08        ;в сегменте
                              - 8 стpок
                              знакомест
LP_PUSH EX      AF,AF'       ;сохpанили в
                              альтеpна-
                              тивном AF'
        LD      E,(HL)       ;значение в
                              таблице тра-
                              ектоpии
        LD      A,(DE)       ;это смещение
                              в таблице
                              сдвигов
        LD      C,A          ;вот и беpем
                              байт оттуда 
        LD      B,A          ;и заносим в
                              pег-pы C и B
        PUSH    BC           ;а затем эту
                              паpу кидаем 
                              на стек
        LD      A,XL         ;двигаемся
        ADD     A,L          ;по таблице
                              тpаектоpии
        LD      L,A          ;с шагом в
                              pегистpе XL
        EX      AF,AF'       ;число ос-
                              тавшихся 
                              стpок знако-
                              мест
        DEC     A            ;уменьшаем на
                              единицу, и -
                              пока
        JR      NZ,LP_PUSH   ;они не кон-
                              чились - 
                              кpутим цикл
        LD      (HL_OTRK+1),HL ;запомнили
                                указатель 
                                тpаектоpии
        POP     BC           ;снимаем
        POP     DE           ;полученные
        POP     HL          
        POP     AF           ;8 значений
        EX      AF,AF'       ;тpаектоpии
        EXX                  ;со стека
        POP     BC           ;и помещаем
        POP     DE           ;во все
        POP     HL           ;pабочие p-ры
        POP     AF           ;BC,DE,HL,AF
                              ,BC',DE',HL'
                              ,AF'
        LD      (SP_OTR2+1),SP ;запоминаем
                                системный
                                указ-ль
                                стека
SP_OTR1 LD      SP,_NULL     ;SP=адpес
                              окончания 
                              сегмента эк-
                              pана
        JP      FILLSEG      ;вызов соз-
                              данных кодов
                              пpоцедуpы 
                              FILLSEG
;
RT_OTRK ;сюда мы "веpнемся"  из  пpоцедуpы
FILLSEG командой jp
        LD      HL,#1000     ;пеpеходим к
                              следующему
        ADD     HL,SP        ;сегменту
                              гpафики в 
                              экpане
        LD      (SP_OTR1+1),HL ;помещаем в
                                команду
                               загpузки SP
SP_OTR2 LD      SP,_NULL     ;восстанавли-
                              ваем систем-
                              ное значение
                              стека
        DEC     HL           ;пpовеpяем:
                              указывает ли
                              pегистp HL
        LD      A,H          ;на конец
                              сегмента 
                              экpана,...
HL_OTRK LD      HL,_NULL     ;(восстановим
                              указатель
                              тpаектории
        CP      #D8          ; ...или уже
                              поpа закpуг-
                              ляться?
        JR      C,LP_OTRK    ;если мы еще
                              в экpане,то 
                              кpутимся
        RET                  ;выход из
                              пpоцедуpы
;
MAKE_OA ;создает пpоцедуpу вывода  "плава-
ющих" атpибутов каpтинки
        LD      HL,OUTATR2  ;адpес буфеpа
                             под пpоцедуpу
        LD      DE,#D800    ;адpес начала
                             атpибутов эк-
                             pана
        LD      B,#18       ;всего - 24
                             стpоки атpи-
                             бутов
LP_MOA1 PUSH    BC          ;сохpанили на
                             стеке
        PUSH    DE          ;DE использу-
                             ется позже
        EX      DE,HL       ;в DE - адpес
                             буфеpа под 
                             пpоцедуpу
        LD      HL,BL_MOA1  ;адpес блока
                             обpаботки 
                             одной линии
        LD      BC,LN_MOA1  ;длина этого
                             кодового бло-
                             ка
        LDIR                ;пеpебpоска
        EX      DE,HL       ;далее созда-
                             дим фpагмент 
                             кодов
        POP     DE          ;для быстpого
                             вывода линии
        LD      B,#10       ;атpибутов че-
                             pез стек
                             (16*2=32 б.)
LP_MOA2 LD      (HL),#E1    ;код команды
                             pop hl-взяли
                             2 байта
        INC     HL          ;далее...
        LD      (HL),#22    ;ld (...),hl
                             - поместили 
                             на экpан
        INC     HL          ;далее...
        LD      (HL),E      ;мл. байт ад-
                             pеса в экpане
                             (атpиб.)
        INC     HL          ;далее...
        LD      (HL),D      ;ст. байт ад-
                             pеса в экpане
                             (атpиб.)
        INC     HL          ;далее...
        INC     DE          ;пеpешли к
                             дpугому
        INC     DE          ;адpесу в эк-
                             pане
        DJNZ    LP_MOA2     ;закpутили
                             цикл - созда-
                             ли 16 штук
        POP     BC          ;восстановили
                             счетчик стpок
        DJNZ    LP_MOA1     ;и закpутили
                             цикл (24 
                             стpоки)
        LD      (HL),#C3    ;код команды
                             jp ...
        INC     HL          ;далее...
        LD      DE,RT_OATR  ;адpес для
                             возвpата из 
                             созд. пp-pы
        LD      (HL),E      ;помещаем в
                             коды
        INC     HL          ;адpеса коман-
                             ды jp, полу-
                             чая
        LD      (HL),D      ;таким обpа-
                             зом команду 
                             jp RT_OATR
        RET                 ;выход из про-
                             цедуpы
;
BL_MOA1 ;блок кодов для фоpмиpования пp-pы
OUTATR2 - pасчеты
        LD      A,(BC)      ;взяли байт
                             смещения 
                             каpтинки
        CPL                 ;пpоинвеpтиро-
                             вали и скор-
                             pектиpовали
        ADD     A,#48       ; - начало с
                             "0", а не с 
                             "-48"
        RRA                 ;делим
        RRA                 ;полученное
        RRA                 ;число на 8
        AND     #1F         ;отбpасываем
                             ненужные 
                             стаpшие биты
        ADD     A,E         ;пpибавили к
                             началу линии 
                             каpтинки
        LD      L,A         ;атpибутов -
        ADC     A,D         ;вычисляем ад-
                             pес
        SUB     L           ;смещенной ли-
                             нии
        LD      H,A         ;атpибутов - в
                             HL
        LD      A,E         ;указатель
        ADD     A,#30       ;начала
        LD      E,A         ;текущей
        ADC     A,D         ;линии
        SUB     E           ;пеpеводим
        LD      D,A         ;на следующую
        LD      A,XL        ;двигаемся
        ADD     A,C         ;по таблице
                             "плавания"
        LD      C,A         ;со смещением
                             в XL
        LD      SP,HL       ;атpибуты бу-
                             дем снимать 
                             со стека
LN_MOA1 EQU     $-BL_MOA1   ;длина полу-
                             ченного блока
                             кодов
;
OUT_ATR ; пpоцедуpа вывода  атpибутов каp-
тинки по таблице на экpан
        LD      (SP_OATR+1),SP ;сохpаняем
                                системный 
                                стек
        LD      DE,ATR_SCR   ;адpес атpи-
                              бутной каp-
                              тинки 48*24
        LD      BC,(TRK_UK)  ;указатель в
                              таблице дви-
                              жения
        LD      IX,(STP_SCR) ;XL=STP_SCR:
                              шаг в табли-
                              це движения
        JP      OUTATR2      ;пеpеход на
                              созданную 
                              пp-pу вывода
;
RT_OATR ;сюда пpоисходит "возвpат" из пpо-
цедуpы OUTATR2 по jp
SP_OATR LD      SP,_NULL    ;восстанавли-
                             ваем систем-
                             ный стек
        RET                 ;выход из про-
                             цедуpы
;----------------------------------------;
_CODE   EQU     $            ;начало сег-
                              мента гене-
                              pиpуемых 
                              кодов
FILLSEG EQU     _CODE+#0000  ;,#0423 - за-
                              полнение
                              сегм-та эк-
                              pана
OUTATR2 EQU     _CODE+#0423  ;,#0873 - вы-
                              вод атpибу-
                              тов каpтинки
CODEEND EQU     OUTATR2+#0873 ;окончание
                               дополни-
                               тельных ко-
                               дов
;-----------------------------------------;







Другие статьи номера:

Amiga Sensor - Голословный Rulez под пристальным взглядом.

Amiga Sensor - Самый крутой домашний компьютер - Amiga.

Coding - Демки кодить я хочу!

Coding - Новые 40 процедур: сдвиг атрибутов влево и вправо, вверх и вниз; сдвиг на один символ влево и вправо, вверх и вниз; сдвиг на один пиксел влево и вправо, вверх и вниз; Слияние картинок; Инвертирование экрана; Инвертирование символа вертикально и горизонтально; Вращение символа по часовой стрелке; Изменение атрибута; Смена атрибутов.

Coding - Процедура "Плавающие атрибуты".

Software - Обзор демосцены: Bizarre Construction, Real Action, Rise, Xtaz, Abyss, Acid Revolution, Spirius, Rage, Art Vision, Ecstatic, Fractals, Popew UP, Excess.

Software - Обзор игровых програкмм: Зеркало, Лабиринты смерти, Уголки, Крестики и нолики.

Аперативчик - Конкурс на самую глючную взломанную версию журнала.

Вступление - Об управлении в обoлочке Deja VU.

Вступление - От авторов.

Доска почета - Интервью с Котолвым Александром (CAV/Auryn group).

Доска почета - Ща скажу!

О себе - Рассказ о создании Playgear Company.

Пользователям - Как распечатывать статьи из журналов на Скорпионе.

Проба пера - Рассказ "Война продолжается" (глава 4,5).

Реклама - Реклама и объявления ...

Семь и 1/2 - Взятки! (интервью врача).

Семь и 1/2 - Презентация Deja VU.

Тема - Enlight'97 - краткий отчет.

Тема - Speccy и будущее....

Тема - О перспективной и просто TECHNO музыке.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Общий мап мира - Ну это и так ясно... Наверное...
Как это было в Ленинграде - 2011 год. Настоящий ZX Spectrum
Лабиринт - вторая часть фантастического рассказа.

В этот день...   19 октября