(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