Miracle #03
16 июля 1999

Кто там кодит? - Быстрая графика: несколько рецептов от Zetter'а (печать спрайтов, обновление экрана).

<b>Кто там кодит?</b> - Быстрая графика: несколько рецептов от Zetter'а (печать спрайтов, обновление экрана).
    (C) ROM corp./VVG,1997
    -----------------------

       Быстрая графика.

    Давно  хотел  рассказать о
графике SPECCY, причем не про-
сто  о  графике,  а  о быстрой
графике, которая применяется в
большинстве  музыкальных DEMO,
а  также  во  многих фирменных
игрушках. В этой статье я хочу
предложить несколько иной под-
ход к решению этих вопросов.

1:Применение метода табличного
программирования   для  печати
спрайтов.

2:Применение печати стеком для
очистки  экрана.  Под очисткой
здесь  понимаются любые дейст-
вия,   ведущие   к   освежению
экранной памяти, в том числе и
заполнение   экрана  спрайтами
любого  формата, создание все-
возможных  сеточек  и  т.д.

    Итак, теперь подробнее обо
всем этом. Я не буду приводить
здесь  все  листинги о которых
будет идти речь, поскольку все
это   довольно  прозрачно,  но
ключевые моменты будут подроб-
но освещены.

      1.ПЕЧАТЬ СПРАЙТОВ

    Все  попытки создать быст-
рую  процедуру  печати спрайта
классическим методом, обречены
на  неудачу  из  за  чудовищно
медленной  работы  вычислителя
адреса  в  экране.  Что же де-
лать?  На помощь приходит таб-
личный метод программирования.
Пусть где-то в памяти находит-
ся  таблица адресов всех линий
экрана, тогда процедура печати
спрайта выглядит так:

    PRINT_SPRITE

          LD H,0          ;В HL ПОМЕЩАЕМ Y КООРДИНАТУ
          LD L,YCOORD     ;НАШЕГО СПРАЙТА
                          ;(В ПИКСЕЛЯХ)
          ADD HL,HL       ;УМНОЖАЕМ ЕЕ НА 2
                          ;ТАК КАК АДРЕС ЗАНИМАЕТ
                          ;2 БАЙТА, ТО НАДО УМНОЖИТЬ
                          ;НА 2 ДЛЯ ПОЛУЧЕНИЯ
                          ;СМЕЩЕНИЯ ОТ ВЕРХА
                          ;ТАБЛИЦЫ
          LD DE,DATA      ;В DE-НАЧАЛО ТАБЛИЦЫ
                          ;АДРЕСОВ
          ADD HL,DE       ;СЛОЖЕНИЕ
          LD (STACK),SP   ;СОХРАНИМ СТЕК
                          ;В ПЕРЕМЕННОЙ
          LD SP,HL        ;ПЕРЕСТАВИМ СТЕК НА
                          ;ТАБЛИЦУ АДРЕСОВ
          LD A,LINES      ;В A-ВЫСОТА СПРАЙТА
                          ;В ПИКСЕЛЯХ

    ;ПОДГОТОВИТЕЛЬНЫЕ ОПЕРАЦИИ ЗАКОНЧЕНЫ,
    ;ТЕПЕРЬ НАЧИНАЕТСЯ СОБСТВЕННО ПЕЧАТЬ

    LOOP  LD BC,XCOORD    ;В BC-КООРДИНАТА X
                          ;СПРАЙТА ОТ ЛЕВОГО КРАЯ
                          ;ЭКРАНА В ЗНАКОМЕСТАХ
          POP DE          ;ВОТ ЭТОЙ КОМАНДОЙ И
                          ;ВЫБИРАЮТСЯ АДРЕСА ИЗ
                          ;ТАБЛИЦЫ
          EX DE,HL        ;СЛОЖЕНИЕ С X
          ADD HL,BC       ;КООРДИНАТОЙ
          EX DE,HL        ;
          LDI             ;ПЕРЕБРОС ЛИНИИ СПРАЙТА
          LDI             ;В ЭКРАН КОМАНДАМИ
                          ;LDI БЫСТРЕЕ ЧЕМ LDIR
          ...             ;НА 5 ТАКТОВ НА БАЙТ
                          ;КОЛИЧЕСТВО КОМАНД
          LDI             ;LDI РАВНО ШИРИНЕ
                          ;СПРАЙТА
          DEC A           ;УМЕНЬШЕНИЕ СЧЕТЧИКА
          JR NZ,LOOP      ;ЛИНИЙ И ПЕРЕХОД
          LD SP,(STACK)   ;ВОССТАНОВЛЕНИЕ СТЕКА
          RET             ;ВОЗВРАТ

    Теперь  посмотрим,  во что
