ZX Club #07
28 февраля 1998

Coding - техника и алгоритмы демомейкинга: быстрый вывод графики через стек.

<b>Coding</b> - техника и алгоритмы демомейкинга: быстрый вывод графики через стек.
(C) Saruman / Dementia corp. 

 Ну вот  и  прошло  очередное  demo-party,
Enlight-97,  и вновь вылило на головы бед-
ных  юзеров кучу крутейших и навороченней-
ших  демок. А бедный юзер сидит, глядит на
них, и ничегошеньки-то ему не понятно: как
вообще  ТАКОЕ  может быть возможно? А ведь
возможно, и доказательство вот оно - перед
глазами.
 Эта небольшая заметка, возможно, послужит
началом  для цикла статей, в которых я по-
пытаюсь немного рассказать о демомейкинге,
его  техниках и алгоритмах. Я, конечно, не
такой  крутой кодер как Rst7, Max Iwamoto,
Exploder и т.д., но о чем знаю - о том не-
много  расскажу. Я буду дико рад, если моя
работа поможет написанию хоть одной отлич-
ной проги. А поскольку начинать лучше все-
го  с  самого начала, то сегодняшней темой
будет

     Быстрый вывод графики через стек 

                  - Знаете, у меня на эк- 
                    ран выводится 300 
                    спрайтов за одно пре- 
                    рывание, и я не могу 
                    избавиться от мерца- 
                    ния. Помогите! 
                  - Сейчас тебе кто-нибудь
                    посоветует выводить их
                    через стек. ;-) 
                            Из переписки 
                            в FIDO 


 Возможно, читатель,  внимательно следящий
за всеми электронными изданиями, негодующе
воскликнет:  "Сколько  можно об этом гово-
рить ?!?!?" Сколько нужно! Раз еще появля-
ются демы с дрожащими спрайтами и глючащи-
ми  эффектами (а они появляются!), значит,
сказано еще недостаточно.
 Итак, основная  идея,  стоящая  за данным
методом, такова:
  ───────────────┬────────────────────── 
    Команда      Время исполнения 
  ───────────────┼────────────────────── 
  LD A,(reg)             7
  LD (reg),A             7
  INC reg                6
  DEC reg                6
  LD HL,(ADDR)           16
  LD (ADDR),HL           16
  POP reg                10 ! 
  PUSH reg               11 ! 
  LD SP,nnnn             10   
  ───────────────┴────────────────────── 
 Итак, что  мы  видим? Для переброски двух
байтов в нужное место у нас есть три пути:
 а) использовать  регистр A. То есть имеем
    примерно такой кусок кода:
       LD   A,(HL) 
       LD   (DE),A 
       INC  HL 
       INC  DE 
    Итого 26*2=52 такта. Ouch... Многова-
    то!
 б) использовать регистровую пару HL: 
       LD   HL,(ADDR) 
       LD   (ADDR),HL 
    Итого 16+16=32 такта плюс время на из-
    менение ADDR. То есть тоже немало...
 в) использовать операции PUSH и POP: 
       LD   SP,nnnn 
       POP  HL 
        .... 
       LD   SP,nnnn 
       PUSH HL 
        .... 
 Вы скажете:  "Какой  же  это самый лучший
способ, если он занимает аж 41 такт!!!" Но
я  не  зря  поставил  в  коде  многоточия.
Вспомните  действие команд PUSH и POP: при
PUSH  происходит занесение значения из ре-
гистра  в  адрес,  содержащийся  в  SP,  и
уменьшение значения SP на 2; при POP - на-
оборот,  данные  достаются из памяти, а SP
увеличивается. А так как у нас имеется це-
лых  10 регистровых пар, то мы можем уста-
навливать  стек  только  один  раз  для 20
байт. Конечный код выглядит примерно так:

       LD   SP,addr      ;SP=sprite_adr 
       POP  AF           
       POP  BC           ; и 
       POP  DE           ;  т 
       POP  HL           ;   а 
       POP  IX           ;    е 
       POP  IY           ;     м 
       EX   AF,AF'       ;         с 
       EXX               ;        п 
       POP  AF           ;       р 
       POP  BC           ;      а 
       POP  DE           ;     й 
       POP  HL           ;    т 

       LD   (SP_1+1),SP  ; Сохраняем SP 

       LD   SP,addr      ;SP=screen_adr 
       PUSH HL           
       PUSH DE           ; ы 
       PUSH BC           ;  в 
       PUSH AF           ;   о 
       EX   AF,AF'       ;    д 
       EXX               ;     и 
       PUSH IY           ;      м    с 
       PUSH IX           ;          п 
       PUSH HL           ;         р 
       PUSH DE           ;        а 
       PUSH BC           ;       й 
       PUSH AF           ;      т 

       LD   (SP_2+1),SP  ;сохраняем SP 