нам  это  обошлось:  384 байта
таблички  и  немного на LDI,но
зато:  печать   независима  от
знакомест  и сегментов экрана,
обладает высочайшей скоростью:
расчет  адреса (или точнее вы-
борка) всего 39 тактов.
ПРИМЕЧАНИЕ:  если  X  равен 0,
можно удалить строки с измене-
нием X (это можно использовать
при scroll-е всего экрана).

Печать  примет  следующий вид:

          POP DE
          LDI
          LDI

          ...

          LDI
          LDI

    Можно  пойти  еще дальше и
раскрыть цикл по A, с'экономив
еще 17 тактов на линию. В этом
варианте  на  байт тратится 16
тактов  и плюс 10 (POP DE) де-
ленное на ширину спрайта. Все-
го  в  среднем около 20 тактов
на байт.

    Вы  можете спросить: а как
же  печать с точностью до пик-
селов по горизонтали? Отвечаю:
можно и до пиксела, но опять с
маленькой  хитростью. Мы будем
печатать спрайт с точностью до
пиксела   по  знакоместам.  Вы
скажете:  глупость  какая! Так
ведь  нет!  Идея заключается в
создании   восьми  фаз  нашего
спрайта  со  сдвигом  на  один
пиксель  и  печать  каждого из
них с точностью до знакоместа.
Алгоритм выглядит так: берется
X  в  пикселях,  делится на 8.
Частное  это  X  координата  в
знакоместах, а остаток это но-
мер  фазы нашего спрайта с со-
ответствующим сдвигом, а далее
просто печать уже знакомой нам
процедуркой

    Теперь  о том, как создать
табличку  адресов.  я  не буду
приводить  листинг, он не сло-
жен,  а опишу алгоритм: берет-
ся любая процедура расчета ад-
реса в пикселях (я использовал
процедуру из Элементарной Гра-
фики). Далее цикл от 0 до 191.
Вычисляем  адрес  и  заносим в
таблицу, увеличиваем указатель
текущего  элемента на 2 и пов-
торяем  все  сначала.  Кстати,
эта  же  табличка может приме-
няться  для  любых  операций с
экраном

      2.ОСВЕЖЕНИЕ ЭКРАНА И СЕТОЧКИ 

Для обеспечения плавной графи-
ки  необходимо  освежать экран
50 раз в секунду. Для этой це-
ли  замечательно подходит сте-
ковый  метод  печати.  У  него
есть   немало  разновидностей.
Рассмотрим некоторые из них.

    1:ОЧИСТКА ЭКРАНА
          LD A,0 (XOR A)  ;ОБНУЛЯЕМ АККУМУЛЯТОР 
          LD H,A          ;ЗАПОЛНЯЕМ HL АККУМУЛЯТОРОМ
          LD L,A          ;(ХОТЯ МОЖНО ИСПОЛЬЗОВАТЬ
                          ;ЛЮБУЮ РЕГИСТРОВУЮ ПАРУ)
          PUSH HL ;ПОВТОРЯЕМ PUSH СТОЛЬКО
          ...             ;РАЗ, СКОЛЬКО НУЖНО 
          PUSH HL ;ДЛЯ ПОЛНОЙ ОЧИСТКИ

Вместо  0 можно засылать любой
другой байт и получать всевоз-
можные полоски на экране.

      3.СЕТОЧКА 8x8

    Из предыдущего пункта лег-
ко   получаются  разнообразные
сеточки на весь экран, которые
так  любят  использовать в де-
мах.   Идея   такова:  берется
спрайтик 8x8 пикселей и с кон-
ца начинается выводится на эк-
ран,  линия за линией. Сущест-
вует несколько способов реали-
зации  этого  эффекта, мы рас-
смотрим  один  из  них.  Пусть
имеется некий спрайтик 8x8pix,
наша  задача  заполнить им эк-
ран.

          LD IX,SPRITE    ;УКАЗАТЕЛЬ НА НАЧАЛО СПРАЙТА
          LD (STACK),SP   ;СОХРАНИМ SP
          LD SP,22528     ;ПЕРЕСТАВИМ SP В КОНЕЦ ЭКРАНА
          LD H,(IX+7)     ;ЗАПОЛНИЛИ HL ПОСЛЕДНИМ
          LD L,H          ;БАЙТОМ СПРАЙТА 
          PUSH HL ; PUSH HL ПОВТОРЯЕТСЯ 128 
          ...             ; >РАЗ ДЛЯ ЗАПОЛНЕНИЯ ВСЕХ
          PUSH HL ;/ НИЖНИХ ЛИНИЙ ЭКРАНА
          LD H,(IX+6)     ;ЗАПОЛНИМ HL ПРЕДПОСЛЕДНИМ
          LD L,H          ;БАЙТОМ
          PUSH HL ;
          ...             ; >PUSH HL*128
          PUSH HL ;/
                          ;ПОВТОРЯЕМ ВСЕ ДЛЯ IX+5,IX+4,
          ...             ;IX+3,IX+2,IX+1
          LD H,(IX+0)     ;И ДЛЯ IX+0
          LD L,H          ;
          PUSH HL ;
          ...             ;
          PUSH HL ;

    ;НИЖНИЙ СЕГМЕНТ ЗАПОЛНЕН.ТЕПЕРЬ НАДО
    ;ПОВТОРИТЬ ВЕСЬ ТЕКСТ ОТ LD H,(IX+7) ДО
    ;КОНЦА ЕЩЕ 2 РАЗА ДЛЯ ЗАПОЛНЕНИЯ ОСТАЛЬНЫХ
    ;СЕГМЕНТОВ ЭКРАНА

          LD SP,(STACK)   ;В КОНЦЕ ВОССТАНОВИМ СТЕК
          RET             ;И ВЕРНЕМСЯ ПО RET

    Вот,  неподвижная  сеточка
на  экране. А как заставить ее
двигаться?  Очень просто: надо
создать  блок спрайтов, содер-
жащих фазы движения сеточки по
экрану.  В данном случае (8x8)
это  будет  обыкновенный фонт,
созданный  в  ARTSTUDIO  или в
другом   редакторе.   Алгоритм
движения   по  файлу  спрайтов
(фонту) очень напоминает нача-
ло  процедуры печати символами
8x8:

          LD A,NUM        ;NUM-ЭТО НОМЕР ТЕКУЩЕГО
                          ;СПРАЙТА
          LD XH,0 ;ЗАГРУЗКА IX ЧЕРЕЗ НЕДОКУ-
          LD XL,A ;МЕНТИРОВАННЫЕ КОМАНДЫ
                          ;ДЛЯ УСКОРЕНИЯ ПРОЦЕССА
          ADD IX,IX       ;УМНОЖЕНИЕ НА 8
          ADD IX,IX       ;     
          ADD IX,IX       ;
          LD DE,SPRITES   ;СЛОЖЕНИЕ С АДРЕСОМ НАЧАЛА
          ADD IX,DE       ;ФАЙЛА СПРАЙТОВ

Полученный  в IX адрес исполь-
зуется в предыдущей процедуре.

    Теперь хотелось бы сказать