SP_1   LD   SP,0000      ;SP=sprite_adr 
       ............      ;снова чтение 
       ............      ;данных 

SP_2   LD   SP,0000      ;SP=screen_adr 
       ............      ;снова вывод  
       и т.д.
 Итого получаем  302/10=30.2 тактов на два
байта!
 Как видно,  разница ощутима, особенно при
выводе больших объемов графики. Для дости-
жеия  максимальной скорости лучше обойтись
без всяких циклов, а так и выводить дальше
весь спрайт.
 Теперь расскажу   о   некоторых  полезных
приемах, которые могут вам помочь.
 Нередко, особенно  в демках, картинка со-
стоит из нескольких повторений одной и той
же  ее части. При этом, само собой, доста-
точно  один раз считать эту часть, а затем
выкидывать ее на экран нужное число раз.
 Если вам необходимо вывести спрайт с мас-
кой,  то  часто удобно поступить следующим
образом:  спрайт  хранить в памяти переме-
шанным  с маской, и считывать одновременно
и то, и другое. Пример:
       LD   SP,data_adr  ;адрес спрайта 
       LD   DE,scr_adr   ;адрес экрана 
       POP  BC           ;B=mask, C=sprite
       LD   A,(DE) 
       AND  B            ;A AND mask 
       OR   C            ;A OR sprite 
       LD   (DE),A 
 Именно этот способ, слегка модифицирован-
ный, применяется для вывода курсора в жур-
нале.  Курсор хранится в виде 2_байта_дан-
ных+2_байта_маски.  Перед  выводом маска и
спрайт  сдвигаются  на нужное число битов,
и полученные _ТРИ_ байта спрайта бросаются
на  экран.  Как  видите,  все работает без
мерцаний и глюков!
 Да, кстати, все вещи, которые могут нахо-
диться в любом месте экрана и при этом еще
и  двигаться (различные курсоры, прыгающие
смайлики  и т.п.), необходимо выводить са-
мыми  первыми, до проигрывания музыки, пе-
ресчета  координат и т.д. Иначе, даже если
у вас все работает отлично, может попасть-
ся какой-нибудь тормозной комп, где спрайт
начнет  дрожать и мерцать. Не забывайте об
этом!
 А засим  я на сегодня прощаюсь, если воз-
никнут  какие-либо  вопросы, пожелания или
предложения,  то  вы  можете  связаться со
мной по телефону 54-01-70 (спросить Олега)
или  же  по адресам, приведенным в разделе
"От редакции". Bye!!! 
_______________________________________End



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

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

Новости - Как обстоят дела с организацией барнаульской Spectrum сети.

Новости - Олимпиада'97 по информатике или размышления по окончании.

Games - Описание игры "NIGEL MANSELL WORLD CHAMPIONSHIP".

User group - Обзор музыкальных редакторов: WHAM+AY, ASM, SUPER SONIC, SOUND TRACKER v1.1, STD v2.01, STR v3.00, SOUND TRACKER PRO, PRO TRACKER и утилит: S.T. COMPILER, S. T. RECOMPILER, S.T. MUSIC STEALER, S.T.REC++ , FLASH DECOMPILER.

Coding - техника и алгоритмы демомейкинга: быстрый вывод графики через стек.

Ex Libris - Одиночество - краткий конспект.

Ex Libris - Экзистенциализм - краткий конспект.

Ex Libris - пресса: Для чего нужны книги?

Hard group - Расширение памяти компьютера "Синтез-2" до 128 Кб.

Enjoy - Сказка про Салтана.

Enjoy - Рассказ "Учитесь стрелять".

Реклама - бесплатная реклама и обьявления.


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

Похожие статьи:
Юмор - Краткий репортаж С празнования нового года Smash'овцами.
INTRO - Создание К. Синклером компьютера ZX-2000.
Обратная связь - контакты редакции.
От авторов - вступление.
Sofтинка - обзор экранных упаковщиков для ZX Spectrum.

В этот день...   18 апреля