о  способах  получения файла с
фазами  движения. Первый и са-
мый   наглядный,  но  и  самый
трудоемкий  это  нарисовать их
(фазы)  в графическом редакто-
ре.  А второй - это сгенериро-
вать  его в процессе инсталля-
ции программы. Рассмотрим идею
инсталляции   поподробнее.   В
самом   крутом   варианте  это
будет  выглядеть  так: имеется
некая  двумерная функция (хоть
та  же  синусоида),  программа
вычисляет  ее график и заносит
его в табличку. Далее програм-
ма  производит  преобразование
таблички  по  модулю  8, а по-
просту оставляет вместо полной
координаты  остаток от деления
ее  на 8. Следующий этап: фор-
мирование  спрайтового  набора
(фонта):   берется   начальный
спрайт,  ротируется(!)  X  раз
вправо, Y раз вниз и заносится
на  очередное место в таблице.
Можно  создать несколько функ-
ций,   и   несколько   наборов
спрайтов,  а  можно объединить
их  по  OR или по другой логи-
ческой  операции для получения
сеточек с несколькими  планами
движения (например: две сеточ-
ки:  одна  движется  вверх,  а
другая по диагонали вниз). Вот
и  готова  сеточка, но если вы
попробуете  ее запустить, даже
через  HALT  то  у  вас ничего
путного  не  выйдет  (хотя вся
печать занимает около половины
INTа  (30000 тактов) из за пе-
ресечения  хода ULA и заполне-
ния стека. Выручает второй эк-
ран  (в  128-х  моделях).  Его
включение  происходит  практи-
чески мгновенно, чем и обеспе-
чивается необходимый эффект.

    LOOP  LD BC,32765     ;ПОДКЛЮЧАЕМ СТРАНИЦУ ВТОРОГО
          LD A,23 ;ЭКРАНА ПРИ ВКЛЮЧЕННОМ
          OUT (C),A       ;ПЕРВОМ ЭКРАНЕ
          CALL PRINT      ;ПЕЧАТЬ 
          HALT            ;СИНХРОНИЗАЦИЯ
          LD BC,32765     ;ПОДКЛЮЧАЕМ СТРАНИЦУ ПЕРВОГО
          LD A,21+8       ;ВОГО ЭКРАНА ПРИ ВКЛЮЧЕННОМ
          OUT (C),A       ;ВТОРОМ ЭКРАНЕ
          CALL PRINT      ;ПЕЧАТЬ
          HALT            ;СИНХРОНИЗАЦИЯ
          JR LOOP ;

Вот и двухэкранная технология.
На  это  дело  можно  повесить
музыку,  спрайты  и  еще,  что
нибудь,  но  надо  следить  за
временем выполнения ,чтобы оно
не  превысило  1 INT. Еще пара
замечаний:  если  используются
спрайты, то  табличку  адресов
необходимо   генерировать  под
адрес  49152  а  не 16384, при
использовании    IM2    вектор
прерываниий  должен  быть ниже
49152, а если выше, то он дол-
жен быть продублирован на всех
использующихся  страницах. Му-
зыка  тоже  желательно  должна
находится  ниже  49152, а если
Вы   хотите   посадить  ее  на
страничку, то придется запоми-
нать число из порта 32765 и не
переключать  экраны  на  время
проигрывания музыки.

    2:СЕТОЧКИ 16x16 

          LD IX,SPRITE    ;УКАЗАТЕЛЬ НА НАЧАЛО СПРАЙТА
          LD (STACK),SP   ;СОХРАНИМ SP
          LD SP,22528     ;ПЕРЕСТАВИМ SP В КОНЕЦ ЭКРАНА
          LD B,(IX+31)    ;В BC ЗАГРУЗИМ ПОСЛЕДНИЙ И
          LD C,(IX+30)    ;ПРЕДПОСЛЕДНИЙ БАЙТЫ СПРАЙТА
          LD D,(IX+15)    ;А В DE ДВА БАЙТА ИЗ СЕРЕДИНЫ
          LD E,(IX+14)    ;СПРАЙТА :15 И 16
          PUSH BC * 16*4 ;НАРИСУЕМ НИЖНЮЮ И СРЕДНЮЮ
          PUSH DE * 16/   ;ЛИНИИ СПРАЙТА В ОДНОЙ
                          ;ТРЕТИ ЭКРАНА
          LD B,(IX+29)    ;ПЕРЕЗАГРУЗИМ РЕГИСТРОВЫЕ
          LD C,(IX+28)    ;ПАРЫ,СМЕСТИВШИСЬ НА ОДНУ
          LD D,(IX+13)    ;ЛИНИЮ ВВЕРХ
          LD E,(IX+12)    ;
          PUSH BC * 16*4 ;НАРИСУЕМ ЕЩЕ 2 ЛИНИИ
          PUSH DE * 16/   ;
          ...             ;БУДЕМ ПРОДОЛЖАТЬ СМЕЩАТЬСЯ
                          ;ВВЕРХ И РИСОВАТЬ
                          ;ПО ДВЕ ЛИНИИ
          LD B,(IX+17)    ;И,НАКОНЕЦ,ЗАГРУЖАЕМ В
          LD C,(IX+16)    ;РЕГИСТРОВЫЕ ПАРЫ БАЙТЫ
          LD D,(IX+1)     ;ИЗ СЕРЕДИНЫ И ИЗ НАЧАЛА
          LD E,(IX+0)     ;СПРАЙТА
          PUSH BC * 16*4 ;
          PUSH DE * 16/   ;

    ;ВСЕ,ОДНА ТРЕТЬ НАРИСОВАНА,ТЕПЕРЬ ОСТАЛОСЬ
    ;ПОВТОРИТЬ ВСЕ ЭТО ЕЩЕ 2 РАЗА ОТ КОМАНДЫ
    ;LD B,(IX+31) И ДО КОНЦА.

          LD SP,(STACK)
          RET

    По   времени  эта  сеточка
занимает   почти  столько  же,
сколько и предыдущая т.е. око-
ло 30000 тактов.  Все вышеска-
занное  насчет движения и соз-
дания  фаз  относится и к этой
разновидности  эффекта, но при
создании функции движения, не-
обходимо  брать остаток от де-
ления  на 16, а не на 8, как в
предыдущем  случае.  Надо ска-
зать, что это довольно универ-
сальный способ печати на экра-
не. Если Вы поняли принцип ра-
боты  описанных выше эффектов,
то  Вам будет нетрудно дорабо-
тать  их  до  других размеров:
3x3, 4x4, 2x4 и т.д.

В заключение хотел бы получить
отзывы   на   этот  материал,а
также  предлагаю свою помощь и
сотрудничество  по всем вопро-
сам,  связанным с программиро-
ванием на ASSEMBLERе.

Мой адрес:

    ┌────────────────────┐
    │  394016,Г.ВОРОНЕЖ  │
    │  УЛ.ТУЛЬСКАЯ,Д.16  │
    │    НАСОНОВУ Р.А.   │
    │    (ROM CORP.)     │
    └────────────────────┘






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

От редакции - Предисловие: С какой целью мы выпускаем журнал?

От редакции - Оболочка: описание новой оболчки к журналу.

От редакции - письма в журнал: Dr.Sioux/Phantom Family, Fistsoft, Mr.Z/HardWave, Куров Н., Eagle/Computer Ratz Group, Rom Corp/Virtual Vision Group.

От редакции - в этом номере: содержание номера.

Проект года - презентация версии игры Robo от KT-soft/ETC.

Проект года - презентация игры от группы Spark: Городки.

Проект года - презентация игры "12 Тайных книг".

Проект года - несколько слов о готовящейся к выходу игре Chip & Dale.

Проект года - потрясающая новелла к игре "Навигатор".

Проект года - Мир тьмы: описание новой real-time strategy.

Погремушки - свежие и не очень, но смачные читы.

Погремушки - крематорий: игра Сталкер - описание всех предметов.

Погремушки - крематорий: Страна мифов - советы спеца.

Основы SWAP'А - информация для начинающих, а также несколько хитрых извратов, которые можно провернуть с почтой.

Кто там кодит? - Быстрая графика: несколько рецептов от Zetter'а (печать спрайтов, обновление экрана).

Кто там кодит? - Packer'ы и Depacker'ы: вся правда о паковщиках, или разглагольствования сэра Kot'а.

Кто там кодит? - Работаем с MS-DOS: Все о mod файлах - полное описание структуры mod-файла, а также описание всех эффектов.

Кто там кодит? - Работаем с MS-DOS: Ms-Dos дискеты - описание структуры Ms-Dos диска.

Кто там кодит? - Chanky flame: описание алгоритма чанкового огня.

Кто там кодит? - Attribute bump mapping: bump mapping для тех кто не въехал.

Кто там кодит? - Гуру медитирует: оптимизация программ по времени исполнения и по размеру.

Кто там кодит? - Приближенный поиск заданной последовательности байт!

Кто там кодит? - Fast 42 print: быстрая процедура печати 42 символов в строке.

Party zone - KidSoft'98: репортаж с Воронежского фестиваля компьютерного искусства.

Party zone - EarthQuake'99: репортаж с Челябинского фестиваля компьютерного искусства.

Я сама - 128 цветов на Spectrum: схема доработки до 128 цветов от донецкой группы Spark.

Я сама - Чайникам: подключение General Sound к Profi через системный разъем.

Я сама - Бесперебойные блоки питания: информация об UPS-технологии.

Я сама - General Sound Filter: рассказ о новой примочке к GS.

Я сама - Модемы: Схемы, схемы! Схемы Г.Шепелева и М.Кондратьева подключения Hayes модема.

Я сама - Модемы: Описание команд - описание команд терминала.

Я сама - Модемы: Тотальная модемизация - призыв к подключению момедов.

Системный софт - FastCopy 3.0: полное описание навороченного турбо-копировщика.

Системный софт - Pro Tracker глюки!!! несколько глючков в ProTracker'ах.

Системный софт - Pro Tracker 3.4 final презентация ремикса Pro Tracker из Самары.

Новости - Челябинск: X-Raizor вернулся на спектрум, Wocen пишет boot, Blade отдахыет, Steelzer вступил в Triumph, Crite доделал альфа версию "Мира тьмы", Bytic купил GS, Edison делает сайт, Ironman хочет купить спектрум.

Новости - Омск: полный состав и ожидаемы продукты от группы U98.

Новости - Калининград: громкая смерть или тихая жизнь Spectrum в Калининграде.

Techno-nature - Электронная музыка: Dj.Ironman рассказывает о техно (часть 1).

Techno-nature - Электронная музыка: Dj.Ironman рассказывает о техно (часть 2).

Techno-nature - Internet music-sites: куча адресов,где можно узнать нового об электронной музыке.

Techno-nature - Наркомания XX: байка от Dj.Ironman'а.

Без четверти четыре - рассказ из повседневной жизни от X-Raizor'а.

Комната смеха - Запахи вокруг и внутри: прикольный рассказ из журнала ПТЮЧ.

Комната смеха - Пердмен: убийственный рассказ из все того-же ПТЮЧ'а.

Комната смеха - Фитиль: неколько сценариев из киножурнала ФИТИЛЬ.

Комната смеха - Ореол: окончание рассказа опубликованного во втором номере.

Прокламация - реклама и обьявления о поиске друзей на спектруме.

Прокламация - реклама и обьявления о поиске друзей на спектруме.


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

Похожие статьи:
Юмор - Девять cектоpов Ада.
С-Week - ICQ интервью с известными ZX товарищами - Arty/Digital Reality и UnBEL!EVER.
Маленькие хитрости-2 - О корректной обработке Retry/Abort/Ignore в TR-DOS.
Презентация - REALSOFT представляет стратегическую игру Technodrom.
Чёртова дюжина неудобных вопросов членам жюри - Игорь Можейко.

В этот день...   27 сентября